jakarta-jcs-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Aaron Smuts (JIRA)" <j...@apache.org>
Subject [jira] Resolved: (JCS-40) InetAddress.getLocalHost() ambiguous on Linux systems
Date Wed, 27 Aug 2008 16:49:44 GMT

     [ https://issues.apache.org/jira/browse/JCS-40?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]

Aaron Smuts resolved JCS-40.
----------------------------

    Resolution: Fixed

This will be in the next temp build, 1.3.2.0-RC

> InetAddress.getLocalHost() ambiguous on Linux systems
> -----------------------------------------------------
>
>                 Key: JCS-40
>                 URL: https://issues.apache.org/jira/browse/JCS-40
>             Project: JCS
>          Issue Type: Bug
>    Affects Versions: jcs-1.3
>         Environment: Linux and other *nix systems
>            Reporter: Niall Gallagher
>            Assignee: Aaron Smuts
>   Original Estimate: 1h
>  Remaining Estimate: 1h
>
> Per JDK bug http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4665037
> ...InetAddress.getLocalHost() is ambiguous on Linux systems. JCS uses this method. We
have found that the issue breaks JCS networking on Linux/*nix systems (tested on Fedora, Red
Hat and CentOS) configured with both static and DHCP-assigned IP addresses. The only workarounds
we can find either do not 100% fix the problem, or require non-optimal configuration of the
OS loopback connection.
> Background:
> On Windows the address returned by InetAddress.getLocalHost() is fairly consistent; typically
the server's LAN address. On Windows systems with multiple network cards (e.g. Internet, WAN,
LAN, VPN, multi-homed), the address returned is ambiguous however.
> On Linux, the address returned by InetAddress.getLocalHost() seems to depend on the order
in which the OS lists network interfaces, which really should be irrelevant. Furthermore the
behaviour can vary between Linux distributions. Linux always exposes the loopback address
(127.0.0.1) as a virtual network card, as if it was a physical NIC. On servers using DHCP,
the method usually returns the loopback address. On servers configured with static IP addresses,
depending on OS ordering, the method sometimes returns the LAN address but sometimes returns
the loopback (127.0.0.1) address.
> InetAddress.getLocalHost() makes no attempt to prioritize LAN/non-loopback addresses
in its selection.
> Impact on JCS:
> This affects networking in JCS in general. e.g. remote cache and lateral cache. JCS can
bind to the loopback interface (127.0.0.1) instead of the LAN address, or the RMI system can
advertise the wrong (127.0.0.1) IP address to clients when sending events. We use the JCS
remote cache server, and saw both of these issues on Fedora, Red Hat and CentOS machines configured
with static and DHCP-assigned addresses.
> We first tried various workarounds:
> -setting system property java.rmi.server.hostname=x.x.x.x
> --> JCS overrides this by supplying an invalid (127.0.0.1) IP address to the RMI subsystem
explicitly
> -changing the IP address associated with localhost in /etc/hosts file from 127.0.0.1
to the machines LAN address
> -->reduces the performance of inter-process (loopback) communication on the server
> In the end we modified the JCS source code, and we have been running it flawlessly for
the past 8 months. The fix requires JDK 1.4. Can we therefore get it integrated into the next
1.4 release of JCS?
> JCS uses InetAddress.getLocalHost() in the following classes:
> org/apache/jcs/auxiliary/lateral/socket/tcp/discovery/UDPDiscoveryService.java
> org/apache/jcs/auxiliary/remote/server/RemoteCacheStartupServlet.java
> org/apache/jcs/utils/net/HostNameUtil.java
> We updated UDPDiscoveryService and RemoteCacheStartupServlet to not call InetAddress.getLocalHost()
directly, but to call the getLocalHostAddress() method in HostNameUtil instead.
> We then changed the implementation of HostNameUtil.getLocalHostAddress() as follows:
>     public static String getLocalHostAddress() throws UnknownHostException {
>         return getLocalHostLANAddress().getHostAddress();
>     }
>     /**
>      * Returns an <code>InetAddress</code> object encapsulating what is most
likely the machine's LAN IP address.
>      * <p/>
>      * This method is intended for use as a replacement of JDK method <code>InetAddress.getLocalHost</code>,
because
>      * that method is ambiguous on Linux systems. Linux systems enumerate the loopback
network interface the same
>      * way as regular LAN network interfaces, but the JDK <code>InetAddress.getLocalHost</code>
method does not
>      * specify the algorithm used to select the address returned under such circumstances,
and will often return the
>      * loopback address, which is not valid for network communication. Details
>      * <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4665037">here</a>.
>      * <p/>
>      * This method will scan all IP addresses on all network interfaces on the host machine
to determine the IP address
>      * most likely to be the machine's LAN address. If the machine has multiple IP addresses,
this method will prefer
>      * a site-local IP address (e.g. 192.168.x.x or 10.10.x.x, usually IPv4) if the machine
has one (and will return the
>      * first site-local address if the machine has more than one), but if the machine
does not hold a site-local
>      * address, this method will return simply the first non-loopback address found (IPv4
or IPv6).
>      * <p/>
>      * If this method cannot find a non-loopback address using this selection algorithm,
it will fall back to
>      * calling and returning the result of JDK method <code>InetAddress.getLocalHost</code>.
>      * <p/>
>      *
>      * @throws UnknownHostException If the LAN address of the machine cannot be found.
>      */
>     private static InetAddress getLocalHostLANAddress() throws UnknownHostException {
>         try {
>             InetAddress candidateAddress = null;
>             // Iterate all NICs (network interface cards)...
>             for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();)
{
>                 NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
>                 // Iterate all IP addresses assigned to each card...
>                 for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();)
{
>                     InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
>                     if (!inetAddr.isLoopbackAddress()) {
>                         if (inetAddr.isSiteLocalAddress()) {
>                             // Found non-loopback site-local address. Return it immediately...
>                             return inetAddr;
>                         }
>                         else if (candidateAddress == null) {
>                             // Found non-loopback address, but not necessarily site-local.
>                             // Store it as a candidate to be returned if site-local address
is not subsequently found...
>                             candidateAddress = inetAddr;
>                             // Note that we don't repeatedly assign non-loopback non-site-local
addresses as candidates,
>                             // only the first. For subsequent iterations, candidate will
be non-null.
>                         }
>                     }
>                 }
>             }
>             if (candidateAddress != null) {
>                 // We did not find a site-local address, but we found some other non-loopback
address.
>                 // Server might have a non-site-local address assigned to its NIC (or
it might be running
>                 // IPv6 which deprecates the "site-local" concept).
>                 // Return this non-loopback candidate address...
>                 return candidateAddress;
>             }
>             // At this point, we did not find a non-loopback address.
>             // Fall back to returning whatever InetAddress.getLocalHost() returns...
>             InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
>             if (jdkSuppliedAddress == null) {
>                 throw new UnknownHostException("The JDK InetAddress.getLocalHost() method
unexpectedly returned null.");
>             }
>             return jdkSuppliedAddress;
>         }
>         catch (Exception e) {
>             UnknownHostException unknownHostException = new UnknownHostException("Failed
to determine LAN address: " + e);
>             unknownHostException.initCause(e);
>             throw unknownHostException;
>         }
>     }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: jcs-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jcs-dev-help@jakarta.apache.org


Mime
View raw message