[ https://issues.apache.org/jira/browse/JCS-40?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12626199#action_12626199 ]
Niall Gallagher commented on JCS-40: ------------------------------------ Thanks Aaron. Regarding testing- yes I know testing this is almost impossible, unless there's multiple OS test environments available (unlikely). I can tell you that the method works for us with: - static IPs on Linux - DHCP on Linux - DHCP on Windows We've not tested it with static IPs on Windows as our servers are Linux, but logically it should work in that environment too. > 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: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]