diff --git a/src/share/native/java/net/net_util.c b/src/share/native/java/net/net_util.c index 68776c1ce0c0f28571654c985d9340459dc220bd..d7a6de2073db46c266724501dd3f0dd863f334fd 100644 --- a/src/share/native/java/net/net_util.c +++ b/src/share/native/java/net/net_util.c @@ -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 @@ JNI_OnLoad(JavaVM *vm, void *reserved) */ IPv6_available = IPv6_supported() & (!preferIPv4Stack); initLocalAddrTable (); + parseExclusiveBindProperty(env); + return JNI_VERSION_1_2; } diff --git a/src/share/native/java/net/net_util.h b/src/share/native/java/net/net_util.h index d87ffdad2803a35a9b41b94fd521b107edb97c6c..809cbba6eb2a0dc3066f2446fa84aa722aa3101e 100644 --- a/src/share/native/java/net/net_util.h +++ b/src/share/native/java/net/net_util.h @@ -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 @@ JNIEXPORT jobject JNICALL NET_SockaddrToInetAddress(JNIEnv *env, struct sockaddr *him, int *port); void initLocalAddrTable (); +void parseExclusiveBindProperty(JNIEnv *env); void NET_SetTrafficClass(struct sockaddr *him, int trafficClass); diff --git a/src/solaris/native/java/net/net_util_md.c b/src/solaris/native/java/net/net_util_md.c index f7e6d6a02ab43ec1457fa0628ac817c5b7328d21..469f4657adba42ed38dfcf0b8177f2c6fc68fb34 100644 --- a/src/solaris/native/java/net/net_util_md.c +++ b/src/solaris/native/java/net/net_util_md.c @@ -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 @@ gai_strerror_f gai_strerror_ptr = NULL; 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 @@ void setDefaultScopeID(JNIEnv *env, struct sockaddr *him) 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 @@ void initLocalAddrTable () {} #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 @@ NET_SetSockOpt(int fd, int level, int opt, const void *arg, * 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 @@ NET_Bind(int fd, struct sockaddr *him, int len) #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 @@ NET_Bind(int fd, struct sockaddr *him, int len) 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); diff --git a/src/windows/native/java/net/net_util_md.c b/src/windows/native/java/net/net_util_md.c index 4cf522e786a908212da1c425774b4b33dba06a60..cd3efe922bc5d58abe21f76d539dabbf6942781a 100644 --- a/src/windows/native/java/net/net_util_md.c +++ b/src/windows/native/java/net/net_util_md.c @@ -126,6 +126,7 @@ DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) } void initLocalAddrTable () {} +void parseExclusiveBindProperty (JNIEnv *env) {} /* * Since winsock doesn't have the equivalent of strerror(errno) diff --git a/test/java/net/Socket/setReuseAddress/Basic.java b/test/java/net/Socket/setReuseAddress/Basic.java index 37c3f3b70b8ebd94c6fd09bf138b495804528ea0..1b5757589f97dfe520a589fe115e012f871de075 100644 --- a/test/java/net/Socket/setReuseAddress/Basic.java +++ b/test/java/net/Socket/setReuseAddress/Basic.java @@ -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 @@ public class Basic { 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(); diff --git a/test/java/net/Socket/setReuseAddress/Restart.java b/test/java/net/Socket/setReuseAddress/Restart.java index 051e322e43f9b1b2c237ad4e6702686aa7e03e3f..8287141af4c09b06c4fe5fc213526631cbec5a51 100644 --- a/test/java/net/Socket/setReuseAddress/Restart.java +++ b/test/java/net/Socket/setReuseAddress/Restart.java @@ -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 @@ public class Restart { // 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();