Thanks for the feedback.

yes, we can merge the conditional,
that was my comment about the getAdapter function and the if else statement
because of a spurious IPv4 comment.

the 267(old) and 281(new) is the core of the issue

old

262                     if (nif->index == index) {
 263                         /* found the interface entry
 264                          * set the index to the IPv6 index and add the
 265                          * IPv6 addresses
 266                          */
 267                         nif->index = ptr->Ipv6IfIndex;
 268                         c = getAddrsFromAdapter(ptr, &nif->addrs);
 269                         nif->naddrs += c;
 270                         break;
 271                     }

new

276                     if (nif->index == index) {
 277                         /* found the interface entry
 278                          * set the index to the IPv6 index and add the
 279                          * IPv6 addresses
 280                          */
 281                         nif->ipv6Index = ptr->Ipv6IfIndex;
 282                         c = getAddrsFromAdapter(ptr, &nif->addrs);
 283                         nif->naddrs += c;
 284                         break;
 285                     }

the nif->index is already set in the IPv4 case, hence if (nif->index == index) .
In the original code the assignment was overwriting this value with
Ipv6IfIndex, but this can be zero, if IPv6 is not available for that adapter, 
but IPv6 is enabled in the OS.
Hence, NetworkInterface.getHardwareAddress returns the physical address 
associated with index 0.
When, both IPv4 and IPv6 are configured for an interface then this discrepancy
is not seen.
As netif has an ipv6Index member, the Ipv6IfIndex assignment seemed appropriate.

This is then supplemented with an additional check against the Ipv6IfIndex 
member of IP_ADAPTER_ADDRESSES when checking
the index.

when both IPv4 and IPv6 are available on an interface, then the index should be 
the same.
As such, an OS can be enabled for both IPv4 and IPv6, while an interface may be 
configured for
IPv4 only, which coincidentally was how I managed to reproduce the issue!

regards
Mark

On 03/09/2013 11:27, Michael McMahon wrote:
On 03/09/13 10:45, Dmitry Samersoff wrote:
Mark,

1. If I read the code correctly,

ll. 168 - 177 is exactly the same as ll. 180 - 189

Could you refactor the fix to avoid code duplication?

Would something like

if (
    (ptr->IfIndex != 0 && ptr->IfIndex == index) ||
    (ptr->Ipv6IfIndex != 0 && ptr->Ipv6IfIndex == index)
) {
...
}

work?

I think this makes sense.

Also, I'm not sure I understand the purpose of the change
at line 267 (old) 281 (new). What the old code seemed to be doing
was interpreting an IPv6 index as actually an IPv4 one.
Was that not correct? This code is rather brittle unfortunately
and not the easiest to understand.

Michael




2. It seems to me passed index couldn't be 0 so null check is redundant,
but I don't mind to keep it.
It might make sense to explicitly check passed index for 0 above loop.

-Dmitry



On 2013-09-03 13:23, Mark Sheppard wrote:
Hi
please oblige and review the fix below to address the issue in JDK-8021372: NetworkInterface.getNetworkInterfaces() returns duplicate hardware address

http://cr.openjdk.java.net/~msheppar/8021372/webrev/

the handling of the Ipv6IfIndex was suspect when setting the
interface index and when retrieving the mac address using the index.

in the getAdpaters function, the conditaionalstatement could be rolled
into one.
But, as there was a spurious IPv4 comment, I structured it as an if
else. statement.

It should be noted that IfIndex and the Ipv6IfIndex can be zero, which
implies that the
IPv4 or IPv6 interface is not available. This may be at odds with the
setting of a default index to 0 in the Java NetworkInterface abstraction,
where a defaultIndex of zero is used.

JPRTs have been run and show no side effects.

regards
Mark



Reply via email to