Backport a long standing bug fix from OpenJDK7, i.e., disable IPV6_V6ONLY

option when IPv6 is enabled and failed to create a socket.

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6342561
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6882910

For in-depth analysis of this problem from FreeBSD perspective, please see:

http://diario.beerensalat.info/2008/10/12/java_and_ipv6_on_bsd.html
This commit is contained in:
Jung-uk Kim 2011-03-03 23:22:05 +00:00
parent c20add828e
commit 6fac48313f
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=270217
2 changed files with 219 additions and 35 deletions

View File

@ -7,6 +7,7 @@
PORTNAME= openjdk6
PORTVERSION= b22
PORTREVISION= 1
CATEGORIES= java devel
MASTER_SITES= http://download.java.net/openjdk/jdk6/promoted/${PORTVERSION}/ \
http://download.java.net/jaxp/openjdk/jdk6/:jaxp \

View File

@ -16309,8 +16309,8 @@
memset((char *) &if2, 0, sizeof(if2));
strcpy(if2.ifr_name, name_utf);
--- jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c 2011-01-20 18:54:41.000000000 -0500
+++ jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c 2011-02-01 17:46:56.000000000 -0500
--- jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c 2011-02-28 11:06:49.000000000 -0500
+++ jdk/src/solaris/native/java/net/PlainDatagramSocketImpl.c 2011-03-03 15:31:37.000000000 -0500
@@ -23,12 +23,12 @@
* questions.
*/
@ -16383,7 +16383,69 @@
#else
JVM_Connect(fd, 0, 0);
#endif
@@ -2374,18 +2388,30 @@
@@ -1057,31 +1071,38 @@
Java_java_net_PlainDatagramSocketImpl_datagramSocketCreate(JNIEnv *env,
jobject this) {
jobject fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
- int fd;
-
- int arg = -1;
- 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__
@@ -1094,7 +1115,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));
@@ -2374,18 +2395,30 @@
mname6.ipv6mr_interface = idx;
}
@ -16417,9 +16479,82 @@
}
}
}
--- jdk/src/solaris/native/java/net/PlainSocketImpl.c 2011-01-20 18:54:41.000000000 -0500
+++ jdk/src/solaris/native/java/net/PlainSocketImpl.c 2011-02-01 17:46:57.000000000 -0500
@@ -528,9 +528,11 @@
--- jdk/src/solaris/native/java/net/PlainSocketImpl.c 2011-02-28 11:06:49.000000000 -0500
+++ jdk/src/solaris/native/java/net/PlainSocketImpl.c 2011-03-03 15:31:37.000000000 -0500
@@ -253,7 +253,12 @@
jboolean stream) {
jobject fdObj, ssObj;
int fd;
- int arg = -1;
+ 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");
@@ -267,25 +272,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.
@@ -294,9 +303,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);
}
/*
@@ -528,9 +543,11 @@
if (connect_rv == JVM_IO_INTR) {
JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
"operation interrupted");
@ -16442,8 +16577,8 @@
/*
* The fd table and the number of file descriptors
--- jdk/src/solaris/native/java/net/net_util_md.c 2011-01-20 18:54:41.000000000 -0500
+++ jdk/src/solaris/native/java/net/net_util_md.c 2011-02-01 17:46:57.000000000 -0500
--- jdk/src/solaris/native/java/net/net_util_md.c 2011-02-28 11:06:49.000000000 -0500
+++ jdk/src/solaris/native/java/net/net_util_md.c 2011-03-03 16:56:30.000000000 -0500
@@ -34,6 +34,15 @@
#include <stdlib.h>
#include <dlfcn.h>
@ -16475,6 +16610,15 @@
jint IPv6_supported()
{
#ifndef AF_INET6
@@ -229,7 +246,7 @@
int fd;
void *ipv6_fn;
SOCKADDR sa;
- int sa_len = sizeof(sa);
+ socklen_t sa_len = sizeof(sa);
fd = JVM_Socket(AF_INET6, SOCK_STREAM, 0) ;
if (fd < 0) {
@@ -355,6 +372,7 @@
close(fd);
return JNI_TRUE;
@ -16494,6 +16638,15 @@
/*
* On Linux if we are connecting to a link-local address
* we need to specify the interface in the scope_id (2.4 kernel only)
@@ -1086,7 +1108,7 @@
}
#endif
- rv = getsockopt(fd, level, opt, result, len);
+ rv = getsockopt(fd, level, opt, result, (socklen_t)len);
if (rv < 0) {
return rv;
}
@@ -1133,6 +1155,24 @@
#define IPTOS_PREC_MASK 0xe0
#endif
@ -16530,7 +16683,7 @@
/*
* SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris need to
* ensure that value is <= max_buf as otherwise we get
@@ -1212,6 +1256,83 @@
@@ -1212,6 +1256,84 @@
}
#endif
@ -16583,7 +16736,8 @@
+ * SO_REUSEPORT as well for that combination.
+ */
+ if (level == SOL_SOCKET && opt == SO_REUSEADDR) {
+ int sotype, arglen;
+ int sotype;
+ socklen_t arglen;
+
+ arglen = sizeof(sotype);
+ if (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void *)&sotype, &arglen) < 0) {
@ -18400,11 +18554,54 @@
+#ifdef __cplusplus
+}
+#endif
--- jdk/src/solaris/native/sun/nio/ch/Net.c 2011-01-20 18:54:43.000000000 -0500
+++ jdk/src/solaris/native/sun/nio/ch/Net.c 2011-02-01 17:46:57.000000000 -0500
@@ -140,8 +140,31 @@
--- jdk/src/solaris/native/sun/nio/ch/Net.c 2011-02-28 11:06:50.000000000 -0500
+++ jdk/src/solaris/native/sun/nio/ch/Net.c 2011-03-03 16:07:56.000000000 -0500
@@ -60,17 +60,33 @@
jboolean reuse)
{
int fd;
-
+ int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
#ifdef AF_INET6
- if (ipv6_available())
- fd = socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
- else
-#endif /* AF_INET6 */
- fd = socket(AF_INET, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
+ int domain = ipv6_available() ? AF_INET6 : AF_INET;
+#else
+ int domain = AF_INET;
+#endif
+ fd = socket(domain, type, 0);
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 (NET_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
@@ -138,10 +154,33 @@
Java_sun_nio_ch_Net_localPort(JNIEnv *env, jclass clazz, jobject fdo)
{
SOCKADDR sa;
int sa_len = SOCKADDR_LEN;
- int sa_len = SOCKADDR_LEN;
+ socklen_t sa_len = SOCKADDR_LEN;
if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
+#ifdef _ALLBSD_SOURCE
+ /*
@ -18434,8 +18631,12 @@
}
return NET_GetPortFromSockaddr((struct sockaddr *)&sa);
}
@@ -153,12 +176,76 @@
int sa_len = SOCKADDR_LEN;
@@ -150,15 +189,79 @@
Java_sun_nio_ch_Net_localInetAddress(JNIEnv *env, jclass clazz, jobject fdo)
{
SOCKADDR sa;
- int sa_len = SOCKADDR_LEN;
+ socklen_t sa_len = SOCKADDR_LEN;
int port;
if (getsockname(fdval(env, fdo), (struct sockaddr *)&sa, &sa_len) < 0) {
- handleSocketError(env, errno);
@ -18513,25 +18714,7 @@
#ifdef NEEDED
@@ -224,7 +311,7 @@
int result;
struct linger linger;
void *arg;
- int arglen;
+ socklen_t arglen;
if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
JNU_ThrowByNameWithLastError(env,
@@ -262,7 +349,7 @@
int result;
struct linger linger;
void *parg;
- int arglen;
+ socklen_t arglen;
if (NET_MapSocketOption(opt, &klevel, &kopt) < 0) {
JNU_ThrowByNameWithLastError(env,
@@ -304,9 +391,11 @@
@@ -304,9 +407,11 @@
switch (errorValue) {
case EINPROGRESS: /* Non-blocking connect */
return 0;