JDK-8021372 : NetworkInterface.getNetworkInterfaces() returns duplicate hardware address
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 6u43,7u25,8
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_2008
  • Submitted: 2013-07-25
  • Updated: 2022-12-01
  • Resolved: 2013-09-09
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 7 JDK 8
7u66Fixed 8 b108Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
java version  " 1.6.0_26 " 
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) Server VM (build 20.1-b02, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Windows Server 2008 R2

EXTRA RELEVANT SYSTEM CONFIGURATION :
the OS is hosted in a VM

A DESCRIPTION OF THE PROBLEM :
MAC Addresses of the network interfaces in the VM is retrieved by calling the following method NetworkInterface.getNetworkInterface().getHardwareAddress():

The Physical machine has two network adapters. and therefore upon executing  " ipconfig /all "  command in the windows command prompt, there are two network adapters that can be observed with distinct IP Address and Physical Address.

however, upon executing the above code at the problematic VMs, the system out shows similar Mac Address or Hardware Address for the two network adapters is returned, but the distinct IP Addresses for each network adapters are correctly returned.

The behavior is observed in 3 out of 4 VMs, but only 1 VM behaves as expected i.e. the MAC Address is returned correctly.
Each VM resides on a separate physical machine.

All of the 4 VMs have the same network setup. and there is no change to the system or OS patches that is related to networking.

Noted that this is similar to the following cases, but please kindly relook into the matters:
1. JDK-6709430 : Unable to detect MAC address in Windows Vista
2. JDK-6763420 : NetworkInterface.getNetworkInterfaces() returns duplicate

REGRESSION.  Last worked in version 6u43

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Refer to the Description above.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The MAC Address or hardware address of the network adapter is returned correctly, according to that returned upon executing  " ipconfig /all "  command in Windows Command Prompt.
ACTUAL -
Refer to Description above.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Refer to Description above.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
---------- BEGIN SOURCE ----------
package com.isprint.am.util;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 *
 */
public class NetUtil {
    
    /** Utility class has no object instance */
    private NetUtil() {
    }
    
    /**
     * Execute the 'hostname' command to get local host name; this is more reliable than the host name from the network interfaces
     * @return
     * @throws IOException
     */
    public static String getExecHostName() throws IOException {
        Process proc = Runtime.getRuntime().exec( " hostname " );
        if(proc!=null) {
            StringBuffer s = new StringBuffer();
            byte[] b = new byte[256];
            int k;
            InputStream in = proc.getInputStream();
            while((k=in.read(b))>-1) {
                s.append(new String(b, 0, k));
            }
            k = s.indexOf( " \r
 " );
            if(k<0) k = s.indexOf( " 
 " );
            if(k<0) k = s.length();
            return s.substring(0, k);
        }
        return null;
    }

    /**
     * Only avail in JRE1.6 so we test with reflection
     * @param ni
     * @return
     */
    public static byte[] getHardwareAddrIfAvail(NetworkInterface ni) {
        try {
            Method meth = ni.getClass().getDeclaredMethod( " getHardwareAddress " , new Class[0]);
            byte[] mac = (byte[])meth.invoke(ni, new Object[0]);
            return mac;
        } catch (NoSuchMethodException e) {
            //jre 1.5 and below; ignore
            return new byte[0];
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
    
    public static void main(String[] args) throws IOException {
    Enumeration nis = NetworkInterface.getNetworkInterfaces();
    System.out.println( " 
Hostname:  " +getExecHostName()+ " 
 " );
    while (nis.hasMoreElements()) {
    System.out.println( " ********************************** " );
    NetworkInterface ni = (NetworkInterface)nis.nextElement();
    System.out.println( " NetworkInterface displayName= "  + ni.getDisplayName()+ "  name= " +ni.getName()+'
');
            Enumeration addrs = ni.getInetAddresses();
while (addrs.hasMoreElements()) {
InetAddress addr = (InetAddress) addrs.nextElement();
System.out.println( "   canonicalHostName= " 
+ addr.getCanonicalHostName() +  "  hostName= " 
+ addr.getHostName() +  "  hostAddr= " 
+ addr.getHostAddress() +  " , loopback= " 
+ addr.isLoopbackAddress() +  "  linkLocal= " 
+ addr.isLinkLocalAddress() + '
');
byte[] macAddress = getHardwareAddrIfAvail(ni);
//System.out.println( " macAddress - getHardwareAddress - reflection:  " +EncodingUtil.hexBinEncodeAsString(macAddress).toString());
//System.out.println( " macAddress - getHardwareAddress - method:  " +EncodingUtil.hexBinEncodeAsString(ni.getHardwareAddress()).toString());
byte[] mac = ni.getHardwareAddress();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < mac.length; i++) {
            sb.append(String.format( " %02X%s " , mac[i], (i < mac.length - 1) ?  " - "  :  "  " ));
        }
        System.out.println( " macAddress - getHardwareAddress - method - other format:  " +sb.toString());

}
    }
    }
}

---------- END SOURCE ----------
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
For the affected VMs, at the point of detection of the MAC Address or hardware address of the machine, the second network adapter is disabled.
It is then enabled back after the MAC Address detection is not required anymore.
Comments
Attached regression test passed, verified in b120
13-12-2013

URL: http://hg.openjdk.java.net/jdk8/jdk8/jdk/rev/4fd7abaf0a5f User: lana Date: 2013-09-18 00:31:25 +0000
18-09-2013

URL: http://hg.openjdk.java.net/jdk8/tl/jdk/rev/4fd7abaf0a5f User: chegar Date: 2013-09-09 12:45:41 +0000
09-09-2013

the essence of the problem, at least in my windows environment, is that the ipv6_available() returns true. This means that the processing via the IPV6 oriented functions in NetworkInterface_winXP.c In this context it is the handling of the IfIndex and the Ipv6IfIndex from the IP_ADAPTER_ADDRESSES structure and its representation in the netif structure. The documentation informs us that if the adapter doesn't support IPV4 then the IfIndex will be 0 and if it doesn't support IPv6 then the Ipv6IfIndex will be 0. The code handling the IPV4 (in the context of IPv6 enablement) sets the index in the netif to that of Ipv6IfIndex and hence zero. Thus all adapters are returning a default adapter mac address i.e. the first on the returned adapter list. That is, when the native method getMacAddress0() is invoked the processing logic is checking against IPV6 values, rather than taking into account that the adapter is IPV4, with the result the mac address for the same adapter 0 is retrieved each time continuing testing and further investigation. None of the adapters are IPV6 so will need to verify against this scenario.
29-08-2013

exploring this issue further the problem appears to lie in the XP processing code and the fact that ipv6_available() returns true. The getAllAddressesAndInterfaces, and during the processing of the retrieved adapters the index in the nif structure is set to an Ipv6IfIndex from the IP_ADAPTER_ADDRESSES. This appears to be 0 or default adapter. This will cause the default interface's MAC address to be returned for each interface. Investigation continues. a form of workaround for my test is to enable java.net.preferIPv4Stack boolean property and the correct MAC address is obtained
28-08-2013

Ran the sample NetUtil, and the problem appears to be that the invocation of the NetworkInterface.getHardwareAddress() in turn invokes the native method getMacAddr0 with the same index for each of the interfaces. The getMacAddr0 will typically call getIF for each of the interfaces with the same index. The index is set during the instantiation of the NetworkInterfaces via the getNetworkInterfaces method and its call on getAll. For the interfaces with an IP address bound, the index comes back as 0. As other interfaces (non IP addresses) has a valid index - there are 40 returned on my laptop, and those in the sequence with an IP address have each an index of 0. This afaik is data reterived from the OS via a network utils API. This is on a windows 7 machine with virtualization enabled, and using jdk7.0-25 the network interface data comes from GetIfTable and from the GetFriendlyIfIndex - So, do we have a bug in the MS network API functions If the following line in the test code above is amended System.out.println( " NetworkInterface displayName= " + ni.getDisplayName()+ " name= " +ni.getName()+'\n'); with System.out.println( " NetworkInterface displayName= " + ni.getDisplayName()+ " name= " +ni.getName()+ " index= " + ni.getIndex + '\n'); I think we may see that this is index = 0 for both In my case there are 3 network interfaces bound with an IP address, and they each return index == 0 "route print" from a cmd prompt window will provide output such as: C:\Users\msheppar>route print =========================================================================== Interface List 18...00 05 9a 3c 7a 00 ......Cisco AnyConnect VPN Virtual Miniport Adapter for Windows x64 16...60 67 20 04 1d 70 ......Intel(R) Centrino(R) Advanced-N 6205 14...00 21 cc c9 c1 cb ......Intel(R) 82579LM Gigabit Network Connection 23...08 00 27 00 c0 6b ......VirtualBox Host-Only Ethernet Adapter 1...........................Software Loopback Interface 1 =========================================================================== This shows the index on the left most column, these are coming back as 0 via getNetwokInterfaces()
26-08-2013