提交 e80a5178 编写于 作者: M michaelm

8029607: Type of Service (TOS) cannot be set in IPv6 header

Reviewed-by: alanb
上级 0faa50b0
...@@ -195,15 +195,8 @@ class DatagramChannelImpl ...@@ -195,15 +195,8 @@ class DatagramChannelImpl
synchronized (stateLock) { synchronized (stateLock) {
ensureOpen(); ensureOpen();
if (name == StandardSocketOptions.IP_TOS) { if (name == StandardSocketOptions.IP_TOS ||
// IPv4 only; no-op for IPv6 name == StandardSocketOptions.IP_MULTICAST_TTL ||
if (family == StandardProtocolFamily.INET) {
Net.setSocketOption(fd, family, name, value);
}
return this;
}
if (name == StandardSocketOptions.IP_MULTICAST_TTL ||
name == StandardSocketOptions.IP_MULTICAST_LOOP) name == StandardSocketOptions.IP_MULTICAST_LOOP)
{ {
// options are protocol dependent // options are protocol dependent
...@@ -256,16 +249,8 @@ class DatagramChannelImpl ...@@ -256,16 +249,8 @@ class DatagramChannelImpl
synchronized (stateLock) { synchronized (stateLock) {
ensureOpen(); ensureOpen();
if (name == StandardSocketOptions.IP_TOS) { if (name == StandardSocketOptions.IP_TOS ||
// IPv4 only; always return 0 on IPv6 name == StandardSocketOptions.IP_MULTICAST_TTL ||
if (family == StandardProtocolFamily.INET) {
return (T) Net.getSocketOption(fd, family, name);
} else {
return (T) Integer.valueOf(0);
}
}
if (name == StandardSocketOptions.IP_MULTICAST_TTL ||
name == StandardSocketOptions.IP_MULTICAST_LOOP) name == StandardSocketOptions.IP_MULTICAST_LOOP)
{ {
return (T) Net.getSocketOption(fd, family, name); return (T) Net.getSocketOption(fd, family, name);
......
...@@ -352,7 +352,8 @@ public class Net { ...@@ -352,7 +352,8 @@ public class Net {
} }
boolean mayNeedConversion = (family == UNSPEC); 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, static Object getSocketOption(FileDescriptor fd, ProtocolFamily family,
...@@ -499,7 +500,7 @@ public class Net { ...@@ -499,7 +500,7 @@ public class Net {
throws IOException; throws IOException;
private static native void setIntOption0(FileDescriptor fd, boolean mayNeedConversion, 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; throws IOException;
static native int poll(FileDescriptor fd, int events, long timeout) static native int poll(FileDescriptor fd, int events, long timeout)
......
...@@ -133,6 +133,14 @@ class ServerSocketChannelImpl ...@@ -133,6 +133,14 @@ class ServerSocketChannelImpl
synchronized (stateLock) { synchronized (stateLock) {
if (!isOpen()) if (!isOpen())
throw new ClosedChannelException(); 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 && if (name == StandardSocketOptions.SO_REUSEADDR &&
Net.useExclusiveBind()) Net.useExclusiveBind())
{ {
...@@ -177,6 +185,7 @@ class ServerSocketChannelImpl ...@@ -177,6 +185,7 @@ class ServerSocketChannelImpl
HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(2); HashSet<SocketOption<?>> set = new HashSet<SocketOption<?>>(2);
set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_RCVBUF);
set.add(StandardSocketOptions.SO_REUSEADDR); set.add(StandardSocketOptions.SO_REUSEADDR);
set.add(StandardSocketOptions.IP_TOS);
return Collections.unmodifiableSet(set); return Collections.unmodifiableSet(set);
} }
} }
......
...@@ -173,14 +173,14 @@ class SocketChannelImpl ...@@ -173,14 +173,14 @@ class SocketChannelImpl
if (!isOpen()) if (!isOpen())
throw new ClosedChannelException(); throw new ClosedChannelException();
// special handling for IP_TOS: no-op when IPv6
if (name == StandardSocketOptions.IP_TOS) { if (name == StandardSocketOptions.IP_TOS) {
if (!Net.isIPv6Available()) ProtocolFamily family = Net.isIPv6Available() ?
Net.setSocketOption(fd, StandardProtocolFamily.INET, name, value); StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
Net.setSocketOption(fd, family, name, value);
return this; return this;
} else if (name == StandardSocketOptions.SO_REUSEADDR && }
Net.useExclusiveBind())
{ if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) {
// SO_REUSEADDR emulated when using exclusive bind // SO_REUSEADDR emulated when using exclusive bind
isReuseAddress = (Boolean)value; isReuseAddress = (Boolean)value;
return this; return this;
...@@ -215,8 +215,9 @@ class SocketChannelImpl ...@@ -215,8 +215,9 @@ class SocketChannelImpl
// special handling for IP_TOS: always return 0 when IPv6 // special handling for IP_TOS: always return 0 when IPv6
if (name == StandardSocketOptions.IP_TOS) { if (name == StandardSocketOptions.IP_TOS) {
return (Net.isIPv6Available()) ? (T) Integer.valueOf(0) : ProtocolFamily family = Net.isIPv6Available() ?
(T) Net.getSocketOption(fd, StandardProtocolFamily.INET, name); StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
return (T) Net.getSocketOption(fd, family, name);
} }
// no options that require special handling // no options that require special handling
......
...@@ -110,6 +110,7 @@ int main(int argc, const char* argv[]) { ...@@ -110,6 +110,7 @@ int main(int argc, const char* argv[]) {
emit_inet("StandardSocketOptions.IP_MULTICAST_LOOP", IPPROTO_IP, IP_MULTICAST_LOOP); emit_inet("StandardSocketOptions.IP_MULTICAST_LOOP", IPPROTO_IP, IP_MULTICAST_LOOP);
#ifdef AF_INET6 #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_IF", IPPROTO_IPV6, IPV6_MULTICAST_IF);
emit_inet6("StandardSocketOptions.IP_MULTICAST_TTL", IPPROTO_IPV6, IPV6_MULTICAST_HOPS); emit_inet6("StandardSocketOptions.IP_MULTICAST_TTL", IPPROTO_IPV6, IPV6_MULTICAST_HOPS);
emit_inet6("StandardSocketOptions.IP_MULTICAST_LOOP", IPPROTO_IPV6, IPV6_MULTICAST_LOOP); emit_inet6("StandardSocketOptions.IP_MULTICAST_LOOP", IPPROTO_IPV6, IPV6_MULTICAST_LOOP);
......
...@@ -1310,7 +1310,7 @@ NET_SetSockOpt(int fd, int level, int opt, const void *arg, ...@@ -1310,7 +1310,7 @@ NET_SetSockOpt(int fd, int level, int opt, const void *arg,
* or sending UDP packet. * or sending UDP packet.
* 2. IPv6 on Linux: By default Linux ignores flowinfo * 2. IPv6 on Linux: By default Linux ignores flowinfo
* field so enable IPV6_FLOWINFO_SEND so that 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 * 3. IPv4: set socket option based on ToS and Precedence
* fields (otherwise get invalid argument) * fields (otherwise get invalid argument)
*/ */
...@@ -1326,8 +1326,10 @@ NET_SetSockOpt(int fd, int level, int opt, const void *arg, ...@@ -1326,8 +1326,10 @@ NET_SetSockOpt(int fd, int level, int opt, const void *arg,
#if defined(AF_INET6) && defined(__linux__) #if defined(AF_INET6) && defined(__linux__)
if (ipv6_available()) { if (ipv6_available()) {
int optval = 1; int optval = 1;
return setsockopt(fd, IPPROTO_IPV6, IPV6_FLOWINFO_SEND, if (setsockopt(fd, IPPROTO_IPV6, IPV6_FLOWINFO_SEND,
(void *)&optval, sizeof(optval)); (void *)&optval, sizeof(optval)) < 0) {
return -1;
}
} }
#endif #endif
......
...@@ -478,7 +478,8 @@ Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo, ...@@ -478,7 +478,8 @@ Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo, 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; int result;
struct linger linger; struct linger linger;
...@@ -521,6 +522,12 @@ Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo, ...@@ -521,6 +522,12 @@ Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
JNU_JAVANETPKG "SocketException", JNU_JAVANETPKG "SocketException",
"sun.nio.ch.Net.setIntOption"); "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 JNIEXPORT jint JNICALL
......
...@@ -319,7 +319,7 @@ Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo, ...@@ -319,7 +319,7 @@ Java_sun_nio_ch_Net_getIntOption0(JNIEnv *env, jclass clazz, jobject fdo,
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_sun_nio_ch_Net_setIntOption0(JNIEnv *env, jclass clazz, jobject fdo, 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; struct linger linger;
char *parg; char *parg;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册