8290349: IP_DONTFRAGMENT doesn't set DF bit in IPv4 header

Reviewed-by: michaelm, alanb
This commit is contained in:
Daniel Jeliński 2022-08-04 10:52:15 +00:00
parent 26e5c112da
commit ce61eb6ff9
9 changed files with 74 additions and 134 deletions

View file

@ -133,11 +133,11 @@ public abstract class ExtendedSocketOptions {
} }
/** Sets the value of a socket option, for the given socket. */ /** Sets the value of a socket option, for the given socket. */
public abstract void setOption(FileDescriptor fd, SocketOption<?> option, Object value) public abstract void setOption(FileDescriptor fd, SocketOption<?> option, Object value, boolean isIPv6)
throws SocketException; throws SocketException;
/** Returns the value of a socket option, for the given socket. */ /** Returns the value of a socket option, for the given socket. */
public abstract Object getOption(FileDescriptor fd, SocketOption<?> option) public abstract Object getOption(FileDescriptor fd, SocketOption<?> option, boolean isIPv6)
throws SocketException; throws SocketException;
protected ExtendedSocketOptions(Set<SocketOption<?>> options) { protected ExtendedSocketOptions(Set<SocketOption<?>> options) {
@ -206,7 +206,7 @@ public abstract class ExtendedSocketOptions {
} }
@Override @Override
public void setOption(FileDescriptor fd, SocketOption<?> option, Object value) public void setOption(FileDescriptor fd, SocketOption<?> option, Object value, boolean isIPv6)
throws SocketException throws SocketException
{ {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
@ -214,7 +214,7 @@ public abstract class ExtendedSocketOptions {
} }
@Override @Override
public Object getOption(FileDescriptor fd, SocketOption<?> option) public Object getOption(FileDescriptor fd, SocketOption<?> option, boolean isIPv6)
throws SocketException throws SocketException
{ {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(

View file

@ -402,9 +402,10 @@ public class Net {
// only simple values supported by this method // only simple values supported by this method
Class<?> type = name.type(); Class<?> type = name.type();
boolean isIPv6 = (family == StandardProtocolFamily.INET6);
if (extendedOptions.isOptionSupported(name)) { if (extendedOptions.isOptionSupported(name)) {
extendedOptions.setOption(fd, name, value); extendedOptions.setOption(fd, name, value, isIPv6);
return; return;
} }
@ -451,7 +452,6 @@ public class Net {
} }
boolean mayNeedConversion = (family == UNSPEC); boolean mayNeedConversion = (family == UNSPEC);
boolean isIPv6 = (family == StandardProtocolFamily.INET6);
setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg, isIPv6); setIntOption0(fd, mayNeedConversion, key.level(), key.name(), arg, isIPv6);
} }
@ -467,7 +467,8 @@ public class Net {
Class<?> type = name.type(); Class<?> type = name.type();
if (extendedOptions.isOptionSupported(name)) { if (extendedOptions.isOptionSupported(name)) {
return extendedOptions.getOption(fd, name); boolean isIPv6 = (family == StandardProtocolFamily.INET6);
return extendedOptions.getOption(fd, name, isIPv6);
} }
// only simple values supported by this method // only simple values supported by this method

View file

@ -108,13 +108,13 @@ class LinuxSocketOptions extends PlatformSocketOptions {
} }
@Override @Override
void setIpDontFragment(int fd, final boolean value) throws SocketException { void setIpDontFragment(int fd, final boolean value, boolean isIPv6) throws SocketException {
setIpDontFragment0(fd, value); setIpDontFragment0(fd, value, isIPv6);
} }
@Override @Override
boolean getIpDontFragment(int fd) throws SocketException { boolean getIpDontFragment(int fd, boolean isIPv6) throws SocketException {
return getIpDontFragment0(fd); return getIpDontFragment0(fd, isIPv6);
} }
@Override @Override
@ -130,11 +130,11 @@ class LinuxSocketOptions extends PlatformSocketOptions {
private static native void setTcpkeepAliveProbes0(int fd, int value) throws SocketException; private static native void setTcpkeepAliveProbes0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveTime0(int fd, int value) throws SocketException; private static native void setTcpKeepAliveTime0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveIntvl0(int fd, int value) throws SocketException; private static native void setTcpKeepAliveIntvl0(int fd, int value) throws SocketException;
private static native void setIpDontFragment0(int fd, boolean value) throws SocketException; private static native void setIpDontFragment0(int fd, boolean value, boolean isIPv6) throws SocketException;
private static native int getTcpkeepAliveProbes0(int fd) throws SocketException; private static native int getTcpkeepAliveProbes0(int fd) throws SocketException;
private static native int getTcpKeepAliveTime0(int fd) throws SocketException; private static native int getTcpKeepAliveTime0(int fd) throws SocketException;
private static native int getTcpKeepAliveIntvl0(int fd) throws SocketException; private static native int getTcpKeepAliveIntvl0(int fd) throws SocketException;
private static native boolean getIpDontFragment0(int fd) throws SocketException; private static native boolean getIpDontFragment0(int fd, boolean isIPv6) throws SocketException;
private static native void setQuickAck0(int fd, boolean on) throws SocketException; private static native void setQuickAck0(int fd, boolean on) throws SocketException;
private static native boolean getQuickAck0(int fd) throws SocketException; private static native boolean getQuickAck0(int fd) throws SocketException;
private static native long getSoPeerCred0(int fd) throws SocketException; private static native long getSoPeerCred0(int fd) throws SocketException;

View file

@ -244,34 +244,18 @@ JNIEXPORT jint JNICALL Java_jdk_net_LinuxSocketOptions_getIncomingNapiId0
return optval; return optval;
} }
static int socketFamily(jint fd) {
struct sockaddr_storage st;
struct sockaddr *sa = (struct sockaddr *)&st;
socklen_t sa_len = sizeof(st);
if (getsockname(fd, sa, &sa_len) == 0) {
return sa->sa_family;
}
return -1;
}
/* /*
* Class: jdk_net_LinuxSocketOptions * Class: jdk_net_LinuxSocketOptions
* Method: setIpDontFragment0 * Method: setIpDontFragment0
* Signature: (IZ)V * Signature: (IZZ)V
*/ */
JNIEXPORT void JNICALL Java_jdk_net_LinuxSocketOptions_setIpDontFragment0 JNIEXPORT void JNICALL Java_jdk_net_LinuxSocketOptions_setIpDontFragment0
(JNIEnv *env, jobject unused, jint fd, jboolean optval) { (JNIEnv *env, jobject unused, jint fd, jboolean optval, jboolean isIPv6) {
jint rv, optsetting; jint rv, optsetting;
jint family = socketFamily(fd);
if (family == -1) {
handleError(env, family, "get socket family failed");
return;
}
optsetting = optval ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT; optsetting = optval ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
if (family == AF_INET) { if (!isIPv6) {
rv = setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, &optsetting, sizeof (optsetting)); rv = setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, &optsetting, sizeof (optsetting));
} else { } else {
rv = setsockopt(fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &optsetting, sizeof (optsetting)); rv = setsockopt(fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &optsetting, sizeof (optsetting));
@ -282,18 +266,13 @@ JNIEXPORT void JNICALL Java_jdk_net_LinuxSocketOptions_setIpDontFragment0
/* /*
* Class: jdk_net_LinuxSocketOptions * Class: jdk_net_LinuxSocketOptions
* Method: getIpDontFragment0 * Method: getIpDontFragment0
* Signature: (I)Z; * Signature: (IZ)Z;
*/ */
JNIEXPORT jboolean JNICALL Java_jdk_net_LinuxSocketOptions_getIpDontFragment0 JNIEXPORT jboolean JNICALL Java_jdk_net_LinuxSocketOptions_getIpDontFragment0
(JNIEnv *env, jobject unused, jint fd) { (JNIEnv *env, jobject unused, jint fd, jboolean isIPv6) {
jint optlevel, optname, optval, rv; jint optlevel, optname, optval, rv;
jint family = socketFamily(fd);
if (family == -1) {
handleError(env, family, "get socket family failed");
return JNI_FALSE;
}
if (family == AF_INET) { if (!isIPv6) {
optlevel = IPPROTO_IP; optlevel = IPPROTO_IP;
optname = IP_MTU_DISCOVER; optname = IP_MTU_DISCOVER;
} else { } else {

View file

@ -84,13 +84,13 @@ class MacOSXSocketOptions extends PlatformSocketOptions {
} }
@Override @Override
void setIpDontFragment(int fd, final boolean value) throws SocketException { void setIpDontFragment(int fd, final boolean value, boolean isIPv6) throws SocketException {
setIpDontFragment0(fd, value); setIpDontFragment0(fd, value, isIPv6);
} }
@Override @Override
boolean getIpDontFragment(int fd) throws SocketException { boolean getIpDontFragment(int fd, boolean isIPv6) throws SocketException {
return getIpDontFragment0(fd); return getIpDontFragment0(fd, isIPv6);
} }
@Override @Override
@ -106,11 +106,11 @@ class MacOSXSocketOptions extends PlatformSocketOptions {
private static native void setTcpkeepAliveProbes0(int fd, int value) throws SocketException; private static native void setTcpkeepAliveProbes0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveTime0(int fd, int value) throws SocketException; private static native void setTcpKeepAliveTime0(int fd, int value) throws SocketException;
private static native void setTcpKeepAliveIntvl0(int fd, int value) throws SocketException; private static native void setTcpKeepAliveIntvl0(int fd, int value) throws SocketException;
private static native void setIpDontFragment0(int fd, boolean value) throws SocketException; private static native void setIpDontFragment0(int fd, boolean value, boolean isIPv6) throws SocketException;
private static native int getTcpkeepAliveProbes0(int fd) throws SocketException; private static native int getTcpkeepAliveProbes0(int fd) throws SocketException;
private static native int getTcpKeepAliveTime0(int fd) throws SocketException; private static native int getTcpKeepAliveTime0(int fd) throws SocketException;
private static native int getTcpKeepAliveIntvl0(int fd) throws SocketException; private static native int getTcpKeepAliveIntvl0(int fd) throws SocketException;
private static native boolean getIpDontFragment0(int fd) throws SocketException; private static native boolean getIpDontFragment0(int fd, boolean isIPv6) throws SocketException;
private static native long getSoPeerCred0(int fd) throws SocketException; private static native long getSoPeerCred0(int fd) throws SocketException;
private static native boolean keepAliveOptionsSupported0(); private static native boolean keepAliveOptionsSupported0();
private static native boolean ipDontFragmentSupported0(); private static native boolean ipDontFragmentSupported0();

View file

@ -178,17 +178,6 @@ JNIEXPORT jint JNICALL Java_jdk_net_MacOSXSocketOptions_getTcpKeepAliveIntvl0
return optval; return optval;
} }
static int socketFamily(jint fd) {
struct sockaddr_storage st;
struct sockaddr* sa = (struct sockaddr *)&st;
socklen_t sa_len = sizeof(st);
if (getsockname(fd, sa, &sa_len) == 0) {
return sa->sa_family;
}
return -1;
}
/* /*
* Class: jdk_net_MacOSXSocketOptions * Class: jdk_net_MacOSXSocketOptions
* Method: ipDontFragmentSupported0 * Method: ipDontFragmentSupported0
@ -198,42 +187,37 @@ JNIEXPORT jboolean JNICALL Java_jdk_net_MacOSXSocketOptions_ipDontFragmentSuppor
(JNIEnv *env, jobject unused) { (JNIEnv *env, jobject unused) {
jint rv, fd, value; jint rv, fd, value;
fd = socket(AF_INET, SOCK_DGRAM, 0); fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1) if (fd != -1) {
return JNI_FALSE;
value = 1; value = 1;
rv = setsockopt(fd, IPPROTO_IP, IP_DONTFRAG, &value, sizeof(value)); rv = setsockopt(fd, IPPROTO_IP, IP_DONTFRAG, &value, sizeof(value));
close(fd); close(fd);
if (rv == -1) { if (rv == -1) {
return JNI_FALSE; return JNI_FALSE;
} }
}
fd = socket(AF_INET6, SOCK_DGRAM, 0); fd = socket(AF_INET6, SOCK_DGRAM, 0);
if (fd == -1) if (fd != -1) {
return JNI_FALSE;
value = 1; value = 1;
rv = setsockopt(fd, IPPROTO_IPV6, IPV6_DONTFRAG, &value, sizeof(value)); rv = setsockopt(fd, IPPROTO_IPV6, IPV6_DONTFRAG, &value, sizeof(value));
close(fd); close(fd);
if (rv == -1) { if (rv == -1) {
return JNI_FALSE; return JNI_FALSE;
} }
}
return JNI_TRUE; return JNI_TRUE;
} }
/* /*
* Class: jdk_net_MacOSXSocketOptions * Class: jdk_net_MacOSXSocketOptions
* Method: setIpDontFragment0 * Method: setIpDontFragment0
* Signature: (IZ)V * Signature: (IZZ)V
*/ */
JNIEXPORT void JNICALL Java_jdk_net_MacOSXSocketOptions_setIpDontFragment0 JNIEXPORT void JNICALL Java_jdk_net_MacOSXSocketOptions_setIpDontFragment0
(JNIEnv *env, jobject unused, jint fd, jboolean optval) { (JNIEnv *env, jobject unused, jint fd, jboolean optval, jboolean isIPv6) {
jint rv; jint rv;
jint family = socketFamily(fd);
jint value = optval ? 1 : 0; jint value = optval ? 1 : 0;
if (family == -1) { if (!isIPv6) {
handleError(env, family, "get socket family failed");
return;
}
if (family == AF_INET) {
rv = setsockopt(fd, IPPROTO_IP, IP_DONTFRAG, &value, sizeof(value)); rv = setsockopt(fd, IPPROTO_IP, IP_DONTFRAG, &value, sizeof(value));
} else { } else {
rv = setsockopt(fd, IPPROTO_IPV6, IPV6_DONTFRAG, &value, sizeof(value)); rv = setsockopt(fd, IPPROTO_IPV6, IPV6_DONTFRAG, &value, sizeof(value));
@ -244,18 +228,13 @@ JNIEXPORT void JNICALL Java_jdk_net_MacOSXSocketOptions_setIpDontFragment0
/* /*
* Class: jdk_net_MacOSXSocketOptions * Class: jdk_net_MacOSXSocketOptions
* Method: getIpDontFragment0 * Method: getIpDontFragment0
* Signature: (I)Z; * Signature: (IZ)Z;
*/ */
JNIEXPORT jboolean JNICALL Java_jdk_net_MacOSXSocketOptions_getIpDontFragment0 JNIEXPORT jboolean JNICALL Java_jdk_net_MacOSXSocketOptions_getIpDontFragment0
(JNIEnv *env, jobject unused, jint fd) { (JNIEnv *env, jobject unused, jint fd, jboolean isIPv6) {
jint optval, rv; jint optval, rv;
socklen_t sz = sizeof (optval); socklen_t sz = sizeof (optval);
jint family = socketFamily(fd); if (!isIPv6) {
if (family == -1) {
handleError(env, family, "get socket family failed");
return 0;
}
if (family == AF_INET) {
rv = getsockopt(fd, IPPROTO_IP, IP_DONTFRAG, &optval, &sz); rv = getsockopt(fd, IPPROTO_IP, IP_DONTFRAG, &optval, &sz);
} else { } else {
rv = getsockopt(fd, IPPROTO_IPV6, IPV6_DONTFRAG, &optval, &sz); rv = getsockopt(fd, IPPROTO_IPV6, IPV6_DONTFRAG, &optval, &sz);

View file

@ -28,6 +28,7 @@ package jdk.net;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.net.SocketException; import java.net.SocketException;
import java.net.SocketOption; import java.net.SocketOption;
import java.net.StandardProtocolFamily;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedAction; import java.security.PrivilegedAction;
import java.util.Collections; import java.util.Collections;
@ -209,6 +210,9 @@ public final class ExtendedSocketOptions {
* sizes to the {@link java.net.NetworkInterface#getMTU() local MTU}. Depending * sizes to the {@link java.net.NetworkInterface#getMTU() local MTU}. Depending
* on the implementation and the network interface, packets larger than the MTU * on the implementation and the network interface, packets larger than the MTU
* may be sent or dropped silently or dropped with an exception thrown. * may be sent or dropped silently or dropped with an exception thrown.
* For {@link StandardProtocolFamily#INET6 IPv6} sockets it is
* system dependent whether the option also applies to datagrams
* sent to IPv4 addresses.
* *
* @apiNote * @apiNote
* For IPv4 this option sets the DF (Do not Fragment) flag in the IP packet * For IPv4 this option sets the DF (Do not Fragment) flag in the IP packet
@ -263,10 +267,9 @@ public final class ExtendedSocketOptions {
new sun.net.ext.ExtendedSocketOptions(extendedOptions) { new sun.net.ext.ExtendedSocketOptions(extendedOptions) {
@Override @Override
@SuppressWarnings("removal")
public void setOption(FileDescriptor fd, public void setOption(FileDescriptor fd,
SocketOption<?> option, SocketOption<?> option,
Object value) Object value, boolean isIPv6)
throws SocketException throws SocketException
{ {
if (fd == null || !fd.valid()) if (fd == null || !fd.valid())
@ -277,7 +280,7 @@ public final class ExtendedSocketOptions {
} else if (option == TCP_KEEPCOUNT) { } else if (option == TCP_KEEPCOUNT) {
setTcpkeepAliveProbes(fd, (Integer) value); setTcpkeepAliveProbes(fd, (Integer) value);
} else if (option == IP_DONTFRAGMENT) { } else if (option == IP_DONTFRAGMENT) {
setIpDontFragment(fd, (Boolean) value); setIpDontFragment(fd, (Boolean) value, isIPv6);
} else if (option == TCP_KEEPIDLE) { } else if (option == TCP_KEEPIDLE) {
setTcpKeepAliveTime(fd, (Integer) value); setTcpKeepAliveTime(fd, (Integer) value);
} else if (option == TCP_KEEPINTERVAL) { } else if (option == TCP_KEEPINTERVAL) {
@ -295,9 +298,8 @@ public final class ExtendedSocketOptions {
} }
@Override @Override
@SuppressWarnings("removal")
public Object getOption(FileDescriptor fd, public Object getOption(FileDescriptor fd,
SocketOption<?> option) SocketOption<?> option, boolean isIPv6)
throws SocketException throws SocketException
{ {
if (fd == null || !fd.valid()) if (fd == null || !fd.valid())
@ -308,7 +310,7 @@ public final class ExtendedSocketOptions {
} else if (option == TCP_KEEPCOUNT) { } else if (option == TCP_KEEPCOUNT) {
return getTcpkeepAliveProbes(fd); return getTcpkeepAliveProbes(fd);
} else if (option == IP_DONTFRAGMENT) { } else if (option == IP_DONTFRAGMENT) {
return getIpDontFragment(fd); return getIpDontFragment(fd, isIPv6);
} else if (option == TCP_KEEPIDLE) { } else if (option == TCP_KEEPIDLE) {
return getTcpKeepAliveTime(fd); return getTcpKeepAliveTime(fd);
} else if (option == TCP_KEEPINTERVAL) { } else if (option == TCP_KEEPINTERVAL) {
@ -352,9 +354,9 @@ public final class ExtendedSocketOptions {
platformSocketOptions.setTcpKeepAliveTime(fdAccess.get(fd), value); platformSocketOptions.setTcpKeepAliveTime(fdAccess.get(fd), value);
} }
private static void setIpDontFragment(FileDescriptor fd, boolean value) private static void setIpDontFragment(FileDescriptor fd, boolean value, boolean isIPv6)
throws SocketException { throws SocketException {
platformSocketOptions.setIpDontFragment(fdAccess.get(fd), value); platformSocketOptions.setIpDontFragment(fdAccess.get(fd), value, isIPv6);
} }
private static void setTcpKeepAliveIntvl(FileDescriptor fd, int value) private static void setTcpKeepAliveIntvl(FileDescriptor fd, int value)
@ -366,8 +368,8 @@ public final class ExtendedSocketOptions {
return platformSocketOptions.getTcpkeepAliveProbes(fdAccess.get(fd)); return platformSocketOptions.getTcpkeepAliveProbes(fdAccess.get(fd));
} }
private static boolean getIpDontFragment(FileDescriptor fd) throws SocketException { private static boolean getIpDontFragment(FileDescriptor fd, boolean isIPv6) throws SocketException {
return platformSocketOptions.getIpDontFragment(fdAccess.get(fd)); return platformSocketOptions.getIpDontFragment(fdAccess.get(fd), isIPv6);
} }
private static int getTcpKeepAliveTime(FileDescriptor fd) throws SocketException { private static int getTcpKeepAliveTime(FileDescriptor fd) throws SocketException {
@ -462,11 +464,11 @@ public final class ExtendedSocketOptions {
throw new UnsupportedOperationException("unsupported TCP_KEEPINTVL option"); throw new UnsupportedOperationException("unsupported TCP_KEEPINTVL option");
} }
void setIpDontFragment(int fd, final boolean value) throws SocketException { void setIpDontFragment(int fd, final boolean value, boolean isIPv6) throws SocketException {
throw new UnsupportedOperationException("unsupported IP_DONTFRAGMENT option"); throw new UnsupportedOperationException("unsupported IP_DONTFRAGMENT option");
} }
boolean getIpDontFragment(int fd) throws SocketException { boolean getIpDontFragment(int fd, boolean isIPv6) throws SocketException {
throw new UnsupportedOperationException("unsupported IP_DONTFRAGMENT option"); throw new UnsupportedOperationException("unsupported IP_DONTFRAGMENT option");
} }

View file

@ -42,17 +42,17 @@ class WindowsSocketOptions extends PlatformSocketOptions {
} }
@Override @Override
void setIpDontFragment(int fd, final boolean value) throws SocketException { void setIpDontFragment(int fd, final boolean value, boolean isIPv6) throws SocketException {
setIpDontFragment0(fd, value); setIpDontFragment0(fd, value, isIPv6);
} }
@Override @Override
boolean getIpDontFragment(int fd) throws SocketException { boolean getIpDontFragment(int fd, boolean isIPv6) throws SocketException {
return getIpDontFragment0(fd); return getIpDontFragment0(fd, isIPv6);
} }
private static native void setIpDontFragment0(int fd, boolean value) throws SocketException; private static native void setIpDontFragment0(int fd, boolean value, boolean isIPv6) throws SocketException;
private static native boolean getIpDontFragment0(int fd) throws SocketException; private static native boolean getIpDontFragment0(int fd, boolean isIPv6) throws SocketException;
static { static {
if (System.getSecurityManager() == null) { if (System.getSecurityManager() == null) {

View file

@ -43,32 +43,16 @@ static void handleError(JNIEnv *env, jint rv, const char *errmsg) {
} }
} }
static int socketFamily(jint fd) {
WSAPROTOCOL_INFO info;
socklen_t sa_len = sizeof(info);
if (getsockopt(fd, SOL_SOCKET, SO_PROTOCOL_INFO, (char *)&info, &sa_len) == 0) {
return info.iAddressFamily;
}
return -1;
}
/* /*
* Class: jdk_net_WindowsSocketOptions * Class: jdk_net_WindowsSocketOptions
* Method: setIpDontFragment0 * Method: setIpDontFragment0
* Signature: (IZ)V * Signature: (IZZ)V
*/ */
JNIEXPORT void JNICALL Java_jdk_net_WindowsSocketOptions_setIpDontFragment0 JNIEXPORT void JNICALL Java_jdk_net_WindowsSocketOptions_setIpDontFragment0
(JNIEnv *env, jobject unused, jint fd, jboolean optval) { (JNIEnv *env, jobject unused, jint fd, jboolean optval, jboolean isIPv6) {
int rv, opt; int rv, opt;
jint family = socketFamily(fd);
if (family == -1) {
handleError(env, family, "get socket family failed");
return;
}
if (!isIPv6) {
if (family == AF_INET) {
opt = optval ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT; opt = optval ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT;
rv = setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, (char *)&opt, sizeof(int)); rv = setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, (char *)&opt, sizeof(int));
if (rv == SOCKET_ERROR && WSAGetLastError() == WSAENOPROTOOPT) { if (rv == SOCKET_ERROR && WSAGetLastError() == WSAENOPROTOOPT) {
@ -81,7 +65,7 @@ JNIEXPORT void JNICALL Java_jdk_net_WindowsSocketOptions_setIpDontFragment0
if (rv == SOCKET_ERROR && WSAGetLastError() == WSAENOPROTOOPT) { if (rv == SOCKET_ERROR && WSAGetLastError() == WSAENOPROTOOPT) {
/* IPV6_MTU_DISCOVER not supported on W 2016 and older, can use old option */ /* IPV6_MTU_DISCOVER not supported on W 2016 and older, can use old option */
opt = optval; opt = optval;
rv = setsockopt(fd, IPPROTO_IP, IP_DONTFRAGMENT, (char *)&opt, sizeof(int)); rv = setsockopt(fd, IPPROTO_IPV6, IPV6_DONTFRAG, (char *)&opt, sizeof(int));
} }
} }
handleError(env, rv, "set option IP_DONTFRAGMENT failed"); handleError(env, rv, "set option IP_DONTFRAGMENT failed");
@ -90,18 +74,13 @@ JNIEXPORT void JNICALL Java_jdk_net_WindowsSocketOptions_setIpDontFragment0
/* /*
* Class: jdk_net_WindowsSocketOptions * Class: jdk_net_WindowsSocketOptions
* Method: getIpDontFragment0 * Method: getIpDontFragment0
* Signature: (I)Z; * Signature: (IZ)Z;
*/ */
JNIEXPORT jboolean JNICALL Java_jdk_net_WindowsSocketOptions_getIpDontFragment0 JNIEXPORT jboolean JNICALL Java_jdk_net_WindowsSocketOptions_getIpDontFragment0
(JNIEnv *env, jobject unused, jint fd) { (JNIEnv *env, jobject unused, jint fd, jboolean isIPv6) {
int optval, rv, sz = sizeof(optval); int optval, rv, sz = sizeof(optval);
jint family = socketFamily(fd);
if (family == -1) {
handleError(env, family, "get socket family failed");
return JNI_FALSE;
}
if (family == AF_INET) { if (!isIPv6) {
rv = getsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, (char *)&optval, &sz); rv = getsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, (char *)&optval, &sz);
if (rv == SOCKET_ERROR && WSAGetLastError() == WSAENOPROTOOPT) { if (rv == SOCKET_ERROR && WSAGetLastError() == WSAENOPROTOOPT) {
sz = sizeof(optval); sz = sizeof(optval);
@ -115,7 +94,7 @@ JNIEXPORT jboolean JNICALL Java_jdk_net_WindowsSocketOptions_getIpDontFragment0
rv = getsockopt(fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, (char *)&optval, &sz); rv = getsockopt(fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER, (char *)&optval, &sz);
if (rv == SOCKET_ERROR && WSAGetLastError() == WSAENOPROTOOPT) { if (rv == SOCKET_ERROR && WSAGetLastError() == WSAENOPROTOOPT) {
sz = sizeof(optval); sz = sizeof(optval);
rv = getsockopt(fd, IPPROTO_IP, IP_DONTFRAGMENT, (char *)&optval, &sz); rv = getsockopt(fd, IPPROTO_IPV6, IPV6_DONTFRAG, (char *)&optval, &sz);
handleError(env, rv, "get option IP_DONTFRAGMENT failed"); handleError(env, rv, "get option IP_DONTFRAGMENT failed");
return optval; return optval;
} }