8313804: JDWP support for -Djava.net.preferIPv6Addresses=system

Reviewed-by: cjplummer, amenkov
This commit is contained in:
Liam Miller-Cushon 2023-09-25 16:43:20 +00:00
parent afa48333ab
commit 9291b46bcf
2 changed files with 117 additions and 19 deletions

View File

@ -727,11 +727,13 @@ socketTransport_startListening(jdwpTransportEnv* env, const char* address,
return err;
}
// Try to find bind address of preferred address family first.
for (ai = addrInfo; ai != NULL; ai = ai->ai_next) {
if (ai->ai_family == preferredAddressFamily) {
listenAddr = ai;
break;
// Try to find bind address of preferred address family first (if java.net.preferIPv6Addresses != "system").
if (preferredAddressFamily != AF_UNSPEC) {
for (ai = addrInfo; ai != NULL; ai = ai->ai_next) {
if (ai->ai_family == preferredAddressFamily) {
listenAddr = ai;
break;
}
}
}
@ -743,9 +745,9 @@ socketTransport_startListening(jdwpTransportEnv* env, const char* address,
// Binding to IN6ADDR_ANY allows to serve both IPv4 and IPv6 connections,
// but binding to mapped INADDR_ANY (::ffff:0.0.0.0) allows to serve IPv4
// connections only. Make sure that IN6ADDR_ANY is preferred over
// mapped INADDR_ANY if preferredAddressFamily is AF_INET6 or not set.
// mapped INADDR_ANY if preferIPv4Stack is false.
if (preferredAddressFamily != AF_INET) {
if (!allowOnlyIPv4) {
inet_pton(AF_INET6, "::ffff:0.0.0.0", &mappedAny);
if (isEqualIPv6Addr(listenAddr, mappedAny)) {
@ -967,8 +969,10 @@ socketTransport_attach(jdwpTransportEnv* env, const char* addressString, jlong a
return err;
}
/* 1st pass - preferredAddressFamily (by default IPv4), 2nd pass - the rest */
for (pass = 0; pass < 2 && socketFD < 0; pass++) {
// 1st pass - preferredAddressFamily (by default IPv4), 2nd pass - the rest;
// if java.net.preferIPv6Addresses == "system", only 2nd pass is needed
pass = preferredAddressFamily != AF_UNSPEC ? 0 : 1;
for (; pass < 2 && socketFD < 0; pass++) {
for (ai = addrInfo; ai != NULL; ai = ai->ai_next) {
if ((pass == 0 && ai->ai_family == preferredAddressFamily) ||
(pass == 1 && ai->ai_family != preferredAddressFamily))
@ -1305,6 +1309,43 @@ static int readBooleanSysProp(int *result, int trueValue, int falseValue,
return JNI_OK;
}
/*
* Reads java.net.preferIPv6Addresses system value, sets preferredAddressFamily to
* - AF_INET6 if the property is "true";
* - AF_INET if the property is "false".
* - AF_UNSPEC if the property is "system".
* Doesn't change preferredAddressFamily if the property is not set or failed to read.
*/
static int readPreferIPv6Addresses(JNIEnv* jniEnv,
jclass sysClass, jmethodID getPropMethod, const char *propName)
{
jstring value;
jstring name = (*jniEnv)->NewStringUTF(jniEnv, propName);
if (name == NULL) {
return JNI_ERR;
}
value = (jstring)(*jniEnv)->CallStaticObjectMethod(jniEnv, sysClass, getPropMethod, name);
if ((*jniEnv)->ExceptionCheck(jniEnv)) {
return JNI_ERR;
}
if (value != NULL) {
const char *theValue = (*jniEnv)->GetStringUTFChars(jniEnv, value, NULL);
if (theValue == NULL) {
return JNI_ERR;
}
if (strcmp(theValue, "true") == 0) {
preferredAddressFamily = AF_INET6;
} else if (strcmp(theValue, "false") == 0) {
preferredAddressFamily = AF_INET;
} else if (strcmp(theValue, "system") == 0) {
preferredAddressFamily = AF_UNSPEC;
}
(*jniEnv)->ReleaseStringUTFChars(jniEnv, value, theValue);
}
return JNI_OK;
}
JNIEXPORT jint JNICALL
jdwpTransport_OnLoad(JavaVM *vm, jdwpTransportCallback* cbTablePtr,
jint version, jdwpTransportEnv** env)
@ -1362,7 +1403,7 @@ jdwpTransport_OnLoad(JavaVM *vm, jdwpTransportCallback* cbTablePtr,
}
readBooleanSysProp(&allowOnlyIPv4, 1, 0,
jniEnv, sysClass, getPropMethod, "java.net.preferIPv4Stack");
readBooleanSysProp(&preferredAddressFamily, AF_INET6, AF_INET,
readPreferIPv6Addresses(
jniEnv, sysClass, getPropMethod, "java.net.preferIPv6Addresses");
} while (0);

View File

@ -36,15 +36,16 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/*
* @test
* @bug 8184770
* @bug 8184770 8313804
* @summary Tests that JDWP agent honors jdk net properties
* @library /test/lib
*
* @build HelloWorld JdwpNetProps
* @run main/othervm JdwpNetProps
* @run main/othervm -Djava.net.preferIPv6Addresses=system JdwpNetProps
*/
public class JdwpNetProps {
@ -60,33 +61,88 @@ public class JdwpNetProps {
}
}
String preferIPv6Address = System.getProperty("java.net.preferIPv6Addresses");
if (!Objects.equals(preferIPv6Address, "system")) {
throw new AssertionError(
"Expected -Djava.net.preferIPv6Address=system, was " + preferIPv6Address);
}
boolean systemPrefersIPv6 = addrs[0] instanceof Inet6Address;
if (ipv4Address != null) {
new ListenTest("localhost", ipv4Address)
.preferIPv4Stack(true)
.run(TestResult.Success);
new ListenTest("localhost", ipv4Address)
.preferIPv4Stack(true)
.preferIPv6Addresses("true")
.run(TestResult.Success);
new ListenTest("localhost", ipv4Address)
.preferIPv4Stack(true)
.preferIPv6Addresses("system")
.run(TestResult.Success);
new ListenTest("localhost", ipv4Address)
.preferIPv4Stack(false)
.run(TestResult.Success);
if (ipv6Address != null) {
// - only IPv4, so connection prom IPv6 should fail
// - only IPv4, so connection from IPv6 should fail
new ListenTest("localhost", ipv6Address)
.preferIPv4Stack(true)
.preferIPv6Addresses(true)
.preferIPv6Addresses("true")
.run(TestResult.AttachFailed);
new ListenTest("localhost", ipv6Address)
.preferIPv4Stack(true)
.preferIPv6Addresses("system")
.run(TestResult.AttachFailed);
// - listen on IPv4
new ListenTest("localhost", ipv6Address)
.preferIPv6Addresses(false)
.preferIPv6Addresses("false")
.run(TestResult.AttachFailed);
// - listen on IPv4 (preferIPv6Addresses defaults to false)
new ListenTest("localhost", ipv6Address)
.run(TestResult.AttachFailed);
// - listen on IPv6
new ListenTest("localhost", ipv6Address)
.preferIPv6Addresses(true)
.preferIPv6Addresses("true")
.run(TestResult.Success);
new ListenTest("localhost", ipv6Address)
.preferIPv6Addresses("system")
.run(systemPrefersIPv6 ? TestResult.Success : TestResult.AttachFailed);
// - listen on IPv6, connect from IPv4
new ListenTest("localhost", ipv4Address)
.preferIPv4Stack(false)
.preferIPv6Addresses("true")
.run(TestResult.AttachFailed);
// - listen on system preference, connect from IPv4
new ListenTest("localhost", ipv4Address)
.preferIPv4Stack(false)
.preferIPv6Addresses("system")
.run(systemPrefersIPv6 ? TestResult.AttachFailed : TestResult.Success);
}
} else {
if (!systemPrefersIPv6) {
throw new AssertionError("The system is IPv6-only, but systemPrefersIPv6 was unexpectedly false");
}
// IPv6-only system - expected to fail on IPv4 address
new ListenTest("localhost", ipv6Address)
.preferIPv4Stack(true)
.run(TestResult.ListenFailed);
new ListenTest("localhost", ipv6Address)
.preferIPv4Stack(true)
.preferIPv6Addresses("system")
.run(TestResult.ListenFailed);
new ListenTest("localhost", ipv6Address)
.preferIPv4Stack(true)
.preferIPv6Addresses("true")
.run(TestResult.ListenFailed);
new ListenTest("localhost", ipv6Address)
.run(TestResult.Success);
new ListenTest("localhost", ipv6Address)
.preferIPv6Addresses("system")
.run(TestResult.Success);
new ListenTest("localhost", ipv6Address)
.preferIPv6Addresses("true")
.run(TestResult.Success);
}
}
@ -100,7 +156,7 @@ public class JdwpNetProps {
private final String listenAddress;
private final InetAddress connectAddress;
private Boolean preferIPv4Stack;
private Boolean preferIPv6Addresses;
private String preferIPv6Addresses;
public ListenTest(String listenAddress, InetAddress connectAddress) {
this.listenAddress = listenAddress;
this.connectAddress = connectAddress;
@ -109,7 +165,7 @@ public class JdwpNetProps {
preferIPv4Stack = value;
return this;
}
public ListenTest preferIPv6Addresses(Boolean value) {
public ListenTest preferIPv6Addresses(String value) {
preferIPv6Addresses = value;
return this;
}
@ -120,7 +176,7 @@ public class JdwpNetProps {
options.add("-Djava.net.preferIPv4Stack=" + preferIPv4Stack.toString());
}
if (preferIPv6Addresses != null) {
options.add("-Djava.net.preferIPv6Addresses=" + preferIPv6Addresses.toString());
options.add("-Djava.net.preferIPv6Addresses=" + preferIPv6Addresses);
}
log("Starting listening debuggee at " + listenAddress
+ (expectedResult == TestResult.ListenFailed ? ": expected to fail" : ""));
@ -201,4 +257,5 @@ public class JdwpNetProps {
System.out.println(String.valueOf(o));
}
}