8241800: Disable IPV6_MULTICAST_ALL to prevent interference from all multicast groups

Reviewed-by: alanb
This commit is contained in:
Michael McMahon 2023-06-19 21:35:58 +00:00
parent 137a5f7c2c
commit 7b45c8fc3a
3 changed files with 60 additions and 35 deletions

View file

@ -49,11 +49,15 @@
/** /**
* IP_MULTICAST_ALL supported since 2.6.31 but may not be available at * IP_MULTICAST_ALL supported since 2.6.31 but may not be available at
* build time. * build time.
* IPV6_MULTICAST_ALL supported since 4.20
*/ */
#ifdef __linux__ #ifdef __linux__
#ifndef IP_MULTICAST_ALL #ifndef IP_MULTICAST_ALL
#define IP_MULTICAST_ALL 49 #define IP_MULTICAST_ALL 49
#endif #endif
#ifndef IPV6_MULTICAST_ALL
#define IPV6_MULTICAST_ALL 29
#endif
#endif #endif
/** /**
@ -297,8 +301,8 @@ Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
} }
} }
/* By default, Linux uses the route default */
if (domain == AF_INET6 && type == SOCK_DGRAM) { if (domain == AF_INET6 && type == SOCK_DGRAM) {
/* By default, Linux uses the route default */
int arg = 1; int arg = 1;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &arg, if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &arg,
sizeof(arg)) < 0) { sizeof(arg)) < 0) {
@ -308,6 +312,17 @@ Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
close(fd); close(fd);
return -1; return -1;
} }
/* Disable IPV6_MULTICAST_ALL if option supported */
arg = 0;
if ((setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_ALL, (char*)&arg, sizeof(arg)) < 0) &&
(errno != ENOPROTOOPT)) {
JNU_ThrowByNameWithLastError(env,
JNU_JAVANETPKG "SocketException",
"Unable to set IPV6_MULTICAST_ALL");
close(fd);
return -1;
}
} }
#endif #endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013, 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
@ -44,6 +44,7 @@ import java.util.stream.Collectors;
import jdk.test.lib.NetworkConfiguration; import jdk.test.lib.NetworkConfiguration;
import jdk.test.lib.net.IPSupport; import jdk.test.lib.net.IPSupport;
import jdk.test.lib.Platform;
public class Promiscuous { public class Promiscuous {
@ -192,24 +193,16 @@ public class Promiscuous {
} }
} }
/*
* returns true if platform allows an IPv6 socket join an IPv4 multicast group
*/
private static boolean supportedByPlatform() {
return Platform.isOSX() || Platform.isWindows() || Platform.isLinux();
}
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
IPSupport.throwSkippedExceptionIfNonOperational(); IPSupport.throwSkippedExceptionIfNonOperational();
String os = System.getProperty("os.name");
// Requires IP_MULTICAST_ALL on Linux (new since 2.6.31) so skip
// on older kernels. Note that we skip on <= version 3 to keep the
// parsing simple
if (os.equals("Linux")) {
String osversion = System.getProperty("os.version");
String[] vers = osversion.split("\\.", 0);
int major = Integer.parseInt(vers[0]);
if (major < 3) {
System.out.format("Kernel version is %s, test skipped%n", osversion);
return;
}
}
// get local network configuration to use // get local network configuration to use
NetworkConfiguration config = NetworkConfiguration.probe(); NetworkConfiguration config = NetworkConfiguration.probe();
@ -222,8 +215,8 @@ public class Promiscuous {
InetAddress source = config.ip4Addresses(nif).iterator().next(); InetAddress source = config.ip4Addresses(nif).iterator().next();
test(INET, nif, ip4Group1, ip4Group2); test(INET, nif, ip4Group1, ip4Group2);
// Solaris and Linux allow IPv6 sockets join IPv4 multicast groups // test IPv6 sockets joining IPv4 multicast groups
if (os.equals("Linux")) if (supportedByPlatform())
test(UNSPEC, nif, ip4Group1, ip4Group2); test(UNSPEC, nif, ip4Group1, ip4Group2);
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 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
@ -23,10 +23,10 @@
/* /*
* @test * @test
* @bug 8215294 * @bug 8215294 8241800
* @requires os.family == "linux"
* @library /test/lib * @library /test/lib
* @build jdk.test.lib.NetworkConfiguration * @build jdk.test.lib.NetworkConfiguration
* jdk.test.lib.Platform
* PromiscuousIPv6 * PromiscuousIPv6
* @run main PromiscuousIPv6 * @run main PromiscuousIPv6
* @key randomness * @key randomness
@ -38,6 +38,7 @@ import java.net.*;
import java.util.*; import java.util.*;
import java.io.IOException; import java.io.IOException;
import jdk.test.lib.NetworkConfiguration; import jdk.test.lib.NetworkConfiguration;
import jdk.test.lib.Platform;
import jtreg.SkippedException; import jtreg.SkippedException;
import static java.net.StandardProtocolFamily.*; import static java.net.StandardProtocolFamily.*;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
@ -145,6 +146,7 @@ public class PromiscuousIPv6 {
static void test(ProtocolFamily family, static void test(ProtocolFamily family,
NetworkInterface nif, NetworkInterface nif,
boolean bindToWildcard,
InetAddress group1, InetAddress group1,
InetAddress group2) InetAddress group2)
throws IOException throws IOException
@ -154,8 +156,13 @@ public class PromiscuousIPv6 {
// Bind addresses should include the same network interface / scope, so // Bind addresses should include the same network interface / scope, so
// as to not reply on the default route when there are multiple interfaces // as to not reply on the default route when there are multiple interfaces
InetAddress bindAddr1 = Inet6Address.getByAddress(null, group1.getAddress(), nif); InetAddress bindAddr1 = bindToWildcard
InetAddress bindAddr2 = Inet6Address.getByAddress(null, group2.getAddress(), nif); ? InetAddress.getByName("::0")
: Inet6Address.getByAddress(null, group1.getAddress(), nif);
InetAddress bindAddr2 = bindToWildcard
? InetAddress.getByName("::0")
: Inet6Address.getByAddress(null, group2.getAddress(), nif);
DatagramChannel dc1 = (family == UNSPEC) ? DatagramChannel dc1 = (family == UNSPEC) ?
DatagramChannel.open() : DatagramChannel.open(family); DatagramChannel.open() : DatagramChannel.open(family);
@ -194,19 +201,25 @@ public class PromiscuousIPv6 {
} }
} }
/*
* returns true if platform allows an IPv6 socket join an IPv4 multicast group
*/
private static boolean supportedByPlatform() {
return Platform.isOSX() || Platform.isLinux();
}
public static void main(String[] args) throws IOException { public static void main(String[] args) throws IOException {
String os = System.getProperty("os.name"); boolean hasIPV6MulticastAll;
if (!os.equals("Linux")) { if (!supportedByPlatform()) {
throw new SkippedException("This test should be run only on Linux"); throw new SkippedException("This test should not be run on this platform");
} else { } else {
String osVersion = System.getProperty("os.version"); int major = Platform.getOsVersionMajor();
String prefix = "3.10.0"; int minor = Platform.getOsVersionMinor();
if (osVersion.startsWith(prefix)) { hasIPV6MulticastAll =
throw new SkippedException( Platform.isOSX() ||
String.format("The behavior under test is known NOT to work on '%s' kernels", prefix)); (Platform.isLinux() && ((major > 4) || ((major == 4 && minor >= 20))));
}
} }
NetworkConfiguration.printSystemConfiguration(System.out); NetworkConfiguration.printSystemConfiguration(System.out);
@ -226,8 +239,12 @@ public class PromiscuousIPv6 {
InetAddress linkLocal2 = InetAddress.getByName("ff12::6.7.8.9"); InetAddress linkLocal2 = InetAddress.getByName("ff12::6.7.8.9");
for (NetworkInterface nif : nifs) { for (NetworkInterface nif : nifs) {
test(INET6, nif, interfaceLocal1, interfaceLocal2); test(INET6, nif, false, interfaceLocal1, interfaceLocal2);
test(INET6, nif, linkLocal1, linkLocal2); test(INET6, nif, false, linkLocal1, linkLocal2);
if (hasIPV6MulticastAll) {
test(INET6, nif, true, interfaceLocal1, interfaceLocal2);
test(INET6, nif, true, linkLocal1, linkLocal2);
}
} }
} }
} }