mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8216417: cleanup of IPv6 scope-id handling
Reviewed-by: alanb, chegar, dfuchs
This commit is contained in:
parent
04ea6ae9b3
commit
247a6a2ce4
23 changed files with 761 additions and 595 deletions
|
@ -25,6 +25,20 @@
|
|||
|
||||
package sun.net.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class IPAddressUtil {
|
||||
private static final int INADDR4SZ = 4;
|
||||
private static final int INADDR16SZ = 16;
|
||||
|
@ -287,4 +301,75 @@ public class IPAddressUtil {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Mapping from unscoped local Inet(6)Address to the same address
|
||||
* including the correct scope-id, determined from NetworkInterface.
|
||||
*/
|
||||
private final static ConcurrentHashMap<InetAddress,InetAddress>
|
||||
cache = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Returns a scoped version of the supplied local, link-local ipv6 address
|
||||
* if that scope-id can be determined from local NetworkInterfaces.
|
||||
* If the address already has a scope-id or if the address is not local, ipv6
|
||||
* or link local, then the original address is returned.
|
||||
*
|
||||
* @param addr
|
||||
* @exception SocketException if the given ipv6 link local address is found
|
||||
* on more than one local interface
|
||||
* @return
|
||||
*/
|
||||
public static InetAddress toScopedAddress(InetAddress address)
|
||||
throws SocketException {
|
||||
|
||||
if (address instanceof Inet6Address && address.isLinkLocalAddress()
|
||||
&& ((Inet6Address) address).getScopeId() == 0) {
|
||||
|
||||
InetAddress cached = null;
|
||||
try {
|
||||
cached = cache.computeIfAbsent(address, k -> findScopedAddress(k));
|
||||
} catch (UncheckedIOException e) {
|
||||
throw (SocketException)e.getCause();
|
||||
}
|
||||
return cached != null ? cached : address;
|
||||
} else {
|
||||
return address;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as above for InetSocketAddress
|
||||
*/
|
||||
public static InetSocketAddress toScopedAddress(InetSocketAddress address)
|
||||
throws SocketException {
|
||||
InetAddress addr;
|
||||
InetAddress orig = address.getAddress();
|
||||
if ((addr = toScopedAddress(orig)) == orig) {
|
||||
return address;
|
||||
} else {
|
||||
return new InetSocketAddress(addr, address.getPort());
|
||||
}
|
||||
}
|
||||
|
||||
private static InetAddress findScopedAddress(InetAddress address) {
|
||||
PrivilegedExceptionAction<List<InetAddress>> pa = () -> NetworkInterface.networkInterfaces()
|
||||
.flatMap(NetworkInterface::inetAddresses)
|
||||
.filter(a -> (a instanceof Inet6Address)
|
||||
&& address.equals(a)
|
||||
&& ((Inet6Address) a).getScopeId() != 0)
|
||||
.collect(Collectors.toList());
|
||||
List<InetAddress> result;
|
||||
try {
|
||||
result = AccessController.doPrivileged(pa);
|
||||
var sz = result.size();
|
||||
if (sz == 0)
|
||||
return null;
|
||||
if (sz > 1)
|
||||
throw new UncheckedIOException(new SocketException(
|
||||
"Duplicate link local addresses: must specify scope-id"));
|
||||
return result.get(0);
|
||||
} catch (PrivilegedActionException pae) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue