7123896: Unexpected behavior due to Solaris using separate IPv4 and IPv6 port spaces
authorcoffeys
Thu, 17 May 2012 12:21:16 +0100
changeset 13043 10fa4f21ea0f
parent 13042 44d134b0557e
child 13044 8411854afc2b
7123896: Unexpected behavior due to Solaris using separate IPv4 and IPv6 port spaces Reviewed-by: alanb
jdk/src/share/native/java/net/net_util.c
jdk/src/share/native/java/net/net_util.h
jdk/src/solaris/native/java/net/net_util_md.c
jdk/src/windows/native/java/net/net_util_md.c
jdk/test/java/net/Socket/setReuseAddress/Basic.java
jdk/test/java/net/Socket/setReuseAddress/Restart.java
--- a/jdk/src/share/native/java/net/net_util.c	Tue May 08 07:34:53 2012 -0700
+++ b/jdk/src/share/native/java/net/net_util.c	Thu May 17 12:21:16 2012 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2012, 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
@@ -68,6 +68,8 @@
     */
     IPv6_available = IPv6_supported() & (!preferIPv4Stack);
     initLocalAddrTable ();
+    parseExclusiveBindProperty(env);
+
     return JNI_VERSION_1_2;
 }
 
--- a/jdk/src/share/native/java/net/net_util.h	Tue May 08 07:34:53 2012 -0700
+++ b/jdk/src/share/native/java/net/net_util.h	Thu May 17 12:21:16 2012 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
@@ -120,6 +120,7 @@
 NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port);
 
 void initLocalAddrTable ();
+void parseExclusiveBindProperty(JNIEnv *env);
 
 void
 NET_SetTrafficClass(struct sockaddr *him, int trafficClass);
--- a/jdk/src/solaris/native/java/net/net_util_md.c	Tue May 08 07:34:53 2012 -0700
+++ b/jdk/src/solaris/native/java/net/net_util_md.c	Thu May 17 12:21:16 2012 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
@@ -76,7 +76,7 @@
 getnameinfo_f getnameinfo_ptr = NULL;
 
 /*
- * EXCLBIND socket options only on Solaris 8 & 9.
+ * EXCLBIND socket options only on Solaris
  */
 #if defined(__solaris__) && !defined(TCP_EXCLBIND)
 #define TCP_EXCLBIND            0x21
@@ -113,6 +113,7 @@
 static int init_tcp_max_buf, init_udp_max_buf;
 static int tcp_max_buf;
 static int udp_max_buf;
+static int useExclBind = 0;
 
 /*
  * Get the specified parameter from the specified driver. The value
@@ -747,6 +748,26 @@
 
 #endif
 
+void parseExclusiveBindProperty(JNIEnv *env) {
+#ifdef __solaris__
+    jstring s, flagSet;
+    jclass iCls;
+    jmethodID mid;
+
+    s = (*env)->NewStringUTF(env, "sun.net.useExclusiveBind");
+    CHECK_NULL(s);
+    iCls = (*env)->FindClass(env, "java/lang/System");
+    CHECK_NULL(iCls);
+    mid = (*env)->GetStaticMethodID(env, iCls, "getProperty",
+                "(Ljava/lang/String;)Ljava/lang/String;");
+    CHECK_NULL(mid);
+    flagSet = (*env)->CallStaticObjectMethod(env, iCls, mid, s);
+    if (flagSet != NULL) {
+        useExclBind = 1;
+    }
+#endif
+}
+
 /* In the case of an IPv4 Inetaddress this method will return an
  * IPv4 mapped address where IPv6 is available and v4MappedAddress is TRUE.
  * Otherwise it will return a sockaddr_in structure for an IPv4 InetAddress.
@@ -1450,8 +1471,8 @@
  * Linux allows a socket to bind to 127.0.0.255 which must be
  * caught.
  *
- * On Solaris 8/9 with IPv6 enabled we must use an exclusive
- * bind to guaranteed a unique port number across the IPv4 and
+ * On Solaris with IPv6 enabled we must use an exclusive
+ * bind to guarantee a unique port number across the IPv4 and
  * IPv6 port spaces.
  *
  */
@@ -1481,10 +1502,10 @@
 
 #if defined(__solaris__) && defined(AF_INET6)
     /*
-     * Solaris 8/9 have seperate IPv4 and IPv6 port spaces so we
+     * Solaris has separate IPv4 and IPv6 port spaces so we
      * use an exclusive bind when SO_REUSEADDR is not used to
      * give the illusion of a unified port space.
-     * This also avoid problems with IPv6 sockets connecting
+     * This also avoids problems with IPv6 sockets connecting
      * to IPv4 mapped addresses whereby the socket conversion
      * results in a late bind that fails because the
      * corresponding IPv4 port is in use.
@@ -1493,11 +1514,12 @@
         int arg, len;
 
         len = sizeof(arg);
-        if (getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&arg,
-                       &len) == 0) {
-            if (arg == 0) {
+        if (useExclBind || getsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+                       (char *)&arg, &len) == 0) {
+            if (useExclBind || arg == 0) {
                 /*
-                 * SO_REUSEADDR is disabled so enable TCP_EXCLBIND or
+                 * SO_REUSEADDR is disabled or sun.net.useExclusiveBind
+                 * property is true so enable TCP_EXCLBIND or
                  * UDP_EXCLBIND
                  */
                 len = sizeof(arg);
--- a/jdk/src/windows/native/java/net/net_util_md.c	Tue May 08 07:34:53 2012 -0700
+++ b/jdk/src/windows/native/java/net/net_util_md.c	Thu May 17 12:21:16 2012 +0100
@@ -126,6 +126,7 @@
 }
 
 void initLocalAddrTable () {}
+void parseExclusiveBindProperty (JNIEnv *env) {}
 
 /*
  * Since winsock doesn't have the equivalent of strerror(errno)
--- a/jdk/test/java/net/Socket/setReuseAddress/Basic.java	Tue May 08 07:34:53 2012 -0700
+++ b/jdk/test/java/net/Socket/setReuseAddress/Basic.java	Thu May 17 12:21:16 2012 +0100
@@ -26,6 +26,8 @@
  * @bug 4476378
  * @summary Check the specific behaviour of the setReuseAddress(boolean)
  * method.
+ * @run main Basic
+ * @run main/othervm -Dsun.net.useExclusiveBind Basic
  */
 import java.net.*;
 
@@ -170,7 +172,12 @@
             s2.bind( new InetSocketAddress(s1.getLocalPort()) );
             passed();
         } catch (BindException e) {
-            failed();
+            if (System.getProperty("sun.net.useExclusiveBind") != null) {
+                // exclusive bind enabled - expected result
+                passed();
+            } else {
+                failed();
+            }
         }
         s2.close();
 
--- a/jdk/test/java/net/Socket/setReuseAddress/Restart.java	Tue May 08 07:34:53 2012 -0700
+++ b/jdk/test/java/net/Socket/setReuseAddress/Restart.java	Thu May 17 12:21:16 2012 +0100
@@ -26,6 +26,8 @@
  * @bug 4476378
  * @summary Check that SO_REUSEADDR allows a server to restart
  *          after a crash.
+ * @run main Restart
+ * @run main/othervm -Dsun.net.useExclusiveBind Restart
  */
 import java.net.*;
 
@@ -57,6 +59,12 @@
 
             // close the client socket
             s1.close();
+        } catch (BindException be) {
+            if (System.getProperty("sun.net.useExclusiveBind") != null) {
+                // exclusive bind, expected exception
+            } else {
+                throw be;
+            }
         } finally {
             if (ss != null) ss.close();
             if (s1 != null) s1.close();