JDK-8004675 : Inet6Address.getHostAddress should use string scope identifier where available
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 7u9,8
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: os_x
  • CPU: x86
  • Submitted: 2012-12-06
  • Updated: 2013-11-01
  • Resolved: 2012-12-13
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 8
8 b69Fixed
Related Reports
Relates :  
Relates :  
Description
J2SE Version (please include all output from java -version flag):
java version "1.7.0_09"
Java(TM) SE Runtime Environment (build 1.7.0_09-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02, mixed mode)


Does this problem occur on J2SE 6ux or 7ux?  Yes / No (pick one)
6: probably
7u9: yes
7u12: yes


Operating System Configuration Information (be specific):
Darwin macbook-retina.speedport.ip 12.2.1 Darwin Kernel Version 12.2.1: Thu Oct 18 16:32:48 PDT 2012; root:xnu-2050.20.9~2/RELEASE_X86_64 x86_64


Hardware Configuration Information (be specific):
Macbook Pro Retina 15"


Bug Description:

scope_ifname_set field not set correctly.

The problem occurs in two scenarios:
1. When iterating over all InetAddresses returned by NetworkInterface class on OS X (not tested on Win nor Linux)
2. When deserializing Inet6Address (bug in readObject() method)

java.net.Inet6Address#readObject() does not set field scope_ifname_set on deserialization even if network interface name could be verified.

Even though the field ifname is set, the field scope_ifname_set is not set to true, which prevents the interface name to be returned in getHostAddr().

This is even true for all Inet6Addresses returned by java.net.NetworkInterface#getNetworkInterfaces on OS-X. Means: all Inet6Addresses have the field scope_ifname_set==false but the field ifname contains the correct interface name.
Seems that the following line should be added before the current line #429 in java/net/Inet6Address.java :
	scope_ifname_set = true;
so that the try-catch looks like:
                    try {
                        scope_id = deriveNumericScope (scope_ifname);
                        scope_ifname_set = true;
                    } catch (UnknownHostException e) {
                        // typically should not happen, but it may be that
                        // the machine being used for deserialization has
                        // the same interface name but without IPv6 configured.
                    }



Steps to Reproduce (be specific):



import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;

public class Jdk7NoIfname {

    public static void main(String args[]) throws SocketException {
        for (Enumeration<NetworkInterface> e = NetworkInterface.getNetworkInterfaces(); e.hasMoreElements(); ) {
            NetworkInterface iface = e.nextElement();
            for (Enumeration<InetAddress> iadrs = iface.getInetAddresses(); iadrs.hasMoreElements(); ) {
                InetAddress iadr = iadrs.nextElement();
                if (iadr instanceof Inet6Address) {
                    Inet6Address i6adr = (Inet6Address) iadr;
                    System.out.println(iadr);
                    System.out.println("  scoped iface: "+i6adr.getScopedInterface());
                }
            }
        }
    }
}



The output produces 
/fe80:0:0:0:426c:8fff:fe3a:ba79%6
  scoped iface: name:en2 (en2)
/0:0:0:0:0:0:0:1
  scoped iface: null
/fe80:0:0:0:0:0:0:1%1
  scoped iface: name:lo0 (lo0)

But the output should look like this
/fe80:0:0:0:426c:8fff:fe3a:ba79%en2
  scoped iface: name:en2 (en2)
/0:0:0:0:0:0:0:1
  scoped iface: null
/fe80:0:0:0:0:0:0:1%lo0
  scoped iface: name:lo0 (lo0)


Comments
SQE verified and closed. The attached regression test reflects described issue and has not been failed for more then 2 weeks.
01-11-2013

In fact a better solution is to simply remove the 'scope_ifname_set' field from Inet6Address and determine, in the internal implementation, if 'scope_ifname' set by comparing it to null. This should resolve the problem of deserializing as well as addresses returned by NetworkInterface. A partial diff shows: @Override public String getHostAddress() { String s = numericToTextFormat(ipaddress); - if (scope_ifname_set) { /* must check this first */ + if (scope_ifname != null) { /* must check this first */ s = s + "%" + scope_ifname.getName(); } else if (scope_id_set) { s = s + "%" + scope_id; ... and so on
07-12-2012

There is certainly an issue here. Most likely more than one! Taking the testcase in the description for example. The NetworkInterface instances being constructed on the system should have their enclosing Inet6Addresses constructed, or otherwise, with scope_ifname_set to true. The following simple patch resolves this. diff -r 72d3d07b625d src/solaris/native/java/net/NetworkInterface.c --- a/src/solaris/native/java/net/NetworkInterface.c Fri Nov 30 11:18:16 2012 +0000 +++ b/src/solaris/native/java/net/NetworkInterface.c Fri Dec 07 12:08:56 2012 +0000 @@ -683,11 +683,11 @@ jobject createNetworkInterface(JNIEnv *e (jbyte *)&(((struct sockaddr_in6*)addrP->addr)->sin6_addr)); scope = ((struct sockaddr_in6*)addrP->addr)->sin6_scope_id; - if (scope != 0) { /* zero is default value, no need to set */ (*env)->SetIntField(env, iaObj, ia6_scopeidID, scope); (*env)->SetBooleanField(env, iaObj, ia6_scopeidsetID, JNI_TRUE); (*env)->SetObjectField(env, iaObj, ia6_scopeifnameID, netifObj); + (*env)->SetBooleanField(env, iaObj, ia6_scopeifnamesetID, JNI_TRUE); } (*env)->SetObjectField(env, iaObj, ni_ia6ipaddressID, ipaddress); } Then there is the issue of deserialized instances. This needs further investigation.
07-12-2012