Skip to content

Commit

Permalink
8241800: Disable IPV6_MULTICAST_ALL to prevent interference from all …
Browse files Browse the repository at this point in the history
…multicast groups

Reviewed-by: alanb
  • Loading branch information
Michael-Mc-Mahon committed Jun 19, 2023
1 parent 137a5f7 commit 7b45c8f
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 35 deletions.
17 changes: 16 additions & 1 deletion src/java.base/unix/native/libnio/ch/Net.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

/**
Expand Down Expand Up @@ -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) {
Expand All @@ -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

Expand Down
29 changes: 11 additions & 18 deletions test/jdk/java/nio/channels/DatagramChannel/Promiscuous.java
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -44,6 +44,7 @@

import jdk.test.lib.NetworkConfiguration;
import jdk.test.lib.net.IPSupport;
import jdk.test.lib.Platform;

public class Promiscuous {

Expand Down Expand Up @@ -192,24 +193,16 @@ static void test(ProtocolFamily family,
}
}

/*
* 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();

Expand All @@ -222,8 +215,8 @@ public static void main(String[] args) throws IOException {
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);
}
}
Expand Down
49 changes: 33 additions & 16 deletions test/jdk/java/nio/channels/DatagramChannel/PromiscuousIPv6.java
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -38,6 +38,7 @@
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;
Expand Down Expand Up @@ -145,6 +146,7 @@ static void receiveDatagram(DatagramChannel dc,

static void test(ProtocolFamily family,
NetworkInterface nif,
boolean bindToWildcard,
InetAddress group1,
InetAddress group2)
throws IOException
Expand All @@ -154,8 +156,13 @@ static void test(ProtocolFamily family,

// 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);
Expand Down Expand Up @@ -194,19 +201,25 @@ static void test(ProtocolFamily family,
}
}

/*
* 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);
Expand All @@ -226,8 +239,12 @@ public static void main(String[] args) throws IOException {
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);
}
}
}
}

1 comment on commit 7b45c8f

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.