diff --git a/src/java.base/unix/native/libnio/ch/Net.c b/src/java.base/unix/native/libnio/ch/Net.c index 5af38db378b..a91e77702ca 100644 --- a/src/java.base/unix/native/libnio/ch/Net.c +++ b/src/java.base/unix/native/libnio/ch/Net.c @@ -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 diff --git a/test/jdk/java/nio/channels/DatagramChannel/Promiscuous.java b/test/jdk/java/nio/channels/DatagramChannel/Promiscuous.java index f421bf19e48..8db9c60c0b5 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/Promiscuous.java +++ b/test/jdk/java/nio/channels/DatagramChannel/Promiscuous.java @@ -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); } } diff --git a/test/jdk/java/nio/channels/DatagramChannel/PromiscuousIPv6.java b/test/jdk/java/nio/channels/DatagramChannel/PromiscuousIPv6.java index de29b4da026..b7bbba8e16b 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/PromiscuousIPv6.java +++ b/test/jdk/java/nio/channels/DatagramChannel/PromiscuousIPv6.java @@ -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); + } } } }