# HG changeset patch # User michaelm # Date 1403708142 -3600 # Node ID f58832169add91c2da915200d3b8e158817cb0bc # Parent 365cba5326f96cd006e01366927134e28031cbcf 8029607: Type of Service (TOS) cannot be set in IPv6 header Reviewed-by: alanb diff -r 365cba5326f9 -r f58832169add jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c --- a/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c Wed Jun 25 18:49:02 2014 +0800 +++ b/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c Wed Jun 25 15:55:42 2014 +0100 @@ -110,6 +110,7 @@ emit_inet("StandardSocketOptions.IP_MULTICAST_LOOP", IPPROTO_IP, IP_MULTICAST_LOOP); #ifdef AF_INET6 + emit_inet6("StandardSocketOptions.IP_TOS", IPPROTO_IPV6, IPV6_TCLASS); emit_inet6("StandardSocketOptions.IP_MULTICAST_IF", IPPROTO_IPV6, IPV6_MULTICAST_IF); emit_inet6("StandardSocketOptions.IP_MULTICAST_TTL", IPPROTO_IPV6, IPV6_MULTICAST_HOPS); emit_inet6("StandardSocketOptions.IP_MULTICAST_LOOP", IPPROTO_IPV6, IPV6_MULTICAST_LOOP); diff -r 365cba5326f9 -r f58832169add jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java --- a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java Wed Jun 25 18:49:02 2014 +0800 +++ b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java Wed Jun 25 15:55:42 2014 +0100 @@ -195,15 +195,8 @@ synchronized (stateLock) { ensureOpen(); - if (name == StandardSocketOptions.IP_TOS) { - // IPv4 only; no-op for IPv6 - if (family == StandardProtocolFamily.INET) { - Net.setSocketOption(fd, family, name, value); - } - return this; - } - - if (name == StandardSocketOptions.IP_MULTICAST_TTL || + if (name == StandardSocketOptions.IP_TOS || + name == StandardSocketOptions.IP_MULTICAST_TTL || name == StandardSocketOptions.IP_MULTICAST_LOOP) { // options are protocol dependent @@ -256,16 +249,8 @@ synchronized (stateLock) { ensureOpen(); - if (name == StandardSocketOptions.IP_TOS) { - // IPv4 only; always return 0 on IPv6 - if (family == StandardProtocolFamily.INET) { - return (T) Net.getSocketOption(fd, family, name); - } else { - return (T) Integer.valueOf(0); - } - } - - if (name == StandardSocketOptions.IP_MULTICAST_TTL || + if (name == StandardSocketOptions.IP_TOS || + name == StandardSocketOptions.IP_MULTICAST_TTL || name == StandardSocketOptions.IP_MULTICAST_LOOP) { return (T) Net.getSocketOption(fd, family, name); diff -r 365cba5326f9 -r f58832169add jdk/src/share/classes/sun/nio/ch/Net.java --- a/jdk/src/share/classes/sun/nio/ch/Net.java Wed Jun 25 18:49:02 2014 +0800 +++ b/jdk/src/share/classes/sun/nio/ch/Net.java Wed Jun 25 15:55:42 2014 +0100 @@ -352,7 +352,8 @@ } boolean mayNeedConversion = (family == UNSPEC); - setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg); + boolean isIPv6 = (family == StandardProtocolFamily.INET6); + setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg, isIPv6); } static Object getSocketOption(FileDescriptor fd, ProtocolFamily family, @@ -499,7 +500,7 @@ throws IOException; private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion, - int level, int opt, int arg) + int level, int opt, int arg, boolean isIPv6) throws IOException; static native int poll(FileDescriptor fd, int events, long timeout) diff -r 365cba5326f9 -r f58832169add jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java --- a/jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Wed Jun 25 18:49:02 2014 +0800 +++ b/jdk/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Wed Jun 25 15:55:42 2014 +0100 @@ -133,6 +133,14 @@ synchronized (stateLock) { if (!isOpen()) throw new ClosedChannelException(); + + if (name == StandardSocketOptions.IP_TOS) { + ProtocolFamily family = Net.isIPv6Available() ? + StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; + Net.setSocketOption(fd, family, name, value); + return this; + } + if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) { @@ -177,6 +185,7 @@ HashSet> set = new HashSet>(2); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + set.add(StandardSocketOptions.IP_TOS); return Collections.unmodifiableSet(set); } } diff -r 365cba5326f9 -r f58832169add jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java --- a/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java Wed Jun 25 18:49:02 2014 +0800 +++ b/jdk/src/share/classes/sun/nio/ch/SocketChannelImpl.java Wed Jun 25 15:55:42 2014 +0100 @@ -173,14 +173,14 @@ if (!isOpen()) throw new ClosedChannelException(); - // special handling for IP_TOS: no-op when IPv6 if (name == StandardSocketOptions.IP_TOS) { - if (!Net.isIPv6Available()) - Net.setSocketOption(fd, StandardProtocolFamily.INET, name, value); + ProtocolFamily family = Net.isIPv6Available() ? + StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; + Net.setSocketOption(fd, family, name, value); return this; - } else if (name == StandardSocketOptions.SO_REUSEADDR && - Net.useExclusiveBind()) - { + } + + if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) { // SO_REUSEADDR emulated when using exclusive bind isReuseAddress = (Boolean)value; return this; @@ -215,8 +215,9 @@ // special handling for IP_TOS: always return 0 when IPv6 if (name == StandardSocketOptions.IP_TOS) { - return (Net.isIPv6Available()) ? (T) Integer.valueOf(0) : - (T) Net.getSocketOption(fd, StandardProtocolFamily.INET, name); + ProtocolFamily family = Net.isIPv6Available() ? + StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; + return (T) Net.getSocketOption(fd, family, name); } // no options that require special handling diff -r 365cba5326f9 -r f58832169add jdk/src/solaris/native/java/net/net_util_md.c --- a/jdk/src/solaris/native/java/net/net_util_md.c Wed Jun 25 18:49:02 2014 +0800 +++ b/jdk/src/solaris/native/java/net/net_util_md.c Wed Jun 25 15:55:42 2014 +0100 @@ -1317,7 +1317,7 @@ * or sending UDP packet. * 2. IPv6 on Linux: By default Linux ignores flowinfo * field so enable IPV6_FLOWINFO_SEND so that flowinfo - * will be examined. + * will be examined. We also set the IPv4 TOS option in this case. * 3. IPv4: set socket option based on ToS and Precedence * fields (otherwise get invalid argument) */ @@ -1333,8 +1333,10 @@ #if defined(AF_INET6) && defined(__linux__) if (ipv6_available()) { int optval = 1; - return setsockopt(fd, IPPROTO_IPV6, IPV6_FLOWINFO_SEND, - (void *)&optval, sizeof(optval)); + if (setsockopt(fd, IPPROTO_IPV6, IPV6_FLOWINFO_SEND, + (void *)&optval, sizeof(optval)) < 0) { + return -1; + } } #endif diff -r 365cba5326f9 -r f58832169add jdk/src/solaris/native/sun/nio/ch/Net.c --- a/jdk/src/solaris/native/sun/nio/ch/Net.c Wed Jun 25 18:49:02 2014 +0800 +++ b/jdk/src/solaris/native/sun/nio/ch/Net.c Wed Jun 25 15:55:42 2014 +0100 @@ -435,7 +435,8 @@ JNIEXPORT void JNICALL Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo, - jboolean mayNeedConversion, jint level, jint opt, jint arg) + jboolean mayNeedConversion, jint level, + jint opt, jint arg, jboolean isIPv6) { int result; struct linger linger; @@ -478,6 +479,12 @@ JNU_JAVANETPKG "SocketException", "sun.nio.ch.Net.setIntOption"); } +#ifdef __linux__ + if (level == IPPROTO_IPV6 && opt == IPV6_TCLASS && isIPv6) { + // set the V4 option also + setsockopt(fdval(env, fdo), IPPROTO_IP, IP_TOS, parg, arglen); + } +#endif } JNIEXPORT jint JNICALL diff -r 365cba5326f9 -r f58832169add jdk/src/windows/native/sun/nio/ch/Net.c --- a/jdk/src/windows/native/sun/nio/ch/Net.c Wed Jun 25 18:49:02 2014 +0800 +++ b/jdk/src/windows/native/sun/nio/ch/Net.c Wed Jun 25 15:55:42 2014 +0100 @@ -319,7 +319,7 @@ JNIEXPORT void JNICALL Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo, - jboolean mayNeedConversion, jint level, jint opt, jint arg) + jboolean mayNeedConversion, jint level, jint opt, jint arg, jboolean ipv6) { struct linger linger; char *parg;