8222562: Don't set IPV6_V6ONLY when IPv4 is not available
Reviewed-by: dfuchs, chegar
Contributed-by: aeubanks@google.com
--- a/src/java.base/share/native/libnet/net_util.c Thu Apr 25 18:41:52 2019 -0400
+++ b/src/java.base/share/native/libnet/net_util.c Tue Apr 16 13:16:49 2019 -0700
@@ -27,12 +27,19 @@
#include "java_net_InetAddress.h"
+int IPv4_supported();
int IPv6_supported();
int reuseport_supported();
+static int IPv4_available;
static int IPv6_available;
static int REUSEPORT_available;
+JNIEXPORT jint JNICALL ipv4_available()
+{
+ return IPv4_available;
+}
+
JNIEXPORT jint JNICALL ipv6_available()
{
return IPv6_available;
@@ -68,6 +75,7 @@
* check now whether we have IPv6 on this platform and if the
* supporting socket APIs are available
*/
+ IPv4_available = IPv4_supported();
IPv6_available = IPv6_supported() & (!preferIPv4Stack);
/* check if SO_REUSEPORT is supported on this platform */
--- a/src/java.base/share/native/libnet/net_util.h Thu Apr 25 18:41:52 2019 -0400
+++ b/src/java.base/share/native/libnet/net_util.h Tue Apr 16 13:16:49 2019 -0700
@@ -126,6 +126,7 @@
jfieldID NET_GetFileDescriptorID(JNIEnv *env);
+JNIEXPORT jint JNICALL ipv4_available();
JNIEXPORT jint JNICALL ipv6_available();
JNIEXPORT jint JNICALL reuseport_available();
--- a/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Thu Apr 25 18:41:52 2019 -0400
+++ b/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Tue Apr 16 13:16:49 2019 -0700
@@ -915,8 +915,10 @@
return;
}
- /* Disable IPV6_V6ONLY to ensure dual-socket support */
- if (domain == AF_INET6) {
+ /*
+ * If IPv4 is available, disable IPV6_V6ONLY to ensure dual-socket support.
+ */
+ if (domain == AF_INET6 && ipv4_available()) {
arg = 0;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
sizeof(int)) < 0) {
--- a/src/java.base/unix/native/libnet/PlainSocketImpl.c Thu Apr 25 18:41:52 2019 -0400
+++ b/src/java.base/unix/native/libnet/PlainSocketImpl.c Tue Apr 16 13:16:49 2019 -0700
@@ -187,8 +187,10 @@
return;
}
- /* Disable IPV6_V6ONLY to ensure dual-socket support */
- if (domain == AF_INET6) {
+ /*
+ * If IPv4 is available, disable IPV6_V6ONLY to ensure dual-socket support.
+ */
+ if (domain == AF_INET6 && ipv4_available()) {
int arg = 0;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
sizeof(int)) < 0) {
--- a/src/java.base/unix/native/libnet/net_util_md.c Thu Apr 25 18:41:52 2019 -0400
+++ b/src/java.base/unix/native/libnet/net_util_md.c Tue Apr 16 13:16:49 2019 -0700
@@ -278,6 +278,16 @@
return (*env)->GetFieldID(env, cls, "fd", "I");
}
+jint IPv4_supported()
+{
+ int fd = socket(AF_INET, SOCK_STREAM, 0) ;
+ if (fd < 0) {
+ return JNI_FALSE;
+ }
+ close(fd);
+ return JNI_TRUE;
+}
+
#if defined(DONT_ENABLE_IPV6)
jint IPv6_supported()
{
--- a/src/java.base/unix/native/libnio/ch/Net.c Thu Apr 25 18:41:52 2019 -0400
+++ b/src/java.base/unix/native/libnio/ch/Net.c Tue Apr 16 13:16:49 2019 -0700
@@ -216,8 +216,10 @@
return handleSocketError(env, errno);
}
- /* Disable IPV6_V6ONLY to ensure dual-socket support */
- if (domain == AF_INET6) {
+ /*
+ * If IPv4 is available, disable IPV6_V6ONLY to ensure dual-socket support.
+ */
+ if (domain == AF_INET6 && ipv4_available()) {
int arg = 0;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
sizeof(int)) < 0) {
--- a/src/java.base/windows/native/libnet/net_util_md.c Thu Apr 25 18:41:52 2019 -0400
+++ b/src/java.base/windows/native/libnet/net_util_md.c Tue Apr 16 13:16:49 2019 -0700
@@ -214,6 +214,12 @@
return (*env)->GetFieldID(env, cls, "fd", "I");
}
+jint IPv4_supported()
+{
+ /* TODO: properly check for IPv4 support on Windows */
+ return JNI_TRUE;
+}
+
jint IPv6_supported()
{
SOCKET s = socket(AF_INET6, SOCK_STREAM, 0) ;