8303509: Socket setTrafficClass does not work for IPv4 connections when IPv6 enabled

Reviewed-by: djelinski, michaelm
This commit is contained in:
Alan Bateman 2023-03-09 08:13:57 +00:00
parent dc523a58a6
commit dd79410824
5 changed files with 31 additions and 15 deletions

View file

@ -55,7 +55,6 @@ import sun.net.util.IPAddressUtil;
import sun.security.action.GetPropertyAction; import sun.security.action.GetPropertyAction;
public class Net { public class Net {
private Net() { } private Net() { }
// unspecified protocol family // unspecified protocol family
@ -100,8 +99,8 @@ public class Net {
/** /**
* Tells whether both IPV6_XXX and IP_XXX socket options should be set on * Tells whether both IPV6_XXX and IP_XXX socket options should be set on
* IPv6 sockets. On some kernels, both IPV6_XXX and IP_XXX socket options * IPv6 sockets. On some kernels, both IPV6_XXX and IP_XXX socket options
* need to be set so that the settings are effective for IPv4 multicast * need to be set so that the settings are effective for IPv4 connections
* datagrams sent using the socket. * and datagrams.
*/ */
static boolean shouldSetBothIPv4AndIPv6Options() { static boolean shouldSetBothIPv4AndIPv6Options() {
return shouldSetBothIPv4AndIPv6Options0(); return shouldSetBothIPv4AndIPv6Options0();
@ -448,6 +447,23 @@ public class Net {
setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg, isIPv6); setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg, isIPv6);
} }
/**
* Sets a IPPROTO_IPV6/IPPROTO level socket. Some platforms require both
* IPPROTO_IPV6 and IPPROTO socket options to be set when the socket is IPv6.
* In that case, the IPPROTO socket option is set on a best effort basis.
*/
static <T> void setIpSocketOption(FileDescriptor fd, ProtocolFamily family,
SocketOption<T> opt, T value)
throws IOException
{
setSocketOption(fd, family, opt, value);
if (family == StandardProtocolFamily.INET6 && shouldSetBothIPv4AndIPv6Options()) {
try {
setSocketOption(fd, StandardProtocolFamily.INET, opt, value);
} catch (IOException ignore) { }
}
}
static Object getSocketOption(FileDescriptor fd, SocketOption<?> name) static Object getSocketOption(FileDescriptor fd, SocketOption<?> name)
throws IOException throws IOException
{ {
@ -483,7 +499,7 @@ public class Net {
} }
} }
public static boolean isFastTcpLoopbackRequested() { private static boolean isFastTcpLoopbackRequested() {
String loopbackProp = GetPropertyAction String loopbackProp = GetPropertyAction
.privilegedGetProperty("jdk.net.useFastTcpLoopback", "false"); .privilegedGetProperty("jdk.net.useFastTcpLoopback", "false");
return loopbackProp.isEmpty() || Boolean.parseBoolean(loopbackProp); return loopbackProp.isEmpty() || Boolean.parseBoolean(loopbackProp);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -957,8 +957,8 @@ public final class NioSocketImpl extends SocketImpl implements PlatformSocketImp
synchronized (stateLock) { synchronized (stateLock) {
ensureOpen(); ensureOpen();
if (opt == StandardSocketOptions.IP_TOS) { if (opt == StandardSocketOptions.IP_TOS) {
// maps to IP_TOS or IPV6_TCLASS // maps to IPV6_TCLASS and/or IP_TOS
Net.setSocketOption(fd, family(), opt, value); Net.setIpSocketOption(fd, family(), opt, value);
} else if (opt == StandardSocketOptions.SO_REUSEADDR) { } else if (opt == StandardSocketOptions.SO_REUSEADDR) {
boolean b = (boolean) value; boolean b = (boolean) value;
if (Net.useExclusiveBind()) { if (Net.useExclusiveBind()) {
@ -1032,7 +1032,7 @@ public final class NioSocketImpl extends SocketImpl implements PlatformSocketImp
} }
case IP_TOS: { case IP_TOS: {
int i = intValue(value, "IP_TOS"); int i = intValue(value, "IP_TOS");
Net.setSocketOption(fd, family(), StandardSocketOptions.IP_TOS, i); Net.setIpSocketOption(fd, family(), StandardSocketOptions.IP_TOS, i);
break; break;
} }
case TCP_NODELAY: { case TCP_NODELAY: {

View file

@ -272,8 +272,8 @@ class SocketChannelImpl
if (isNetSocket()) { if (isNetSocket()) {
if (name == StandardSocketOptions.IP_TOS) { if (name == StandardSocketOptions.IP_TOS) {
// special handling for IP_TOS // maps to IPV6_TCLASS and/or IP_TOS
Net.setSocketOption(fd, family, name, value); Net.setIpSocketOption(fd, family, name, value);
return this; return this;
} }
if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) { if (name == StandardSocketOptions.SO_REUSEADDR && Net.useExclusiveBind()) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -159,10 +159,10 @@ JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_Net_shouldSetBothIPv4AndIPv6Options0(JNIEnv* env, jclass cl) Java_sun_nio_ch_Net_shouldSetBothIPv4AndIPv6Options0(JNIEnv* env, jclass cl)
{ {
#if defined(__linux__) #if defined(__linux__)
/* Set both IPv4 and IPv6 socket options when setting multicast options */ /* Set both IPv4 and IPv6 socket options when setting IPPROTO_IPV6 options */
return JNI_TRUE; return JNI_TRUE;
#else #else
/* Do not set both IPv4 and IPv6 socket options when setting multicast options */ /* Do not set both IPv4 and IPv6 socket options when setting IPPROTO_IPV6 options */
return JNI_FALSE; return JNI_FALSE;
#endif #endif
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -126,7 +126,7 @@ Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) {
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_sun_nio_ch_Net_shouldSetBothIPv4AndIPv6Options0(JNIEnv* env, jclass cl) Java_sun_nio_ch_Net_shouldSetBothIPv4AndIPv6Options0(JNIEnv* env, jclass cl)
{ {
/* Set both IPv4 and IPv6 socket options when setting multicast options */ /* Set both IPv4 and IPv6 socket options when setting IPPROTO_IPV6 options */
return JNI_TRUE; return JNI_TRUE;
} }