FULL PRODUCT VERSION :
denis@unit-240:~/dev/jdk/jdk1.7.0/bin$ ./java -version
java version "1.7.0"
Java(TM) SE Runtime Environment (build 1.7.0-b147)
Java HotSpot(TM) 64-Bit Server VM (build 21.0-b17, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
denis@unit-240:~/work/ultimate/community$ uname -a
Linux unit-240.mydomain.net 2.6.38-10-generic #46-Ubuntu SMP Tue Jun 28 15:07:17 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
It looks like name of the local host is resolved incorrectly in case of particular network setup. The problem is that that setup is de-facto standard for Ubuntu environment.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Consider the following 'hosts' file setup (default for Ubuntu):
127.0.0.1 localhost
127.0.1.1 unit-240.mydomain.net unit-240
The task is to get fully-qualified name of the current host ('unit-240.mydomain.net'). Following code is assumed to solve that according to the java.net.* API:
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = interfaces.nextElement();
Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress address = addresses.nextElement();
System.out.println(address.getCanonicalHostName());
}
}
It was expected that 'getCanonicalHostName()' returns expected value ('unit-240.mydomain.net') for one of the addresses. However, it never occurs. The problem is that java.net.InetAddress.getHostFromNameService() uses the following algorithm:
1. Perform reverse lookup (address -> name);
2. Perform system-specific lookup (name -> address) for the resolved name. Here 'hosts' file comes into play - it returns address of 127.0.0.1 that doesn't match to the original address. So, resolved name is considered to be 'spoofed' and is not returned to the calling code.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Fully qualified host name may be retrieved via standard API offered by java.net.*
ACTUAL -
Fully qualified host name may not be retrieved in case of particular system setup.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Suggested solution: modify java.net.InetAddress.getHostFromNameService() in a way to avoid 'dns spoof' check for local addresses.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package org;
import java.net.*;
public class Test {
public static void main(String[] args) throws Exception {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = interfaces.nextElement();
Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress address = addresses.nextElement();
System.out.println(address.getCanonicalHostName());
}
}
}
}
Static name-address mappings file ('hosts') should contain entry that maps 127.0.0.1 to the fq-host name. Example:
127.0.1.1 unit-240.mydomain.net unit-240
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Use InetAddress.getLocalHost().getCanonicalHostName() if the code above doesn't provide an expected result
denis@unit-240:~/dev/jdk/jdk1.7.0/bin$ ./java -version
java version "1.7.0"
Java(TM) SE Runtime Environment (build 1.7.0-b147)
Java HotSpot(TM) 64-Bit Server VM (build 21.0-b17, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
denis@unit-240:~/work/ultimate/community$ uname -a
Linux unit-240.mydomain.net 2.6.38-10-generic #46-Ubuntu SMP Tue Jun 28 15:07:17 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
It looks like name of the local host is resolved incorrectly in case of particular network setup. The problem is that that setup is de-facto standard for Ubuntu environment.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Consider the following 'hosts' file setup (default for Ubuntu):
127.0.0.1 localhost
127.0.1.1 unit-240.mydomain.net unit-240
The task is to get fully-qualified name of the current host ('unit-240.mydomain.net'). Following code is assumed to solve that according to the java.net.* API:
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = interfaces.nextElement();
Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress address = addresses.nextElement();
System.out.println(address.getCanonicalHostName());
}
}
It was expected that 'getCanonicalHostName()' returns expected value ('unit-240.mydomain.net') for one of the addresses. However, it never occurs. The problem is that java.net.InetAddress.getHostFromNameService() uses the following algorithm:
1. Perform reverse lookup (address -> name);
2. Perform system-specific lookup (name -> address) for the resolved name. Here 'hosts' file comes into play - it returns address of 127.0.0.1 that doesn't match to the original address. So, resolved name is considered to be 'spoofed' and is not returned to the calling code.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Fully qualified host name may be retrieved via standard API offered by java.net.*
ACTUAL -
Fully qualified host name may not be retrieved in case of particular system setup.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Suggested solution: modify java.net.InetAddress.getHostFromNameService() in a way to avoid 'dns spoof' check for local addresses.
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package org;
import java.net.*;
public class Test {
public static void main(String[] args) throws Exception {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = interfaces.nextElement();
Enumeration<InetAddress> addresses = networkInterface.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress address = addresses.nextElement();
System.out.println(address.getCanonicalHostName());
}
}
}
}
Static name-address mappings file ('hosts') should contain entry that maps 127.0.0.1 to the fq-host name. Example:
127.0.1.1 unit-240.mydomain.net unit-240
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Use InetAddress.getLocalHost().getCanonicalHostName() if the code above doesn't provide an expected result