--- 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);
--- 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);
--- 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)
--- 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<SocketOption<?>> set = new HashSet<SocketOption<?>>(2);
set.add(StandardSocketOptions.SO_RCVBUF);
set.add(StandardSocketOptions.SO_REUSEADDR);
+ set.add(StandardSocketOptions.IP_TOS);
return Collections.unmodifiableSet(set);
}
}
--- 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
--- 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
--- 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
--- 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;