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
src/java.base/unix/native/libnio/ch
test/jdk/java/nio/channels/DatagramChannel

@ -49,11 +49,15 @@
/**
* IP_MULTICAST_ALL supported since 2.6.31 but may not be available at
* build time.
* IPV6_MULTICAST_ALL supported since 4.20
*/
#ifdef __linux__
#ifndef IP_MULTICAST_ALL
#define IP_MULTICAST_ALL 49
#endif
#ifndef IPV6_MULTICAST_ALL
#define IPV6_MULTICAST_ALL 29
#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) {
/* By default, Linux uses the route default */
int arg = 1;
if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &arg,
sizeof(arg)) < 0) {
@ -308,6 +312,17 @@ Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
close(fd);
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

@ -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.
*
* 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.net.IPSupport;
import jdk.test.lib.Platform;
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 {
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
NetworkConfiguration config = NetworkConfiguration.probe();
@ -222,8 +215,8 @@ public class Promiscuous {
InetAddress source = config.ip4Addresses(nif).iterator().next();
test(INET, nif, ip4Group1, ip4Group2);
// Solaris and Linux allow IPv6 sockets join IPv4 multicast groups
if (os.equals("Linux"))
// test IPv6 sockets joining IPv4 multicast groups
if (supportedByPlatform())
test(UNSPEC, nif, ip4Group1, ip4Group2);
}
}

@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,10 +23,10 @@
/*
* @test
* @bug 8215294
* @requires os.family == "linux"
* @bug 8215294 8241800
* @library /test/lib
* @build jdk.test.lib.NetworkConfiguration
* jdk.test.lib.Platform
* PromiscuousIPv6
* @run main PromiscuousIPv6
* @key randomness
@ -38,6 +38,7 @@ import java.net.*;
import java.util.*;
import java.io.IOException;
import jdk.test.lib.NetworkConfiguration;
import jdk.test.lib.Platform;
import jtreg.SkippedException;
import static java.net.StandardProtocolFamily.*;
import static java.nio.charset.StandardCharsets.UTF_8;
@ -145,6 +146,7 @@ public class PromiscuousIPv6 {
static void test(ProtocolFamily family,
NetworkInterface nif,
boolean bindToWildcard,
InetAddress group1,
InetAddress group2)
throws IOException
@ -154,8 +156,13 @@ public class PromiscuousIPv6 {
// Bind addresses should include the same network interface / scope, so
// as to not reply on the default route when there are multiple interfaces
InetAddress bindAddr1 = Inet6Address.getByAddress(null, group1.getAddress(), nif);
InetAddress bindAddr2 = Inet6Address.getByAddress(null, group2.getAddress(), nif);
InetAddress bindAddr1 = bindToWildcard
? 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.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 {
String os = System.getProperty("os.name");
boolean hasIPV6MulticastAll;
if (!os.equals("Linux")) {
throw new SkippedException("This test should be run only on Linux");
if (!supportedByPlatform()) {
throw new SkippedException("This test should not be run on this platform");
} else {
String osVersion = System.getProperty("os.version");
String prefix = "3.10.0";
if (osVersion.startsWith(prefix)) {
throw new SkippedException(
String.format("The behavior under test is known NOT to work on '%s' kernels", prefix));
}
int major = Platform.getOsVersionMajor();
int minor = Platform.getOsVersionMinor();
hasIPV6MulticastAll =
Platform.isOSX() ||
(Platform.isLinux() && ((major > 4) || ((major == 4 && minor >= 20))));
}
NetworkConfiguration.printSystemConfiguration(System.out);
@ -226,8 +239,12 @@ public class PromiscuousIPv6 {
InetAddress linkLocal2 = InetAddress.getByName("ff12::6.7.8.9");
for (NetworkInterface nif : nifs) {
test(INET6, nif, interfaceLocal1, interfaceLocal2);
test(INET6, nif, linkLocal1, linkLocal2);
test(INET6, nif, false, interfaceLocal1, interfaceLocal2);
test(INET6, nif, false, linkLocal1, linkLocal2);
if (hasIPV6MulticastAll) {
test(INET6, nif, true, interfaceLocal1, interfaceLocal2);
test(INET6, nif, true, linkLocal1, linkLocal2);
}
}
}
}