Summary
-------
Refresh the native parts of NetworkInterface class on Windows
Problem
-------
There are currently 2 distinct functional implementations. One is based on pre-WinXP APIs, the other on is based on WinXP APIs. The former is used when user defines system property `java.net.preferIPv4Stack=true` and can't deal with IPv6, the latter is slow and hard to use. None of them provides persistent interface names; names are generated based on interface position in iteration order, and can change when the application is running.
Solution
--------
Reimplement NetworkInterface using the new APIs introduced in Windows Vista, and use persistent interface names offered by the system.
The current implementation assigns names based on interface type and position in iteration order:
```
switch (ifrowP->dwType) {
case MIB_IF_TYPE_ETHERNET:
_snprintf_s(dev_name, 8, _TRUNCATE, "eth%d", eth++);
break;
case MIB_IF_TYPE_TOKENRING:
_snprintf_s(dev_name, 8, _TRUNCATE, "tr%d", tr++);
break;
...
```
This produces names like `eth0`, `ppp0` or `wlan0`. All loopback interfaces were merged under the name `lo`, which was a mixed blessing, see [JDK-6798979](https://bugs.openjdk.org/browse/JDK-6798979).
The new implementation assigns names based on system-provided interface identifier (LUID):
```
// set the NetworkInterface's name
apiRetVal = ConvertInterfaceLuidToNameW(
&(ifRow->InterfaceLuid), ifName, NDIS_IF_MAX_BUFFER_SIZE);
```
This produces names like `ethernet_32768`, `ppp_32768`, `wireless_32768` or `loopback_0`. There's no overlap between the old and the new namespace.
The existing naming scheme is not predictable (except for the `lo` interface), so it's unlikely that existing code stores interface names and reuses them. The more common use case is that the code enumerates all interfaces and picks instances out based on other characteristics like the interface address. That use case won't be affected by this change.
The interface names are used in the following places:
- Method [NetworkInterface.getByName](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/net/NetworkInterface.html#getByName(java.lang.String)) accepts the interface name and returns a NetworkInterface. It returns null if there's no interface with the specified name.
- Methods [InetAddress.getByName](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/net/InetAddress.html#getByName(java.lang.String)) and [getAllByName](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/net/InetAddress.html#getAllByName(java.lang.String)) resolve interface names when passed a [scoped IPv6 address](https://www.rfc-editor.org/rfc/rfc4007) like "[fe80:0:0:0:ece8:3c63:68f9:a95b%wireless_32768]". The methods will throw when they receive an unrecognized interface name.
- Deserialization of Inet6Address will reset the scope to default if the serialized scope refers to an interface that cannot be resolved.
Other user-visible changes include:
- System interfaces are enumerated in a different order.
- Certain NetworkInterface methods like `isUp`, `isPointToPoint`, `isLoopback`, `getHardwareAddress`, `getMTU` and `supportsMulticast` may return different values on some interfaces. In the current XP implementation if you call these methods on a filter interface, you get bogus results because the code can't find the interface. The new return values reflect the interface state more adequately.
Specification
-------------
This is a behavioral change only; there is no update to the specification.