From efcd30d780a9b9779c7768df4416310d828f04fe Mon Sep 17 00:00:00 2001 From: alanb Date: Tue, 15 Mar 2011 13:15:31 +0000 Subject: [PATCH] 7026376: (dc) DatagramChannel created without specifying protocol family fails to join IPv4 group Reviewed-by: chegar --- make/java/nio/mapfile-linux | 2 + make/java/nio/mapfile-solaris | 2 + .../sun/nio/ch/DatagramChannelImpl.java | 23 +-- src/share/classes/sun/nio/ch/Net.java | 21 ++- src/solaris/native/sun/nio/ch/Net.c | 16 ++ src/windows/native/sun/nio/ch/Net.c | 12 ++ .../MulticastSendReceiveTests.java | 138 ++++++++++-------- 7 files changed, 144 insertions(+), 70 deletions(-) diff --git a/make/java/nio/mapfile-linux b/make/java/nio/mapfile-linux index c8fef869d..7738adb1a 100644 --- a/make/java/nio/mapfile-linux +++ b/make/java/nio/mapfile-linux @@ -95,6 +95,8 @@ SUNWprivate_1.1 { Java_sun_nio_ch_NativeThread_current; Java_sun_nio_ch_NativeThread_init; Java_sun_nio_ch_NativeThread_signal; + Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0; + Java_sun_nio_ch_Net_canJoin6WithIPv4Group0; Java_sun_nio_ch_Net_socket0; Java_sun_nio_ch_Net_bind0; Java_sun_nio_ch_Net_connect0; diff --git a/make/java/nio/mapfile-solaris b/make/java/nio/mapfile-solaris index 978aa205c..c295f8771 100644 --- a/make/java/nio/mapfile-solaris +++ b/make/java/nio/mapfile-solaris @@ -82,6 +82,8 @@ SUNWprivate_1.1 { Java_sun_nio_ch_NativeThread_current; Java_sun_nio_ch_NativeThread_init; Java_sun_nio_ch_NativeThread_signal; + Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0; + Java_sun_nio_ch_Net_canJoin6WithIPv4Group0; Java_sun_nio_ch_Net_socket0; Java_sun_nio_ch_Net_bind0; Java_sun_nio_ch_Net_connect0; diff --git a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java index 8d2e31bf7..e63e473ef 100644 --- a/src/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/src/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -755,11 +755,14 @@ class DatagramChannelImpl throw new IllegalArgumentException("Group not a multicast address"); // check multicast address is compatible with this socket - if (!(group instanceof Inet4Address)) { - if (family == StandardProtocolFamily.INET) - throw new IllegalArgumentException("Group is not IPv4 address"); - if (!(group instanceof Inet6Address)) - throw new IllegalArgumentException("Address type not supported"); + if (group instanceof Inet4Address) { + if (family == StandardProtocolFamily.INET6 && !Net.canIPv6SocketJoinIPv4Group()) + throw new IllegalArgumentException("Group is not IPv4 multicast address"); + } else if (group instanceof Inet6Address) { + if (family != StandardProtocolFamily.INET6) + throw new IllegalArgumentException("Group is not IPv6 multicast address"); + } else { + throw new IllegalArgumentException("Address type not supported"); } // check source address @@ -791,7 +794,9 @@ class DatagramChannelImpl } MembershipKeyImpl key; - if (family == StandardProtocolFamily.INET6) { + if ((family == StandardProtocolFamily.INET6) && + ((group instanceof Inet6Address) || Net.canJoin6WithIPv4Group())) + { int index = interf.getIndex(); if (index == -1) throw new IOException("Network interface cannot be identified"); @@ -861,7 +866,7 @@ class DatagramChannelImpl return; try { - if (family == StandardProtocolFamily.INET6) { + if (key instanceof MembershipKeyImpl.Type6) { MembershipKeyImpl.Type6 key6 = (MembershipKeyImpl.Type6)key; Net.drop6(fd, key6.groupAddress(), key6.index(), key6.source()); @@ -901,7 +906,7 @@ class DatagramChannelImpl throw new IllegalArgumentException("Source address is different type to group"); int n; - if (family == StandardProtocolFamily.INET6) { + if (key instanceof MembershipKeyImpl.Type6) { MembershipKeyImpl.Type6 key6 = (MembershipKeyImpl.Type6)key; n = Net.block6(fd, key6.groupAddress(), key6.index(), @@ -931,7 +936,7 @@ class DatagramChannelImpl throw new IllegalStateException("key is no longer valid"); try { - if (family == StandardProtocolFamily.INET6) { + if (key instanceof MembershipKeyImpl.Type6) { MembershipKeyImpl.Type6 key6 = (MembershipKeyImpl.Type6)key; Net.unblock6(fd, key6.groupAddress(), key6.index(), diff --git a/src/share/classes/sun/nio/ch/Net.java b/src/share/classes/sun/nio/ch/Net.java index b1b893a5c..4324350e6 100644 --- a/src/share/classes/sun/nio/ch/Net.java +++ b/src/share/classes/sun/nio/ch/Net.java @@ -60,6 +60,21 @@ class Net { // package-private return isIPv6Available; } + /** + * Tells whether IPv6 sockets can join IPv4 multicast groups + */ + static boolean canIPv6SocketJoinIPv4Group() { + return canIPv6SocketJoinIPv4Group0(); + } + + /** + * Tells whether {@link #join6} can be used to join an IPv4 + * multicast group (IPv4 group as IPv4-mapped IPv6 address) + */ + static boolean canJoin6WithIPv4Group() { + return canJoin6WithIPv4Group0(); + } + static InetSocketAddress checkAddress(SocketAddress sa) { if (sa == null) throw new NullPointerException(); @@ -291,7 +306,11 @@ class Net { // package-private // -- Socket operations -- - static native boolean isIPv6Available0(); + private static native boolean isIPv6Available0(); + + private static native boolean canIPv6SocketJoinIPv4Group0(); + + private static native boolean canJoin6WithIPv4Group0(); static FileDescriptor socket(boolean stream) { return socket(UNSPEC, stream); diff --git a/src/solaris/native/sun/nio/ch/Net.c b/src/solaris/native/sun/nio/ch/Net.c index c43664c50..9f9b4669a 100644 --- a/src/solaris/native/sun/nio/ch/Net.c +++ b/src/solaris/native/sun/nio/ch/Net.c @@ -154,6 +154,22 @@ Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl) return (ipv6_available()) ? JNI_TRUE : JNI_FALSE; } +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl) +{ + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl) +{ +#ifdef __solaris__ + return JNI_TRUE; +#else + return JNI_FALSE; +#endif +} + JNIEXPORT int JNICALL Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6, jboolean stream, jboolean reuse) diff --git a/src/windows/native/sun/nio/ch/Net.c b/src/windows/native/sun/nio/ch/Net.c index b415cdfc3..75c9ba4ce 100644 --- a/src/windows/native/sun/nio/ch/Net.c +++ b/src/windows/native/sun/nio/ch/Net.c @@ -100,6 +100,18 @@ Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl) return JNI_FALSE; } +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0(JNIEnv* env, jclass cl) +{ + return JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl) +{ + return JNI_FALSE; +} + JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6, jboolean stream, jboolean reuse) diff --git a/test/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java b/test/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java index aa79e2214..f4445bb94 100644 --- a/test/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java +++ b/test/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4527345 + * @bug 4527345 7026376 * @summary Unit test for DatagramChannel's multicast support * @build MulticastSendReceiveTests NetworkConfiguration * @run main MulticastSendReceiveTests @@ -31,12 +31,19 @@ import java.nio.ByteBuffer; import java.nio.channels.*; import java.net.*; +import static java.net.StandardProtocolFamily.*; import java.util.*; import java.io.IOException; public class MulticastSendReceiveTests { - static Random rand = new Random(); + static final Random rand = new Random(); + + static final ProtocolFamily UNSPEC = new ProtocolFamily() { + public String name() { + return "UNSPEC"; + } + }; /** * Send datagram from given local address to given multicast @@ -130,75 +137,84 @@ public class MulticastSendReceiveTests { /** * Exercise multicast send/receive on given group/interface */ - static void test(NetworkInterface nif, InetAddress group, InetAddress source) + static void test(ProtocolFamily family, + NetworkInterface nif, + InetAddress group, + InetAddress source) throws IOException { - ProtocolFamily family = (group instanceof Inet6Address) ? - StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; - System.out.format("create channel to %s socket\n", family.name()); - DatagramChannel dc = DatagramChannel.open(family) - .setOption(StandardSocketOption.SO_REUSEADDR, true) - .bind(new InetSocketAddress(0)); - - // join group - System.out.format("join %s @ %s\n", group.getHostAddress(), - nif.getName()); - MembershipKey key = dc.join(group, nif); - - // send message to group - int port = ((InetSocketAddress)dc.getLocalAddress()).getPort(); - int id = sendDatagram(source, nif, group, port); - - // receive message and check id matches - receiveDatagram(dc, source, id); + System.out.format("\nTest DatagramChannel to %s socket\n", family.name()); + try (DatagramChannel dc = (family == UNSPEC) ? + DatagramChannel.open() : DatagramChannel.open(family)) { + dc.setOption(StandardSocketOption.SO_REUSEADDR, true) + .bind(new InetSocketAddress(0)); + + // join group + System.out.format("join %s @ %s\n", group.getHostAddress(), + nif.getName()); + MembershipKey key; + try { + key = dc.join(group, nif); + } catch (IllegalArgumentException iae) { + if (family == UNSPEC) { + System.out.println("Not supported"); + return; + } + throw iae; + } - // exclude-mode filtering + // send message to group + int port = ((InetSocketAddress)dc.getLocalAddress()).getPort(); + int id = sendDatagram(source, nif, group, port); - try { - System.out.format("block %s\n", source.getHostAddress()); + // receive message and check id matches + receiveDatagram(dc, source, id); - // may throw UOE - key.block(source); - id = sendDatagram(source, nif, group, port); - receiveDatagram(dc, null, id); + // exclude-mode filtering - // unblock source, send message, message should be received - System.out.format("unblock %s\n", source.getHostAddress()); - key.unblock(source); - id = sendDatagram(source, nif, group, port); - receiveDatagram(dc, source, id); - } catch (UnsupportedOperationException x) { - System.out.println("Exclude-mode filtering not supported!"); - } + try { + System.out.format("block %s\n", source.getHostAddress()); - key.drop(); + // may throw UOE + key.block(source); + id = sendDatagram(source, nif, group, port); + receiveDatagram(dc, null, id); - // include-mode filtering + // unblock source, send message, message should be received + System.out.format("unblock %s\n", source.getHostAddress()); + key.unblock(source); + id = sendDatagram(source, nif, group, port); + receiveDatagram(dc, source, id); + } catch (UnsupportedOperationException x) { + System.out.println("Exclude-mode filtering not supported!"); + } - InetAddress bogus = (group instanceof Inet6Address) ? - InetAddress.getByName("fe80::1234") : - InetAddress.getByName("1.2.3.4"); - System.out.format("join %s @ %s only-source %s\n", group.getHostAddress(), - nif.getName(), bogus.getHostAddress()); - try { - // may throw UOE - key = dc.join(group, nif, bogus); + key.drop(); - id = sendDatagram(source, nif, group, port); - receiveDatagram(dc, null, id); + // include-mode filtering + InetAddress bogus = (group instanceof Inet6Address) ? + InetAddress.getByName("fe80::1234") : + InetAddress.getByName("1.2.3.4"); System.out.format("join %s @ %s only-source %s\n", group.getHostAddress(), - nif.getName(), source.getHostAddress()); - key = dc.join(group, nif, source); - - id = sendDatagram(source, nif, group, port); - receiveDatagram(dc, source, id); - } catch (UnsupportedOperationException x) { - System.out.println("Include-mode filtering not supported!"); + nif.getName(), bogus.getHostAddress()); + try { + // may throw UOE + key = dc.join(group, nif, bogus); + + id = sendDatagram(source, nif, group, port); + receiveDatagram(dc, null, id); + + System.out.format("join %s @ %s only-source %s\n", group.getHostAddress(), + nif.getName(), source.getHostAddress()); + key = dc.join(group, nif, source); + + id = sendDatagram(source, nif, group, port); + receiveDatagram(dc, source, id); + } catch (UnsupportedOperationException x) { + System.out.println("Include-mode filtering not supported!"); + } } - - // done - dc.close(); } public static void main(String[] args) throws IOException { @@ -210,12 +226,14 @@ public class MulticastSendReceiveTests { for (NetworkInterface nif: config.ip4Interfaces()) { InetAddress source = config.ip4Addresses(nif).iterator().next(); - test(nif, ip4Group, source); + test(INET, nif, ip4Group, source); + test(UNSPEC, nif, ip4Group, source); } for (NetworkInterface nif: config.ip6Interfaces()) { InetAddress source = config.ip6Addresses(nif).iterator().next(); - test(nif, ip6Group, source); + test(INET6, nif, ip6Group, source); + test(UNSPEC, nif, ip6Group, source); } } } -- GitLab