7026376: (dc) DatagramChannel created without specifying protocol family fails to join IPv4 group
Reviewed-by: chegar
--- a/jdk/make/java/nio/mapfile-linux Mon Mar 14 14:49:52 2011 -0700
+++ b/jdk/make/java/nio/mapfile-linux Tue Mar 15 13:15:31 2011 +0000
@@ -95,6 +95,8 @@
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;
--- a/jdk/make/java/nio/mapfile-solaris Mon Mar 14 14:49:52 2011 -0700
+++ b/jdk/make/java/nio/mapfile-solaris Tue Mar 15 13:15:31 2011 +0000
@@ -82,6 +82,8 @@
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;
--- a/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java Mon Mar 14 14:49:52 2011 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/DatagramChannelImpl.java Tue Mar 15 13:15:31 2011 +0000
@@ -755,11 +755,14 @@
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 @@
}
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 @@
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 @@
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 @@
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(),
--- a/jdk/src/share/classes/sun/nio/ch/Net.java Mon Mar 14 14:49:52 2011 -0700
+++ b/jdk/src/share/classes/sun/nio/ch/Net.java Tue Mar 15 13:15:31 2011 +0000
@@ -60,6 +60,21 @@
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 @@
// -- 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);
--- a/jdk/src/solaris/native/sun/nio/ch/Net.c Mon Mar 14 14:49:52 2011 -0700
+++ b/jdk/src/solaris/native/sun/nio/ch/Net.c Tue Mar 15 13:15:31 2011 +0000
@@ -154,6 +154,22 @@
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)
--- a/jdk/src/windows/native/sun/nio/ch/Net.c Mon Mar 14 14:49:52 2011 -0700
+++ b/jdk/src/windows/native/sun/nio/ch/Net.c Tue Mar 15 13:15:31 2011 +0000
@@ -100,6 +100,18 @@
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)
--- a/jdk/test/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java Mon Mar 14 14:49:52 2011 -0700
+++ b/jdk/test/java/nio/channels/DatagramChannel/MulticastSendReceiveTests.java Tue Mar 15 13:15:31 2011 +0000
@@ -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 @@
/**
* 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);
+ 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));
- // 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);
+ // 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
-
- try {
- System.out.format("block %s\n", source.getHostAddress());
+ // send message to group
+ int port = ((InetSocketAddress)dc.getLocalAddress()).getPort();
+ int id = sendDatagram(source, nif, group, port);
- // may throw UOE
- key.block(source);
- id = sendDatagram(source, nif, group, port);
- receiveDatagram(dc, null, id);
+ // receive message and check id matches
+ receiveDatagram(dc, source, id);
+
+ // exclude-mode filtering
+
+ try {
+ System.out.format("block %s\n", source.getHostAddress());
- // 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!");
- }
+ // may throw UOE
+ key.block(source);
+ id = sendDatagram(source, nif, group, port);
+ receiveDatagram(dc, null, id);
- key.drop();
+ // 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!");
+ }
- // include-mode filtering
+ key.drop();
+
+ // 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(), bogus.getHostAddress());
- try {
- // may throw UOE
- key = dc.join(group, nif, bogus);
-
- id = sendDatagram(source, nif, group, port);
- receiveDatagram(dc, null, id);
+ 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);
- 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, 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!");
+ 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 @@
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);
}
}
}