[
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: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]