提交 e80a5178 编写于 作者: M michaelm

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

Reviewed-by: alanb
上级 0faa50b0
......@@ -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);
......
......@@ -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)
......
......@@ -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<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);
}
}
......
......@@ -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
......
......@@ -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);
......
......@@ -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
......
......@@ -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
......
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册