diff --git a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java index fe32f63880b1ca80f826e7cf961c83dddaafe52b..a34286bddb418777b691d1756366627d1cc6ab31 100644 --- a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -195,15 +195,8 @@ class DatagramChannelImpl 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 @@ class DatagramChannelImpl 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 --git a/src/share/classes/sun/nio/ch/Net.java b/src/share/classes/sun/nio/ch/Net.java index 753e541731099227457a623bff3fd78474b284d8..37823e98c550f6e8ae5a382708d508c634d5eb1f 100644 --- a/src/share/classes/sun/nio/ch/Net.java +++ b/src/share/classes/sun/nio/ch/Net.java @@ -352,7 +352,8 @@ public class Net { } 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 @@ public class Net { 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 --git a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java index 6b7d51bd46a362efbc1eda9d67e39619ff62212e..db73c725c57bb0346406ed4f50e52a2f36da77e8 100644 --- a/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/ServerSocketChannelImpl.java @@ -133,6 +133,14 @@ class ServerSocketChannelImpl 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 @@ class ServerSocketChannelImpl 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 --git a/src/share/classes/sun/nio/ch/SocketChannelImpl.java b/src/share/classes/sun/nio/ch/SocketChannelImpl.java index 1e36aed74d02ee59aa3f7bbe1537ed2b6dd44aac..7b694efe6ade1c48b9f56dd3130f7443c6f485a6 100644 --- a/src/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/src/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -173,14 +173,14 @@ class SocketChannelImpl 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 @@ class SocketChannelImpl // 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 --git a/src/share/native/sun/nio/ch/genSocketOptionRegistry.c b/src/share/native/sun/nio/ch/genSocketOptionRegistry.c index d5ed5d7a87e35b6b341e792cec715f58587e7b3f..41bd5484ab7fdaad36591a2dfad18b6d2b4b8542 100644 --- a/src/share/native/sun/nio/ch/genSocketOptionRegistry.c +++ b/src/share/native/sun/nio/ch/genSocketOptionRegistry.c @@ -110,6 +110,7 @@ int main(int argc, const char* argv[]) { 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 --git a/src/solaris/native/java/net/net_util_md.c b/src/solaris/native/java/net/net_util_md.c index 8ba8732ed3f9d85c182234334a70b7a31eda3a9d..769e5405024914d5f48e4395aff932949341bc48 100644 --- a/src/solaris/native/java/net/net_util_md.c +++ b/src/solaris/native/java/net/net_util_md.c @@ -1310,7 +1310,7 @@ NET_SetSockOpt(int fd, int level, int opt, const void *arg, * 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) */ @@ -1326,8 +1326,10 @@ NET_SetSockOpt(int fd, int level, int opt, const void *arg, #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 --git a/src/solaris/native/sun/nio/ch/Net.c b/src/solaris/native/sun/nio/ch/Net.c index 2846217bbb65171273485bb232c6f94957a81e28..ae7f5794316527d1c77c5b7ec08bd06c93625ced 100644 --- a/src/solaris/native/sun/nio/ch/Net.c +++ b/src/solaris/native/sun/nio/ch/Net.c @@ -478,7 +478,8 @@ Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo, 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; @@ -521,6 +522,12 @@ Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo, 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 --git a/src/windows/native/sun/nio/ch/Net.c b/src/windows/native/sun/nio/ch/Net.c index 9720d80ef625bfd40b526993dca2d7ca74e1de0f..fc96ea206aeda1d8344c6b35834840c7dd3fe59a 100644 --- a/src/windows/native/sun/nio/ch/Net.c +++ b/src/windows/native/sun/nio/ch/Net.c @@ -319,7 +319,7 @@ Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo, 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;