6882910: Unexplained lack of IP4 network ability when transparent IP6 to IP4 is disabled.
authorchegar
Tue, 10 Aug 2010 17:30:43 +0100
changeset 6299 a44d48dbcd50
parent 6298 470b6c49fe5c
child 6300 700ec2a5d680
6882910: Unexplained lack of IP4 network ability when transparent IP6 to IP4 is disabled. Reviewed-by: alanb
jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c
jdk/src/solaris/native/java/net/PlainSocketImpl.c
jdk/src/solaris/native/sun/nio/ch/Net.c
--- a/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c	Tue Aug 10 10:07:33 2010 -0400
+++ b/jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c	Tue Aug 10 17:30:43 2010 +0100
@@ -1052,30 +1052,38 @@
 Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env,
                                                            jobject this) {
     jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
-    int fd;
-
-    int t = 1;
+    int fd, t = 1;
+#ifdef AF_INET6
+    int domain = ipv6_available() ? AF_INET6 : AF_INET;
+#else
+    int domain = AF_INET;
+#endif
 
     if (IS_NULL(fdObj)) {
         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
                         "Socket closed");
         return;
-    } else {
-#ifdef AF_INET6
-        if (ipv6_available()) {
-            fd =  JVM_Socket(AF_INET6, SOCK_DGRAM, 0);
-        } else
-#endif /* AF_INET6 */
-            {
-                fd =  JVM_Socket(AF_INET, SOCK_DGRAM, 0);
-            }
     }
-    if (fd == JVM_IO_ERR) {
+
+    if ((fd = JVM_Socket(domain, SOCK_DGRAM, 0)) == JVM_IO_ERR) {
         NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException",
                        "Error creating socket");
         return;
     }
 
+#ifdef AF_INET6
+    /* Disable IPV6_V6ONLY to ensure dual-socket support */
+    if (domain == AF_INET6) {
+        int arg = 0;
+        if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
+                       sizeof(int)) < 0) {
+            NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
+            close(fd);
+            return;
+        }
+    }
+#endif /* AF_INET6 */
+
      setsockopt(fd, SOL_SOCKET, SO_BROADCAST, (char*) &t, sizeof(int));
 
 #ifdef __linux__
@@ -1088,7 +1096,7 @@
      * On Linux for IPv6 sockets we must set the hop limit
      * to 1 to be compatible with default ttl of 1 for IPv4 sockets.
      */
-    if (ipv6_available()) {
+    if (domain == AF_INET6) {
         int ttl = 1;
         setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&ttl,
                    sizeof(ttl));
--- a/jdk/src/solaris/native/java/net/PlainSocketImpl.c	Tue Aug 10 10:07:33 2010 -0400
+++ b/jdk/src/solaris/native/java/net/PlainSocketImpl.c	Tue Aug 10 17:30:43 2010 +0100
@@ -181,6 +181,12 @@
                                            jboolean stream) {
     jobject fdObj, ssObj;
     int fd;
+    int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
+#ifdef AF_INET6
+    int domain = ipv6_available() ? AF_INET6 : AF_INET;
+#else
+    int domain = AF_INET;
+#endif
 
     if (socketExceptionCls == NULL) {
         jclass c = (*env)->FindClass(env, "java/net/SocketException");
@@ -194,25 +200,29 @@
         (*env)->ThrowNew(env, socketExceptionCls, "null fd object");
         return;
     }
-#ifdef AF_INET6
-    if (ipv6_available()) {
-        fd = JVM_Socket(AF_INET6, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
-    } else
-#endif /* AF_INET6 */
-        {
-            fd = JVM_Socket(AF_INET, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
-        }
-    if (fd == JVM_IO_ERR) {
+
+    if ((fd = JVM_Socket(domain, type, 0)) == JVM_IO_ERR) {
         /* note: if you run out of fds, you may not be able to load
          * the exception class, and get a NoClassDefFoundError
          * instead.
          */
         NET_ThrowNew(env, errno, "can't create socket");
         return;
-    } else {
-        (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
     }
 
+#ifdef AF_INET6
+    /* Disable IPV6_V6ONLY to ensure dual-socket support */
+    if (domain == AF_INET6) {
+        int arg = 0;
+        if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
+                       sizeof(int)) < 0) {
+            NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
+            close(fd);
+            return;
+        }
+    }
+#endif /* AF_INET6 */
+
     /*
      * If this is a server socket then enable SO_REUSEADDR
      * automatically and set to non blocking.
@@ -221,9 +231,15 @@
     if (ssObj != NULL) {
         int arg = 1;
         SET_NONBLOCKING(fd);
-        JVM_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
-            sizeof(arg));
+        if (JVM_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
+                           sizeof(arg)) < 0) {
+            NET_ThrowNew(env, errno, "cannot set SO_REUSEADDR");
+            close(fd);
+            return;
+        }
     }
+
+    (*env)->SetIntField(env, fdObj, IO_fd_fdID, fd);
 }
 
 /*
--- a/jdk/src/solaris/native/sun/nio/ch/Net.c	Tue Aug 10 10:07:33 2010 -0400
+++ b/jdk/src/solaris/native/sun/nio/ch/Net.c	Tue Aug 10 17:30:43 2010 +0100
@@ -170,6 +170,22 @@
     if (fd < 0) {
         return handleSocketError(env, errno);
     }
+
+#ifdef AF_INET6
+    /* Disable IPV6_V6ONLY to ensure dual-socket support */
+    if (domain == AF_INET6) {
+        int arg = 0;
+        if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
+                       sizeof(int)) < 0) {
+            JNU_ThrowByNameWithLastError(env,
+                                         JNU_JAVANETPKG "SocketException",
+                                         "sun.nio.ch.Net.setIntOption");
+            close(fd);
+            return -1;
+        }
+    }
+#endif
+
     if (reuse) {
         int arg = 1;
         if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,