提交 efcd30d7 编写于 作者: A alanb

7026376: (dc) DatagramChannel created without specifying protocol family fails to join IPv4 group

Reviewed-by: chegar
上级 d9840162
...@@ -95,6 +95,8 @@ SUNWprivate_1.1 { ...@@ -95,6 +95,8 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_NativeThread_current; Java_sun_nio_ch_NativeThread_current;
Java_sun_nio_ch_NativeThread_init; Java_sun_nio_ch_NativeThread_init;
Java_sun_nio_ch_NativeThread_signal; 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_socket0;
Java_sun_nio_ch_Net_bind0; Java_sun_nio_ch_Net_bind0;
Java_sun_nio_ch_Net_connect0; Java_sun_nio_ch_Net_connect0;
......
...@@ -82,6 +82,8 @@ SUNWprivate_1.1 { ...@@ -82,6 +82,8 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_NativeThread_current; Java_sun_nio_ch_NativeThread_current;
Java_sun_nio_ch_NativeThread_init; Java_sun_nio_ch_NativeThread_init;
Java_sun_nio_ch_NativeThread_signal; 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_socket0;
Java_sun_nio_ch_Net_bind0; Java_sun_nio_ch_Net_bind0;
Java_sun_nio_ch_Net_connect0; Java_sun_nio_ch_Net_connect0;
......
...@@ -755,11 +755,14 @@ class DatagramChannelImpl ...@@ -755,11 +755,14 @@ class DatagramChannelImpl
throw new IllegalArgumentException("Group not a multicast address"); throw new IllegalArgumentException("Group not a multicast address");
// check multicast address is compatible with this socket // check multicast address is compatible with this socket
if (!(group instanceof Inet4Address)) { if (group instanceof Inet4Address) {
if (family == StandardProtocolFamily.INET) if (family == StandardProtocolFamily.INET6 && !Net.canIPv6SocketJoinIPv4Group())
throw new IllegalArgumentException("Group is not IPv4 address"); throw new IllegalArgumentException("Group is not IPv4 multicast address");
if (!(group instanceof Inet6Address)) } else if (group instanceof Inet6Address) {
throw new IllegalArgumentException("Address type not supported"); if (family != StandardProtocolFamily.INET6)
throw new IllegalArgumentException("Group is not IPv6 multicast address");
} else {
throw new IllegalArgumentException("Address type not supported");
} }
// check source address // check source address
...@@ -791,7 +794,9 @@ class DatagramChannelImpl ...@@ -791,7 +794,9 @@ class DatagramChannelImpl
} }
MembershipKeyImpl key; MembershipKeyImpl key;
if (family == StandardProtocolFamily.INET6) { if ((family == StandardProtocolFamily.INET6) &&
((group instanceof Inet6Address) || Net.canJoin6WithIPv4Group()))
{
int index = interf.getIndex(); int index = interf.getIndex();
if (index == -1) if (index == -1)
throw new IOException("Network interface cannot be identified"); throw new IOException("Network interface cannot be identified");
...@@ -861,7 +866,7 @@ class DatagramChannelImpl ...@@ -861,7 +866,7 @@ class DatagramChannelImpl
return; return;
try { try {
if (family == StandardProtocolFamily.INET6) { if (key instanceof MembershipKeyImpl.Type6) {
MembershipKeyImpl.Type6 key6 = MembershipKeyImpl.Type6 key6 =
(MembershipKeyImpl.Type6)key; (MembershipKeyImpl.Type6)key;
Net.drop6(fd, key6.groupAddress(), key6.index(), key6.source()); Net.drop6(fd, key6.groupAddress(), key6.index(), key6.source());
...@@ -901,7 +906,7 @@ class DatagramChannelImpl ...@@ -901,7 +906,7 @@ class DatagramChannelImpl
throw new IllegalArgumentException("Source address is different type to group"); throw new IllegalArgumentException("Source address is different type to group");
int n; int n;
if (family == StandardProtocolFamily.INET6) { if (key instanceof MembershipKeyImpl.Type6) {
MembershipKeyImpl.Type6 key6 = MembershipKeyImpl.Type6 key6 =
(MembershipKeyImpl.Type6)key; (MembershipKeyImpl.Type6)key;
n = Net.block6(fd, key6.groupAddress(), key6.index(), n = Net.block6(fd, key6.groupAddress(), key6.index(),
...@@ -931,7 +936,7 @@ class DatagramChannelImpl ...@@ -931,7 +936,7 @@ class DatagramChannelImpl
throw new IllegalStateException("key is no longer valid"); throw new IllegalStateException("key is no longer valid");
try { try {
if (family == StandardProtocolFamily.INET6) { if (key instanceof MembershipKeyImpl.Type6) {
MembershipKeyImpl.Type6 key6 = MembershipKeyImpl.Type6 key6 =
(MembershipKeyImpl.Type6)key; (MembershipKeyImpl.Type6)key;
Net.unblock6(fd, key6.groupAddress(), key6.index(), Net.unblock6(fd, key6.groupAddress(), key6.index(),
......
...@@ -60,6 +60,21 @@ class Net { // package-private ...@@ -60,6 +60,21 @@ class Net { // package-private
return isIPv6Available; 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) { static InetSocketAddress checkAddress(SocketAddress sa) {
if (sa == null) if (sa == null)
throw new NullPointerException(); throw new NullPointerException();
...@@ -291,7 +306,11 @@ class Net { // package-private ...@@ -291,7 +306,11 @@ class Net { // package-private
// -- Socket operations -- // -- 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) { static FileDescriptor socket(boolean stream) {
return socket(UNSPEC, stream); return socket(UNSPEC, stream);
......
...@@ -154,6 +154,22 @@ Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl) ...@@ -154,6 +154,22 @@ Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
return (ipv6_available()) ? JNI_TRUE : JNI_FALSE; 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 JNIEXPORT int JNICALL
Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6, Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
jboolean stream, jboolean reuse) jboolean stream, jboolean reuse)
......
...@@ -100,6 +100,18 @@ Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl) ...@@ -100,6 +100,18 @@ Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl)
return JNI_FALSE; 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 JNIEXPORT jint JNICALL
Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6, Java_sun_nio_ch_Net_socket0(JNIEnv *env, jclass cl, jboolean preferIPv6,
jboolean stream, jboolean reuse) jboolean stream, jboolean reuse)
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
*/ */
/* @test /* @test
* @bug 4527345 * @bug 4527345 7026376
* @summary Unit test for DatagramChannel's multicast support * @summary Unit test for DatagramChannel's multicast support
* @build MulticastSendReceiveTests NetworkConfiguration * @build MulticastSendReceiveTests NetworkConfiguration
* @run main MulticastSendReceiveTests * @run main MulticastSendReceiveTests
...@@ -31,12 +31,19 @@ ...@@ -31,12 +31,19 @@
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.*; import java.nio.channels.*;
import java.net.*; import java.net.*;
import static java.net.StandardProtocolFamily.*;
import java.util.*; import java.util.*;
import java.io.IOException; import java.io.IOException;
public class MulticastSendReceiveTests { 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 * Send datagram from given local address to given multicast
...@@ -130,75 +137,84 @@ public class MulticastSendReceiveTests { ...@@ -130,75 +137,84 @@ public class MulticastSendReceiveTests {
/** /**
* Exercise multicast send/receive on given group/interface * 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 throws IOException
{ {
ProtocolFamily family = (group instanceof Inet6Address) ? System.out.format("\nTest DatagramChannel to %s socket\n", family.name());
StandardProtocolFamily.INET6 : StandardProtocolFamily.INET; try (DatagramChannel dc = (family == UNSPEC) ?
System.out.format("create channel to %s socket\n", family.name()); DatagramChannel.open() : DatagramChannel.open(family)) {
DatagramChannel dc = DatagramChannel.open(family) dc.setOption(StandardSocketOption.SO_REUSEADDR, true)
.setOption(StandardSocketOption.SO_REUSEADDR, true) .bind(new InetSocketAddress(0));
.bind(new InetSocketAddress(0));
// join group
// join group System.out.format("join %s @ %s\n", group.getHostAddress(),
System.out.format("join %s @ %s\n", group.getHostAddress(), nif.getName());
nif.getName()); MembershipKey key;
MembershipKey key = dc.join(group, nif); try {
key = dc.join(group, nif);
// send message to group } catch (IllegalArgumentException iae) {
int port = ((InetSocketAddress)dc.getLocalAddress()).getPort(); if (family == UNSPEC) {
int id = sendDatagram(source, nif, group, port); System.out.println("Not supported");
return;
// receive message and check id matches }
receiveDatagram(dc, source, id); throw iae;
}
// exclude-mode filtering // send message to group
int port = ((InetSocketAddress)dc.getLocalAddress()).getPort();
int id = sendDatagram(source, nif, group, port);
try { // receive message and check id matches
System.out.format("block %s\n", source.getHostAddress()); receiveDatagram(dc, source, id);
// may throw UOE // exclude-mode filtering
key.block(source);
id = sendDatagram(source, nif, group, port);
receiveDatagram(dc, null, id);
// unblock source, send message, message should be received try {
System.out.format("unblock %s\n", source.getHostAddress()); System.out.format("block %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!");
}
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) ? key.drop();
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); // include-mode filtering
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(), System.out.format("join %s @ %s only-source %s\n", group.getHostAddress(),
nif.getName(), source.getHostAddress()); nif.getName(), bogus.getHostAddress());
key = dc.join(group, nif, source); try {
// may throw UOE
id = sendDatagram(source, nif, group, port); key = dc.join(group, nif, bogus);
receiveDatagram(dc, source, id);
} catch (UnsupportedOperationException x) { id = sendDatagram(source, nif, group, port);
System.out.println("Include-mode filtering not supported!"); 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 { public static void main(String[] args) throws IOException {
...@@ -210,12 +226,14 @@ public class MulticastSendReceiveTests { ...@@ -210,12 +226,14 @@ public class MulticastSendReceiveTests {
for (NetworkInterface nif: config.ip4Interfaces()) { for (NetworkInterface nif: config.ip4Interfaces()) {
InetAddress source = config.ip4Addresses(nif).iterator().next(); 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()) { for (NetworkInterface nif: config.ip6Interfaces()) {
InetAddress source = config.ip6Addresses(nif).iterator().next(); InetAddress source = config.ip6Addresses(nif).iterator().next();
test(nif, ip6Group, source); test(INET6, nif, ip6Group, source);
test(UNSPEC, nif, ip6Group, source);
} }
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册