8029607: Type of Service (TOS) cannot be set in IPv6 header
Reviewed-by: alanb
This commit is contained in:
parent
ea1882be4f
commit
fd148509ce
@ -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);
|
||||
|
@ -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
|
||||
|
@ -1317,7 +1317,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)
|
||||
*/
|
||||
@ -1333,8 +1333,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
|
||||
|
||||
|
@ -435,7 +435,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;
|
||||
@ -478,6 +479,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;
|
||||
|
Loading…
Reference in New Issue
Block a user