8225239: Refactor NetworkInterface lookups
Reviewed-by: michaelm, dfuchs, chegar
This commit is contained in:
parent
eb2818421a
commit
7f1f9a50ae
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,6 +25,8 @@
|
|||||||
package java.net;
|
package java.net;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static java.net.InetAddress.IPv6;
|
||||||
import static java.net.InetAddress.PREFER_IPV6_VALUE;
|
import static java.net.InetAddress.PREFER_IPV6_VALUE;
|
||||||
import static java.net.InetAddress.PREFER_SYSTEM_VALUE;
|
import static java.net.InetAddress.PREFER_SYSTEM_VALUE;
|
||||||
|
|
||||||
@ -70,7 +72,7 @@ class Inet6AddressImpl implements InetAddressImpl {
|
|||||||
* stack system).
|
* stack system).
|
||||||
*/
|
*/
|
||||||
java.util.Enumeration<InetAddress> it = netif.getInetAddresses();
|
java.util.Enumeration<InetAddress> it = netif.getInetAddresses();
|
||||||
InetAddress inetaddr = null;
|
InetAddress inetaddr;
|
||||||
while (it.hasMoreElements()) {
|
while (it.hasMoreElements()) {
|
||||||
inetaddr = it.nextElement();
|
inetaddr = it.nextElement();
|
||||||
if (inetaddr.getClass().isInstance(addr)) {
|
if (inetaddr.getClass().isInstance(addr)) {
|
||||||
@ -110,20 +112,23 @@ class Inet6AddressImpl implements InetAddressImpl {
|
|||||||
boolean preferIPv6Address =
|
boolean preferIPv6Address =
|
||||||
InetAddress.preferIPv6Address == PREFER_IPV6_VALUE ||
|
InetAddress.preferIPv6Address == PREFER_IPV6_VALUE ||
|
||||||
InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE;
|
InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE;
|
||||||
InetAddress loopback4 = (new Inet4AddressImpl()).loopbackAddress();
|
|
||||||
InetAddress loopback6 = new Inet6Address("localhost",
|
for (int i = 0; i < 2; i++) {
|
||||||
|
InetAddress address;
|
||||||
|
// Order the candidate addresses by preference.
|
||||||
|
if (i == (preferIPv6Address ? 0 : 1)) {
|
||||||
|
address = new Inet6Address("localhost",
|
||||||
new byte[]{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
new byte[]{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01});
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01});
|
||||||
// Order the candidate addresses by preference.
|
} else {
|
||||||
InetAddress[] addresses = preferIPv6Address
|
address = new Inet4Address("localhost", new byte[]{ 0x7f,0x00,0x00,0x01 });
|
||||||
? new InetAddress[] {loopback6, loopback4}
|
}
|
||||||
: new InetAddress[] {loopback4, loopback6};
|
if (i == 0) {
|
||||||
// In case of failure, default to the preferred address.
|
// In case of failure, default to the preferred address.
|
||||||
loopbackAddress = addresses[0];
|
loopbackAddress = address;
|
||||||
// Pick the first candidate address that actually exists.
|
}
|
||||||
for (InetAddress address : addresses) {
|
|
||||||
try {
|
try {
|
||||||
if (NetworkInterface.getByInetAddress(address) == null) {
|
if (!NetworkInterface.isBoundInetAddress(address)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} catch (SocketException e) {
|
} catch (SocketException e) {
|
||||||
|
@ -290,7 +290,7 @@ class InetAddress implements java.io.Serializable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Used to store the name service provider */
|
/* Used to store the name service provider */
|
||||||
private static transient NameService nameService = null;
|
private static transient NameService nameService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to store the best available hostname.
|
* Used to store the best available hostname.
|
||||||
@ -305,8 +305,7 @@ class InetAddress implements java.io.Serializable {
|
|||||||
* Load net library into runtime, and perform initializations.
|
* Load net library into runtime, and perform initializations.
|
||||||
*/
|
*/
|
||||||
static {
|
static {
|
||||||
String str = java.security.AccessController.doPrivileged(
|
String str = GetPropertyAction.privilegedGetProperty("java.net.preferIPv6Addresses");
|
||||||
new GetPropertyAction("java.net.preferIPv6Addresses"));
|
|
||||||
if (str == null) {
|
if (str == null) {
|
||||||
preferIPv6Address = PREFER_IPV4_VALUE;
|
preferIPv6Address = PREFER_IPV4_VALUE;
|
||||||
} else if (str.equalsIgnoreCase("true")) {
|
} else if (str.equalsIgnoreCase("true")) {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -321,17 +321,16 @@ public final class NetworkInterface {
|
|||||||
if (addr == null) {
|
if (addr == null) {
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
}
|
}
|
||||||
if (addr instanceof Inet4Address) {
|
|
||||||
Inet4Address inet4Address = (Inet4Address) addr;
|
if (addr.holder.family == InetAddress.IPv4) {
|
||||||
if (inet4Address.holder.family != InetAddress.IPv4) {
|
if (!(addr instanceof Inet4Address)) {
|
||||||
throw new IllegalArgumentException("invalid family type: "
|
throw new IllegalArgumentException("invalid family type: "
|
||||||
+ inet4Address.holder.family);
|
+ addr.holder.family);
|
||||||
}
|
}
|
||||||
} else if (addr instanceof Inet6Address) {
|
} else if (addr.holder.family == InetAddress.IPv6) {
|
||||||
Inet6Address inet6Address = (Inet6Address) addr;
|
if (!(addr instanceof Inet6Address)) {
|
||||||
if (inet6Address.holder.family != InetAddress.IPv6) {
|
|
||||||
throw new IllegalArgumentException("invalid family type: "
|
throw new IllegalArgumentException("invalid family type: "
|
||||||
+ inet6Address.holder.family);
|
+ addr.holder.family);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("invalid address type: " + addr);
|
throw new IllegalArgumentException("invalid address type: " + addr);
|
||||||
@ -394,6 +393,23 @@ public final class NetworkInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given address is bound to any of the interfaces on this
|
||||||
|
* machine.
|
||||||
|
*
|
||||||
|
* @param addr
|
||||||
|
* The {@code InetAddress} to search with.
|
||||||
|
* @return true iff the addr parameter is currently bound to one of
|
||||||
|
* the interfaces on this machine.
|
||||||
|
*
|
||||||
|
* @throws SocketException
|
||||||
|
* If an I/O error occurs.
|
||||||
|
*/
|
||||||
|
/* package-private */ static boolean isBoundInetAddress(InetAddress addr)
|
||||||
|
throws SocketException {
|
||||||
|
return boundInetAddress0(addr);
|
||||||
|
}
|
||||||
|
|
||||||
private static <T> Enumeration<T> enumerationFromArray(T[] a) {
|
private static <T> Enumeration<T> enumerationFromArray(T[] a) {
|
||||||
return new Enumeration<>() {
|
return new Enumeration<>() {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -431,6 +447,9 @@ public final class NetworkInterface {
|
|||||||
private static native NetworkInterface getByIndex0(int index)
|
private static native NetworkInterface getByIndex0(int index)
|
||||||
throws SocketException;
|
throws SocketException;
|
||||||
|
|
||||||
|
private static native boolean boundInetAddress0(InetAddress addr)
|
||||||
|
throws SocketException;
|
||||||
|
|
||||||
private static native NetworkInterface getByInetAddress0(InetAddress addr)
|
private static native NetworkInterface getByInetAddress0(InetAddress addr)
|
||||||
throws SocketException;
|
throws SocketException;
|
||||||
|
|
||||||
|
@ -320,33 +320,9 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Return the interface in ifs that iaObj is bound to, if any - otherwise NULL
|
||||||
* Class: java_net_NetworkInterface
|
static netif* find_bound_interface(JNIEnv *env, netif* ifs, jobject iaObj, int family) {
|
||||||
* Method: getByInetAddress0
|
netif* curr = ifs;
|
||||||
* Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
|
|
||||||
*/
|
|
||||||
JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
|
|
||||||
(JNIEnv *env, jclass cls, jobject iaObj)
|
|
||||||
{
|
|
||||||
netif *ifs, *curr;
|
|
||||||
jobject obj = NULL;
|
|
||||||
jboolean match = JNI_FALSE;
|
|
||||||
int family = getInetAddress_family(env, iaObj);
|
|
||||||
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
|
|
||||||
|
|
||||||
if (family == java_net_InetAddress_IPv4) {
|
|
||||||
family = AF_INET;
|
|
||||||
} else if (family == java_net_InetAddress_IPv6) {
|
|
||||||
family = AF_INET6;
|
|
||||||
} else {
|
|
||||||
return NULL; // Invalid family
|
|
||||||
}
|
|
||||||
ifs = enumInterfaces(env);
|
|
||||||
if (ifs == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
curr = ifs;
|
|
||||||
while (curr != NULL) {
|
while (curr != NULL) {
|
||||||
netaddr *addrP = curr->addr;
|
netaddr *addrP = curr->addr;
|
||||||
|
|
||||||
@ -359,11 +335,10 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
|
|||||||
((struct sockaddr_in *)addrP->addr)->sin_addr.s_addr);
|
((struct sockaddr_in *)addrP->addr)->sin_addr.s_addr);
|
||||||
int address2 = getInetAddress_addr(env, iaObj);
|
int address2 = getInetAddress_addr(env, iaObj);
|
||||||
if ((*env)->ExceptionCheck(env)) {
|
if ((*env)->ExceptionCheck(env)) {
|
||||||
goto cleanup;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (address1 == address2) {
|
if (address1 == address2) {
|
||||||
match = JNI_TRUE;
|
return curr;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} else if (family == AF_INET6) {
|
} else if (family == AF_INET6) {
|
||||||
jbyte *bytes = (jbyte *)&(
|
jbyte *bytes = (jbyte *)&(
|
||||||
@ -383,30 +358,117 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (i >= 16) {
|
if (i >= 16) {
|
||||||
match = JNI_TRUE;
|
return curr;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
addrP = addrP->next;
|
addrP = addrP->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
curr = curr->next;
|
curr = curr->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if found create a NetworkInterface
|
return NULL;
|
||||||
if (match) {
|
}
|
||||||
obj = createNetworkInterface(env, curr);
|
|
||||||
|
/*
|
||||||
|
* Class: java_net_NetworkInterface
|
||||||
|
* Method: boundInetAddress0
|
||||||
|
* Signature: (Ljava/net/InetAddress;)boundInetAddress;
|
||||||
|
*/
|
||||||
|
JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_boundInetAddress0
|
||||||
|
(JNIEnv *env, jclass cls, jobject iaObj)
|
||||||
|
{
|
||||||
|
netif *ifs = NULL;
|
||||||
|
jboolean bound = JNI_FALSE;
|
||||||
|
int sock;
|
||||||
|
|
||||||
|
int family = getInetAddress_family(env, iaObj);
|
||||||
|
JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
|
||||||
|
|
||||||
|
if (family == java_net_InetAddress_IPv4) {
|
||||||
|
family = AF_INET;
|
||||||
|
} else if (family == java_net_InetAddress_IPv6) {
|
||||||
|
family = AF_INET6;
|
||||||
|
} else {
|
||||||
|
return JNI_FALSE; // Invalid family
|
||||||
|
}
|
||||||
|
|
||||||
|
if (family == AF_INET) {
|
||||||
|
sock = openSocket(env, AF_INET);
|
||||||
|
if (sock < 0 && (*env)->ExceptionOccurred(env)) {
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// enumerate IPv4 addresses
|
||||||
|
if (sock >= 0) {
|
||||||
|
ifs = enumIPv4Interfaces(env, sock, ifs);
|
||||||
|
close(sock);
|
||||||
|
|
||||||
|
if ((*env)->ExceptionOccurred(env)) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (find_bound_interface(env, ifs, iaObj, family) != NULL)
|
||||||
|
bound = JNI_TRUE;
|
||||||
|
} else if (ipv6_available()) {
|
||||||
|
// If IPv6 is available then enumerate IPv6 addresses.
|
||||||
|
// User can disable ipv6 explicitly by -Djava.net.preferIPv4Stack=true,
|
||||||
|
// so we have to call ipv6_available()
|
||||||
|
sock = openSocket(env, AF_INET6);
|
||||||
|
if (sock < 0) {
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ifs = enumIPv6Interfaces(env, sock, ifs);
|
||||||
|
close(sock);
|
||||||
|
|
||||||
|
if ((*env)->ExceptionOccurred(env)) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (find_bound_interface(env, ifs, iaObj, family) != NULL)
|
||||||
|
bound = JNI_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
freeif(ifs);
|
||||||
|
|
||||||
|
return bound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: java_net_NetworkInterface
|
||||||
|
* Method: getByInetAddress0
|
||||||
|
* Signature: (Ljava/net/InetAddress;)Ljava/net/NetworkInterface;
|
||||||
|
*/
|
||||||
|
JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
|
||||||
|
(JNIEnv *env, jclass cls, jobject iaObj)
|
||||||
|
{
|
||||||
|
netif *ifs, *curr;
|
||||||
|
jobject obj = NULL;
|
||||||
|
int family = getInetAddress_family(env, iaObj);
|
||||||
|
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
|
||||||
|
|
||||||
|
if (family == java_net_InetAddress_IPv4) {
|
||||||
|
family = AF_INET;
|
||||||
|
} else if (family == java_net_InetAddress_IPv6) {
|
||||||
|
family = AF_INET6;
|
||||||
|
} else {
|
||||||
|
return NULL; // Invalid family
|
||||||
|
}
|
||||||
|
ifs = enumInterfaces(env);
|
||||||
|
if (ifs == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
curr = find_bound_interface(env, ifs, iaObj, family);
|
||||||
|
|
||||||
|
// if found create a NetworkInterface
|
||||||
|
if (curr != NULL) {
|
||||||
|
obj = createNetworkInterface(env, curr);
|
||||||
|
}
|
||||||
|
|
||||||
// release the interface list
|
// release the interface list
|
||||||
freeif(ifs);
|
freeif(ifs);
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,6 +25,7 @@
|
|||||||
#include "net_util.h"
|
#include "net_util.h"
|
||||||
#include "NetworkInterface.h"
|
#include "NetworkInterface.h"
|
||||||
|
|
||||||
|
#include "java_net_InetAddress.h"
|
||||||
#include "java_net_NetworkInterface.h"
|
#include "java_net_NetworkInterface.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -347,7 +348,7 @@ int enumInterfaces(JNIEnv *env, netif **netifPP)
|
|||||||
/*
|
/*
|
||||||
* Free the interface table and return the interface list
|
* Free the interface table and return the interface list
|
||||||
*/
|
*/
|
||||||
if (tableP) {
|
if (tableP != NULL) {
|
||||||
free(tableP);
|
free(tableP);
|
||||||
}
|
}
|
||||||
*netifPP = netifP;
|
*netifPP = netifP;
|
||||||
@ -355,24 +356,13 @@ int enumInterfaces(JNIEnv *env, netif **netifPP)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enumerate the IP addresses on an interface using the IP helper library
|
* Enumerate all addresses using the IP helper library
|
||||||
* routine GetIfAddrTable and matching based on the index name. There are
|
|
||||||
* more efficient routines but we use GetIfAddrTable because it's avaliable
|
|
||||||
* on 98 and NT.
|
|
||||||
*
|
|
||||||
* Returns the count of addresses, or -1 if error. If no error occurs then
|
|
||||||
* netaddrPP will return a list of netaddr structures with the IP addresses.
|
|
||||||
*/
|
*/
|
||||||
int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP)
|
int lookupIPAddrTable(JNIEnv *env, MIB_IPADDRTABLE **tablePP)
|
||||||
{
|
{
|
||||||
MIB_IPADDRTABLE *tableP;
|
MIB_IPADDRTABLE *tableP;
|
||||||
ULONG size;
|
ULONG size;
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
DWORD i;
|
|
||||||
netaddr *netaddrP;
|
|
||||||
int count = 0;
|
|
||||||
unsigned long mask;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use GetIpAddrTable to enumerate the IP Addresses
|
* Use GetIpAddrTable to enumerate the IP Addresses
|
||||||
*/
|
*/
|
||||||
@ -396,7 +386,7 @@ int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP)
|
|||||||
ret = GetIpAddrTable(tableP, &size, FALSE);
|
ret = GetIpAddrTable(tableP, &size, FALSE);
|
||||||
}
|
}
|
||||||
if (ret != NO_ERROR) {
|
if (ret != NO_ERROR) {
|
||||||
if (tableP) {
|
if (tableP != NULL) {
|
||||||
free(tableP);
|
free(tableP);
|
||||||
}
|
}
|
||||||
JNU_ThrowByName(env, "java/lang/Error",
|
JNU_ThrowByName(env, "java/lang/Error",
|
||||||
@ -405,11 +395,30 @@ int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP)
|
|||||||
// GetIpAddrTable in pure IPv6 environment
|
// GetIpAddrTable in pure IPv6 environment
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
*tablePP = tableP;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enumerate the IP addresses on an interface, given an IP address table
|
||||||
|
* and matching based on index.
|
||||||
|
*
|
||||||
|
* Returns the count of addresses, or -1 if error. If no error occurs then
|
||||||
|
* netaddrPP will return a list of netaddr structures with the IP addresses.
|
||||||
|
*/
|
||||||
|
int enumAddresses_win_ipaddrtable(JNIEnv *env, netif *netifP, netaddr **netaddrPP, MIB_IPADDRTABLE *tableP)
|
||||||
|
{
|
||||||
|
DWORD i;
|
||||||
|
netaddr *netaddrP;
|
||||||
|
int count = 0;
|
||||||
|
unsigned long mask;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Iterate through the table to find the addresses with the
|
* Iterate through the table to find the addresses with the
|
||||||
* matching dwIndex. Ignore 0.0.0.0 addresses.
|
* matching dwIndex. Ignore 0.0.0.0 addresses.
|
||||||
*/
|
*/
|
||||||
|
if (tableP == NULL)
|
||||||
|
return 0;
|
||||||
count = 0;
|
count = 0;
|
||||||
netaddrP = NULL;
|
netaddrP = NULL;
|
||||||
|
|
||||||
@ -474,10 +483,30 @@ int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP)
|
|||||||
}
|
}
|
||||||
|
|
||||||
*netaddrPP = netaddrP;
|
*netaddrPP = netaddrP;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Enumerate the IP addresses on an interface, using an IP address table
|
||||||
|
* retrieved using GetIPAddrTable and matching based on index.
|
||||||
|
*
|
||||||
|
* Returns the count of addresses, or -1 if error. If no error occurs then
|
||||||
|
* netaddrPP will return a list of netaddr structures with the IP addresses.
|
||||||
|
*/
|
||||||
|
int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP) {
|
||||||
|
MIB_IPADDRTABLE *tableP;
|
||||||
|
int count;
|
||||||
|
int ret = lookupIPAddrTable(env, &tableP);
|
||||||
|
if (ret < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
count = enumAddresses_win_ipaddrtable(env, netifP, netaddrPP, tableP);
|
||||||
free(tableP);
|
free(tableP);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: java_net_NetworkInterface
|
* Class: java_net_NetworkInterface
|
||||||
* Method: init
|
* Method: init
|
||||||
@ -758,6 +787,50 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByIndex0
|
|||||||
return netifObj;
|
return netifObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Class: java_net_NetworkInterface
|
||||||
|
* Method: boundInetAddress0
|
||||||
|
* Signature: (Ljava/net/InetAddress;)Z
|
||||||
|
*/
|
||||||
|
JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_boundInetAddress0
|
||||||
|
(JNIEnv *env, jclass cls, jobject iaObj)
|
||||||
|
{
|
||||||
|
jobject netifObj = NULL;
|
||||||
|
DWORD i;
|
||||||
|
|
||||||
|
int family = getInetAddress_family(env, iaObj);
|
||||||
|
JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
|
||||||
|
|
||||||
|
if (family == java_net_InetAddress_IPv6) {
|
||||||
|
if (!ipv6_available())
|
||||||
|
return JNI_FALSE;
|
||||||
|
return Java_java_net_NetworkInterface_getByInetAddress0_XP(env, cls, iaObj) != NULL;
|
||||||
|
} else if (family == java_net_InetAddress_IPv4) {
|
||||||
|
jint addr = getInetAddress_addr(env, iaObj);
|
||||||
|
JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE);
|
||||||
|
|
||||||
|
jboolean found = JNI_FALSE;
|
||||||
|
MIB_IPADDRTABLE *tableP;
|
||||||
|
if (lookupIPAddrTable(env, &tableP) >= 0 && tableP != NULL) {
|
||||||
|
for (i = 0; i < tableP->dwNumEntries; i++) {
|
||||||
|
if (tableP->table[i].dwAddr != 0 &&
|
||||||
|
(unsigned long)addr == ntohl(tableP->table[i].dwAddr)) {
|
||||||
|
found = JNI_TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tableP != NULL) {
|
||||||
|
free(tableP);
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
} else {
|
||||||
|
// Unknown address family
|
||||||
|
return JNI_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Class: java_net_NetworkInterface
|
* Class: java_net_NetworkInterface
|
||||||
* Method: getByInetAddress0
|
* Method: getByInetAddress0
|
||||||
@ -767,11 +840,11 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
|
|||||||
(JNIEnv *env, jclass cls, jobject iaObj)
|
(JNIEnv *env, jclass cls, jobject iaObj)
|
||||||
{
|
{
|
||||||
netif *ifList, *curr;
|
netif *ifList, *curr;
|
||||||
|
MIB_IPADDRTABLE *tableP;
|
||||||
jobject netifObj = NULL;
|
jobject netifObj = NULL;
|
||||||
jint addr = getInetAddress_addr(env, iaObj);
|
jint addr = getInetAddress_addr(env, iaObj);
|
||||||
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
|
JNU_CHECK_EXCEPTION_RETURN(env, NULL);
|
||||||
|
|
||||||
// Retained for now to support IPv4 only stack, java.net.preferIPv4Stack
|
|
||||||
if (ipv6_available()) {
|
if (ipv6_available()) {
|
||||||
return Java_java_net_NetworkInterface_getByInetAddress0_XP (env, cls, iaObj);
|
return Java_java_net_NetworkInterface_getByInetAddress0_XP (env, cls, iaObj);
|
||||||
}
|
}
|
||||||
@ -785,6 +858,8 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
|
|||||||
* Enumerate the addresses on each interface until we find a
|
* Enumerate the addresses on each interface until we find a
|
||||||
* matching address.
|
* matching address.
|
||||||
*/
|
*/
|
||||||
|
tableP = NULL;
|
||||||
|
if (lookupIPAddrTable(env, &tableP) >= 0) {
|
||||||
curr = ifList;
|
curr = ifList;
|
||||||
while (curr != NULL) {
|
while (curr != NULL) {
|
||||||
int count;
|
int count;
|
||||||
@ -792,9 +867,10 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
|
|||||||
netaddr *addrP;
|
netaddr *addrP;
|
||||||
|
|
||||||
/* enumerate the addresses on this interface */
|
/* enumerate the addresses on this interface */
|
||||||
count = enumAddresses_win(env, curr, &addrList);
|
count = enumAddresses_win_ipaddrtable(env, curr, &addrList, tableP);
|
||||||
if (count < 0) {
|
if (count < 0) {
|
||||||
free_netif(ifList);
|
free_netif(ifList);
|
||||||
|
free(tableP);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -821,6 +897,11 @@ JNIEXPORT jobject JNICALL Java_java_net_NetworkInterface_getByInetAddress0
|
|||||||
/* on next interface */
|
/* on next interface */
|
||||||
curr = curr->next;
|
curr = curr->next;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* release the IP address table */
|
||||||
|
if (tableP != NULL)
|
||||||
|
free(tableP);
|
||||||
|
|
||||||
/* release the interface list */
|
/* release the interface list */
|
||||||
free_netif(ifList);
|
free_netif(ifList);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -33,7 +33,9 @@
|
|||||||
* and getByAddress.
|
* and getByAddress.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
extern int enumAddresses_win_ipaddrtable(JNIEnv *env, netif *netifP, netaddr **netaddrPP, MIB_IPADDRTABLE *tableP);
|
||||||
extern int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP);
|
extern int enumAddresses_win(JNIEnv *env, netif *netifP, netaddr **netaddrPP);
|
||||||
|
extern int lookupIPAddrTable(JNIEnv *env, MIB_IPADDRTABLE **tablePP);
|
||||||
int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP);
|
int getAddrsFromAdapter(IP_ADAPTER_ADDRESSES *ptr, netaddr **netaddrPP);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -239,6 +241,7 @@ static int ipinflen = 2048;
|
|||||||
int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP)
|
int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP)
|
||||||
{
|
{
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
MIB_IPADDRTABLE *tableP;
|
||||||
IP_ADAPTER_ADDRESSES *ptr, *adapters=NULL;
|
IP_ADAPTER_ADDRESSES *ptr, *adapters=NULL;
|
||||||
ULONG len=ipinflen, count=0;
|
ULONG len=ipinflen, count=0;
|
||||||
netif *nif=NULL, *dup_nif, *last=NULL, *loopif=NULL, *curr;
|
netif *nif=NULL, *dup_nif, *last=NULL, *loopif=NULL, *curr;
|
||||||
@ -271,10 +274,15 @@ int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP)
|
|||||||
|
|
||||||
// Retrieve IPv4 addresses with the IP Helper API
|
// Retrieve IPv4 addresses with the IP Helper API
|
||||||
curr = *netifPP;
|
curr = *netifPP;
|
||||||
|
ret = lookupIPAddrTable(env, &tableP);
|
||||||
|
if (ret < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
while (curr != NULL) {
|
while (curr != NULL) {
|
||||||
netaddr *netaddrP;
|
netaddr *netaddrP;
|
||||||
ret = enumAddresses_win(env, curr, &netaddrP);
|
ret = enumAddresses_win_ipaddrtable(env, curr, &netaddrP, tableP);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
|
free(tableP);
|
||||||
return -1;
|
return -1;
|
||||||
} else if (ret == -2) {
|
} else if (ret == -2) {
|
||||||
if ((*env)->ExceptionCheck(env)) {
|
if ((*env)->ExceptionCheck(env)) {
|
||||||
@ -287,7 +295,7 @@ int getAllInterfacesAndAddresses (JNIEnv *env, netif **netifPP)
|
|||||||
curr = curr->next;
|
curr = curr->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
free(tableP);
|
||||||
ret = getAdapters (env, &adapters);
|
ret = getAdapters (env, &adapters);
|
||||||
if (ret != ERROR_SUCCESS) {
|
if (ret != ERROR_SUCCESS) {
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -23,17 +23,21 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @test
|
* @test
|
||||||
* @bug 8179559
|
* @bug 8179559 8225239
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.NetworkInterface;
|
import java.net.NetworkInterface;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
public class NetworkInterfaceRetrievalTests {
|
public class NetworkInterfaceRetrievalTests {
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
int checkFailureCount = 0;
|
int checkFailureCount = 0;
|
||||||
|
|
||||||
|
Method isBound = NetworkInterface.class.getDeclaredMethod("isBoundInetAddress", InetAddress.class);
|
||||||
|
isBound.setAccessible(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Enumeration<NetworkInterface> en = NetworkInterface
|
Enumeration<NetworkInterface> en = NetworkInterface
|
||||||
.getNetworkInterfaces();
|
.getNetworkInterfaces();
|
||||||
@ -58,6 +62,13 @@ public class NetworkInterfaceRetrievalTests {
|
|||||||
checkFailureCount++;
|
checkFailureCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Any bound address should return true when calling isBoundInetAddress
|
||||||
|
if (!((boolean)isBound.invoke(null, addr))) {
|
||||||
|
System.out.println("Retreived net if bound addr " + addr
|
||||||
|
+ "NOT shown as bound using NetworkInterface.isBoundAddress "
|
||||||
|
+ "***********");
|
||||||
|
checkFailureCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
package org.openjdk.bench.java.net;
|
||||||
|
|
||||||
|
import org.openjdk.jmh.annotations.Benchmark;
|
||||||
|
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||||
|
import org.openjdk.jmh.annotations.Fork;
|
||||||
|
import org.openjdk.jmh.annotations.Measurement;
|
||||||
|
import org.openjdk.jmh.annotations.Mode;
|
||||||
|
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||||
|
import org.openjdk.jmh.annotations.Scope;
|
||||||
|
import org.openjdk.jmh.annotations.State;
|
||||||
|
import org.openjdk.jmh.annotations.Warmup;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.NetworkInterface;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assess time to perform native NetworkInterface lookups; uses
|
||||||
|
* reflection to access both package-private isBoundInetAddress and
|
||||||
|
* public getByInetAddress (to get comparable numbers)
|
||||||
|
*/
|
||||||
|
@BenchmarkMode(Mode.Throughput)
|
||||||
|
@OutputTimeUnit(TimeUnit.SECONDS)
|
||||||
|
@State(Scope.Thread)
|
||||||
|
@Fork(2)
|
||||||
|
@Warmup(iterations = 5, time = 2)
|
||||||
|
@Measurement(iterations = 10, time = 2)
|
||||||
|
public class NetworkInterfaceLookup {
|
||||||
|
|
||||||
|
static final InetAddress address = InetAddress.getLoopbackAddress();
|
||||||
|
|
||||||
|
static final Method isBoundInetAddress_method;
|
||||||
|
|
||||||
|
static final Method getByInetAddress_method;
|
||||||
|
|
||||||
|
static {
|
||||||
|
Method isBound = null;
|
||||||
|
Method getByInet = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
isBound = NetworkInterface.class.getDeclaredMethod("isBoundInetAddress", InetAddress.class);
|
||||||
|
isBound.setAccessible(true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("NetworkInterface.isBoundInetAddress not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
getByInet = NetworkInterface.class.getDeclaredMethod("getByInetAddress", InetAddress.class);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("NetworkInterface.getByInetAddress not found");
|
||||||
|
}
|
||||||
|
isBoundInetAddress_method = isBound;
|
||||||
|
getByInetAddress_method = getByInet;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public boolean bound() throws Exception {
|
||||||
|
return (boolean)isBoundInetAddress_method.invoke(null, address);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
public NetworkInterface getByInetAddress() throws Exception {
|
||||||
|
return (NetworkInterface)getByInetAddress_method.invoke(null, address);
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user