mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8016521: InetAddress should not always re-order addresses returned from name service
Reviewed-by: chegar
This commit is contained in:
parent
27a77176a6
commit
af7a591d39
7 changed files with 216 additions and 41 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 2016, 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,7 +23,10 @@
|
||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
package java.net;
|
package java.net;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import static java.net.InetAddress.PREFER_IPV6_VALUE;
|
||||||
|
import static java.net.InetAddress.PREFER_SYSTEM_VALUE;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Package private implementation of InetAddressImpl for dual
|
* Package private implementation of InetAddressImpl for dual
|
||||||
|
@ -35,15 +38,23 @@ import java.io.IOException;
|
||||||
*
|
*
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class Inet6AddressImpl implements InetAddressImpl {
|
class Inet6AddressImpl implements InetAddressImpl {
|
||||||
public native String getLocalHostName() throws UnknownHostException;
|
|
||||||
public native InetAddress[]
|
|
||||||
lookupAllHostAddr(String hostname) throws UnknownHostException;
|
|
||||||
public native String getHostByAddr(byte[] addr) throws UnknownHostException;
|
|
||||||
private native boolean isReachable0(byte[] addr, int scope, int timeout, byte[] inf, int ttl, int if_scope) throws IOException;
|
|
||||||
|
|
||||||
public boolean isReachable(InetAddress addr, int timeout, NetworkInterface netif, int ttl) throws IOException {
|
public native String getLocalHostName() throws UnknownHostException;
|
||||||
|
|
||||||
|
public native InetAddress[] lookupAllHostAddr(String hostname)
|
||||||
|
throws UnknownHostException;
|
||||||
|
|
||||||
|
public native String getHostByAddr(byte[] addr) throws UnknownHostException;
|
||||||
|
|
||||||
|
private native boolean isReachable0(byte[] addr, int scope, int timeout,
|
||||||
|
byte[] inf, int ttl, int if_scope)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
|
public boolean isReachable(InetAddress addr, int timeout,
|
||||||
|
NetworkInterface netif, int ttl)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
byte[] ifaddr = null;
|
byte[] ifaddr = null;
|
||||||
int scope = -1;
|
int scope = -1;
|
||||||
int netif_scope = -1;
|
int netif_scope = -1;
|
||||||
|
@ -79,7 +90,8 @@ class Inet6AddressImpl implements InetAddressImpl {
|
||||||
|
|
||||||
public synchronized InetAddress anyLocalAddress() {
|
public synchronized InetAddress anyLocalAddress() {
|
||||||
if (anyLocalAddress == null) {
|
if (anyLocalAddress == null) {
|
||||||
if (InetAddress.preferIPv6Address) {
|
if (InetAddress.preferIPv6Address == PREFER_IPV6_VALUE ||
|
||||||
|
InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE) {
|
||||||
anyLocalAddress = new Inet6Address();
|
anyLocalAddress = new Inet6Address();
|
||||||
anyLocalAddress.holder().hostName = "::";
|
anyLocalAddress.holder().hostName = "::";
|
||||||
} else {
|
} else {
|
||||||
|
@ -91,7 +103,8 @@ class Inet6AddressImpl implements InetAddressImpl {
|
||||||
|
|
||||||
public synchronized InetAddress loopbackAddress() {
|
public synchronized InetAddress loopbackAddress() {
|
||||||
if (loopbackAddress == null) {
|
if (loopbackAddress == null) {
|
||||||
if (InetAddress.preferIPv6Address) {
|
if (InetAddress.preferIPv6Address == PREFER_IPV6_VALUE ||
|
||||||
|
InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE) {
|
||||||
byte[] loopback =
|
byte[] loopback =
|
||||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
|
||||||
|
@ -103,6 +116,6 @@ class Inet6AddressImpl implements InetAddressImpl {
|
||||||
return loopbackAddress;
|
return loopbackAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
private InetAddress anyLocalAddress;
|
private InetAddress anyLocalAddress;
|
||||||
private InetAddress loopbackAddress;
|
private InetAddress loopbackAddress;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,6 @@
|
||||||
package java.net;
|
package java.net;
|
||||||
|
|
||||||
import java.util.NavigableSet;
|
import java.util.NavigableSet;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
@ -41,6 +39,7 @@ import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectInputStream.GetField;
|
import java.io.ObjectInputStream.GetField;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.io.ObjectOutputStream.PutField;
|
import java.io.ObjectOutputStream.PutField;
|
||||||
|
import java.lang.annotation.Native;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.ConcurrentSkipListSet;
|
import java.util.concurrent.ConcurrentSkipListSet;
|
||||||
|
@ -193,6 +192,11 @@ import sun.net.util.IPAddressUtil;
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
class InetAddress implements java.io.Serializable {
|
class InetAddress implements java.io.Serializable {
|
||||||
|
|
||||||
|
@Native static final int PREFER_IPV4_VALUE = 0;
|
||||||
|
@Native static final int PREFER_IPV6_VALUE = 1;
|
||||||
|
@Native static final int PREFER_SYSTEM_VALUE = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specify the address family: Internet Protocol, Version 4
|
* Specify the address family: Internet Protocol, Version 4
|
||||||
* @since 1.4
|
* @since 1.4
|
||||||
|
@ -206,8 +210,7 @@ class InetAddress implements java.io.Serializable {
|
||||||
static final int IPv6 = 2;
|
static final int IPv6 = 2;
|
||||||
|
|
||||||
/* Specify address family preference */
|
/* Specify address family preference */
|
||||||
static transient boolean preferIPv6Address = false;
|
static transient final int preferIPv6Address;
|
||||||
|
|
||||||
|
|
||||||
static class InetAddressHolder {
|
static class InetAddressHolder {
|
||||||
/**
|
/**
|
||||||
|
@ -293,8 +296,19 @@ class InetAddress implements java.io.Serializable {
|
||||||
* Load net library into runtime, and perform initializations.
|
* Load net library into runtime, and perform initializations.
|
||||||
*/
|
*/
|
||||||
static {
|
static {
|
||||||
preferIPv6Address = java.security.AccessController.doPrivileged(
|
String str = java.security.AccessController.doPrivileged(
|
||||||
new GetBooleanAction("java.net.preferIPv6Addresses")).booleanValue();
|
new GetPropertyAction("java.net.preferIPv6Addresses"));
|
||||||
|
if (str == null) {
|
||||||
|
preferIPv6Address = PREFER_IPV4_VALUE;
|
||||||
|
} else if (str.equalsIgnoreCase("true")) {
|
||||||
|
preferIPv6Address = PREFER_IPV6_VALUE;
|
||||||
|
} else if (str.equalsIgnoreCase("false")) {
|
||||||
|
preferIPv6Address = PREFER_IPV4_VALUE;
|
||||||
|
} else if (str.equalsIgnoreCase("system")) {
|
||||||
|
preferIPv6Address = PREFER_SYSTEM_VALUE;
|
||||||
|
} else {
|
||||||
|
preferIPv6Address = PREFER_IPV4_VALUE;
|
||||||
|
}
|
||||||
AccessController.doPrivileged(
|
AccessController.doPrivileged(
|
||||||
new java.security.PrivilegedAction<>() {
|
new java.security.PrivilegedAction<>() {
|
||||||
public Void run() {
|
public Void run() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!--
|
<!--
|
||||||
Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
|
Copyright (c) 1998, 2016, 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
|
||||||
|
@ -58,7 +58,8 @@ and detail all of these properties.</P>
|
||||||
applications that depend on the representation of an IPv4 address
|
applications that depend on the representation of an IPv4 address
|
||||||
(e.g. 192.168.1.1). This property can be set to <B>true</B> to
|
(e.g. 192.168.1.1). This property can be set to <B>true</B> to
|
||||||
change that preference and use IPv6 addresses over IPv4 ones where
|
change that preference and use IPv6 addresses over IPv4 ones where
|
||||||
possible.</P>
|
possible, or <B>system</B> to preserve the order of the addresses as
|
||||||
|
returned by the operating system.</P>
|
||||||
</UL>
|
</UL>
|
||||||
<P>Both of these properties are checked only once, at startup.</P>
|
<P>Both of these properties are checked only once, at startup.</P>
|
||||||
<a name="Proxies"></a>
|
<a name="Proxies"></a>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2016, 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
|
||||||
|
@ -61,7 +61,7 @@ Java_java_net_InetAddress_init(JNIEnv *env, jclass cls) {
|
||||||
CHECK_NULL(iac_class);
|
CHECK_NULL(iac_class);
|
||||||
ia_holderID = (*env)->GetFieldID(env, ia_class, "holder", "Ljava/net/InetAddress$InetAddressHolder;");
|
ia_holderID = (*env)->GetFieldID(env, ia_class, "holder", "Ljava/net/InetAddress$InetAddressHolder;");
|
||||||
CHECK_NULL(ia_holderID);
|
CHECK_NULL(ia_holderID);
|
||||||
ia_preferIPv6AddressID = (*env)->GetStaticFieldID(env, ia_class, "preferIPv6Address", "Z");
|
ia_preferIPv6AddressID = (*env)->GetStaticFieldID(env, ia_class, "preferIPv6Address", "I");
|
||||||
CHECK_NULL(ia_preferIPv6AddressID);
|
CHECK_NULL(ia_preferIPv6AddressID);
|
||||||
|
|
||||||
iac_addressID = (*env)->GetFieldID(env, iac_class, "address", "I");
|
iac_addressID = (*env)->GetFieldID(env, iac_class, "address", "I");
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2016, 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
|
||||||
|
@ -48,6 +48,7 @@
|
||||||
|
|
||||||
#include "java_net_Inet4AddressImpl.h"
|
#include "java_net_Inet4AddressImpl.h"
|
||||||
#include "java_net_Inet6AddressImpl.h"
|
#include "java_net_Inet6AddressImpl.h"
|
||||||
|
#include "java_net_InetAddress.h"
|
||||||
|
|
||||||
/* the initial size of our hostent buffers */
|
/* the initial size of our hostent buffers */
|
||||||
#ifndef NI_MAXHOST
|
#ifndef NI_MAXHOST
|
||||||
|
@ -312,8 +313,8 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
JNU_ReleaseStringPlatformChars(env, host, hostname);
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
int i = 0;
|
int i = 0, addressPreference = -1;
|
||||||
int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
|
int inetCount = 0, inet6Count = 0, inetIndex = 0, inet6Index = 0, originalIndex = 0;
|
||||||
struct addrinfo *itr, *last = NULL, *iterator = res;
|
struct addrinfo *itr, *last = NULL, *iterator = res;
|
||||||
while (iterator != NULL) {
|
while (iterator != NULL) {
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
|
@ -394,14 +395,18 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
goto cleanupAndReturn;
|
goto cleanupAndReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID)) {
|
addressPreference = (*env)->GetStaticIntField(env, ia_class, ia_preferIPv6AddressID);
|
||||||
|
|
||||||
|
if (addressPreference == java_net_InetAddress_PREFER_IPV6_VALUE) {
|
||||||
/* AF_INET addresses will be offset by inet6Count */
|
/* AF_INET addresses will be offset by inet6Count */
|
||||||
inetIndex = inet6Count;
|
inetIndex = inet6Count;
|
||||||
inet6Index = 0;
|
inet6Index = 0;
|
||||||
} else {
|
} else if (addressPreference == java_net_InetAddress_PREFER_IPV4_VALUE) {
|
||||||
/* AF_INET6 addresses will be offset by inetCount */
|
/* AF_INET6 addresses will be offset by inetCount */
|
||||||
inetIndex = 0;
|
inetIndex = 0;
|
||||||
inet6Index = inetCount;
|
inet6Index = inetCount;
|
||||||
|
} else if (addressPreference == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
|
||||||
|
inetIndex = inet6Index = originalIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (iterator != NULL) {
|
while (iterator != NULL) {
|
||||||
|
@ -414,7 +419,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
}
|
}
|
||||||
setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
|
setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
|
||||||
setInetAddress_hostName(env, iaObj, host);
|
setInetAddress_hostName(env, iaObj, host);
|
||||||
(*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
|
(*env)->SetObjectArrayElement(env, ret, (inetIndex | originalIndex), iaObj);
|
||||||
inetIndex++;
|
inetIndex++;
|
||||||
} else if (iterator->ai_family == AF_INET6) {
|
} else if (iterator->ai_family == AF_INET6) {
|
||||||
jint scope = 0;
|
jint scope = 0;
|
||||||
|
@ -435,9 +440,13 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
setInet6Address_scopeid(env, iaObj, scope);
|
setInet6Address_scopeid(env, iaObj, scope);
|
||||||
}
|
}
|
||||||
setInetAddress_hostName(env, iaObj, host);
|
setInetAddress_hostName(env, iaObj, host);
|
||||||
(*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
|
(*env)->SetObjectArrayElement(env, ret, (inet6Index | originalIndex), iaObj);
|
||||||
inet6Index++;
|
inet6Index++;
|
||||||
}
|
}
|
||||||
|
if (addressPreference == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
|
||||||
|
originalIndex++;
|
||||||
|
inetIndex = inet6Index = 0;
|
||||||
|
}
|
||||||
iterator = iterator->ai_next;
|
iterator = iterator->ai_next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2016, 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
|
||||||
|
@ -97,7 +97,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
|
|
||||||
/* get the address preference */
|
/* get the address preference */
|
||||||
preferIPv6Address
|
preferIPv6Address
|
||||||
= (*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID);
|
= (*env)->GetStaticIntField(env, ia_class, ia_preferIPv6AddressID);
|
||||||
|
|
||||||
/* Try once, with our static buffer. */
|
/* Try once, with our static buffer. */
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
@ -122,7 +122,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int inetCount = 0, inet6Count = 0, inetIndex, inet6Index;
|
int inetCount = 0, inet6Count = 0, inetIndex = 0, inet6Index = 0, originalIndex = 0;
|
||||||
struct addrinfo *itr, *last, *iterator = res;
|
struct addrinfo *itr, *last, *iterator = res;
|
||||||
while (iterator != NULL) {
|
while (iterator != NULL) {
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
|
@ -203,12 +203,14 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
goto cleanupAndReturn;
|
goto cleanupAndReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (preferIPv6Address) {
|
if (preferIPv6Address == java_net_InetAddress_PREFER_IPV6_VALUE) {
|
||||||
inetIndex = inet6Count;
|
inetIndex = inet6Count;
|
||||||
inet6Index = 0;
|
inet6Index = 0;
|
||||||
} else {
|
} else if (preferIPv6Address == java_net_InetAddress_PREFER_IPV4_VALUE) {
|
||||||
inetIndex = 0;
|
inetIndex = 0;
|
||||||
inet6Index = inetCount;
|
inet6Index = inetCount;
|
||||||
|
} else if (preferIPv6Address == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
|
||||||
|
inetIndex = inet6Index = originalIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (iterator != NULL) {
|
while (iterator != NULL) {
|
||||||
|
@ -220,7 +222,7 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
}
|
}
|
||||||
setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
|
setInetAddress_addr(env, iaObj, ntohl(((struct sockaddr_in*)iterator->ai_addr)->sin_addr.s_addr));
|
||||||
setInetAddress_hostName(env, iaObj, host);
|
setInetAddress_hostName(env, iaObj, host);
|
||||||
(*env)->SetObjectArrayElement(env, ret, inetIndex, iaObj);
|
(*env)->SetObjectArrayElement(env, ret, (inetIndex | originalIndex), iaObj);
|
||||||
inetIndex ++;
|
inetIndex ++;
|
||||||
} else if (iterator->ai_family == AF_INET6) {
|
} else if (iterator->ai_family == AF_INET6) {
|
||||||
jint scope = 0;
|
jint scope = 0;
|
||||||
|
@ -240,9 +242,13 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this,
|
||||||
setInet6Address_scopeid(env, iaObj, scope);
|
setInet6Address_scopeid(env, iaObj, scope);
|
||||||
}
|
}
|
||||||
setInetAddress_hostName(env, iaObj, host);
|
setInetAddress_hostName(env, iaObj, host);
|
||||||
(*env)->SetObjectArrayElement(env, ret, inet6Index, iaObj);
|
(*env)->SetObjectArrayElement(env, ret, (inet6Index | originalIndex), iaObj);
|
||||||
inet6Index ++;
|
inet6Index ++;
|
||||||
}
|
}
|
||||||
|
if (preferIPv6Address == java_net_InetAddress_PREFER_SYSTEM_VALUE) {
|
||||||
|
originalIndex++;
|
||||||
|
inetIndex = inet6Index = 0;
|
||||||
|
}
|
||||||
iterator = iterator->ai_next;
|
iterator = iterator->ai_next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
132
jdk/test/java/net/Inet6Address/PreferIPv6AddressesTest.java
Normal file
132
jdk/test/java/net/Inet6Address/PreferIPv6AddressesTest.java
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @test
|
||||||
|
* @bug 8016521
|
||||||
|
* @summary InetAddress should not always re-order addresses returned from name
|
||||||
|
* service
|
||||||
|
* @run main/othervm -Djava.net.preferIPv6Addresses=false PreferIPv6AddressesTest
|
||||||
|
* @run main/othervm -Djava.net.preferIPv6Addresses=true PreferIPv6AddressesTest
|
||||||
|
* @run main/othervm -Djava.net.preferIPv6Addresses=system PreferIPv6AddressesTest
|
||||||
|
* @run main/othervm PreferIPv6AddressesTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.*;
|
||||||
|
import java.nio.channels.DatagramChannel;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import static java.lang.System.out;
|
||||||
|
|
||||||
|
public class PreferIPv6AddressesTest {
|
||||||
|
|
||||||
|
// A name, that if resolves, returns both IPv4 and IPv6 addresses.
|
||||||
|
static final String HOST_NAME = "www.google.com";
|
||||||
|
|
||||||
|
static final InetAddress LOOPBACK = InetAddress.getLoopbackAddress();
|
||||||
|
|
||||||
|
static final String preferIPV6Address =
|
||||||
|
System.getProperty("java.net.preferIPv6Addresses", "false");
|
||||||
|
|
||||||
|
public static void main(String args[]) throws IOException {
|
||||||
|
|
||||||
|
InetAddress addrs[];
|
||||||
|
try {
|
||||||
|
addrs = InetAddress.getAllByName(HOST_NAME);
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
out.println("Unknown host " + HOST_NAME + ", cannot run test.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int firstIPv4Address = IntStream.range(0, addrs.length)
|
||||||
|
.filter(x -> addrs[x] instanceof Inet4Address)
|
||||||
|
.findFirst().orElse(-1);
|
||||||
|
int firstIPv6Address = IntStream.range(0, addrs.length)
|
||||||
|
.filter(x -> addrs[x] instanceof Inet6Address)
|
||||||
|
.findFirst().orElse(-1);
|
||||||
|
|
||||||
|
out.println("IPv6 supported: " + IPv6Supported());
|
||||||
|
out.println("Addresses: " + Arrays.asList(addrs));
|
||||||
|
|
||||||
|
if (preferIPV6Address.equalsIgnoreCase("true") && firstIPv6Address != -1) {
|
||||||
|
int off = firstIPv4Address != -1 ? firstIPv4Address : addrs.length;
|
||||||
|
assertAllv6Addresses(addrs, 0, off);
|
||||||
|
assertAllv4Addresses(addrs, off, addrs.length);
|
||||||
|
assertLoopbackAddress(Inet6Address.class);
|
||||||
|
assertAnyLocalAddress(Inet6Address.class);
|
||||||
|
} else if (preferIPV6Address.equalsIgnoreCase("false") && firstIPv4Address != -1) {
|
||||||
|
int off = firstIPv6Address != -1 ? firstIPv6Address : addrs.length;
|
||||||
|
assertAllv4Addresses(addrs, 0, off);
|
||||||
|
assertAllv6Addresses(addrs, off, addrs.length);
|
||||||
|
assertLoopbackAddress(Inet4Address.class);
|
||||||
|
assertAnyLocalAddress(Inet4Address.class);
|
||||||
|
} else if (preferIPV6Address.equalsIgnoreCase("system") && IPv6Supported()) {
|
||||||
|
assertLoopbackAddress(Inet6Address.class);
|
||||||
|
assertAnyLocalAddress(Inet6Address.class);
|
||||||
|
} else if (preferIPV6Address.equalsIgnoreCase("system") && !IPv6Supported()) {
|
||||||
|
assertLoopbackAddress(Inet4Address.class);
|
||||||
|
assertAnyLocalAddress(Inet4Address.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assertAllv4Addresses(InetAddress[] addrs, int off, int len) {
|
||||||
|
IntStream.range(off, len)
|
||||||
|
.mapToObj(x -> addrs[x])
|
||||||
|
.forEach(x -> {
|
||||||
|
if (!(x instanceof Inet4Address))
|
||||||
|
throw new RuntimeException("Expected IPv4, got " + x);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assertAllv6Addresses(InetAddress[] addrs, int off, int len) {
|
||||||
|
IntStream.range(off, len)
|
||||||
|
.mapToObj(x -> addrs[x])
|
||||||
|
.forEach(x -> {
|
||||||
|
if (!(x instanceof Inet6Address))
|
||||||
|
throw new RuntimeException("Expected IPv6, got " + x);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assertLoopbackAddress(Class<?> expectedType) {
|
||||||
|
if (!LOOPBACK.getClass().isAssignableFrom(expectedType))
|
||||||
|
throw new RuntimeException("Expected " + expectedType
|
||||||
|
+ ", got " + LOOPBACK.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void assertAnyLocalAddress(Class<?> expectedType) {
|
||||||
|
InetAddress anyAddr = (new InetSocketAddress(0)).getAddress();
|
||||||
|
if (!anyAddr.getClass().isAssignableFrom(expectedType))
|
||||||
|
throw new RuntimeException("Expected " + expectedType
|
||||||
|
+ ", got " + anyAddr.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean IPv6Supported() throws IOException {
|
||||||
|
try {
|
||||||
|
DatagramChannel.open(StandardProtocolFamily.INET6);
|
||||||
|
return true;
|
||||||
|
} catch (UnsupportedOperationException x) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue