[ 
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]

Reply via email to