8241786: Improve heuristic to determine default network interface on macOS
DefaultInetrface.getDefault is updated to prefer interfaces that have non link-local addresses. NetworkConfiguration is updated to skip interface that have only link-local addresses, whether IPv4 or IPv6, for multicasting. Reviewed-by: chegar, alanb
This commit is contained in:
parent
553ea1e891
commit
f541970b31
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2020, 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
|
||||
@ -54,11 +54,30 @@ class DefaultInterface {
|
||||
/**
|
||||
* Choose a default interface. This method returns the first interface that
|
||||
* is both "up" and supports multicast. This method chooses an interface in
|
||||
* order of preference:
|
||||
* 1. neither loopback nor point to point
|
||||
* ( prefer interfaces with dual IP support )
|
||||
* 2. point to point
|
||||
* 3. loopback
|
||||
* order of preference, using the following algorithm:
|
||||
*
|
||||
* <pre>
|
||||
* Interfaces that are down, or don't support multicasting, are skipped.
|
||||
* In steps 1-4 below, PPP and loopback interfaces are skipped.
|
||||
*
|
||||
* 1. The first interface that has at least an IPv4 address, and an IPv6 address,
|
||||
* and a non link-local IP address, is picked.
|
||||
*
|
||||
* 2. If none is found, then the first interface that has at least an
|
||||
* IPv4 address, and an IPv6 address is picked.
|
||||
*
|
||||
* 3. If none is found, then the first interface that has at least a
|
||||
* non link local IP address is picked.
|
||||
*
|
||||
* 4. If none is found, then the first non loopback and non PPP interface
|
||||
* is picked.
|
||||
*
|
||||
* 5. If none is found then first PPP interface is picked.
|
||||
*
|
||||
* 6. If none is found, then the first loopback interface is picked.
|
||||
*
|
||||
* 7. If none is found, then null is returned.
|
||||
* </pre>
|
||||
*
|
||||
* @return the chosen interface or {@code null} if there isn't a suitable
|
||||
* default
|
||||
@ -74,6 +93,8 @@ class DefaultInterface {
|
||||
}
|
||||
|
||||
NetworkInterface preferred = null;
|
||||
NetworkInterface dual = null;
|
||||
NetworkInterface nonLinkLocal = null;
|
||||
NetworkInterface ppp = null;
|
||||
NetworkInterface loopback = null;
|
||||
|
||||
@ -83,7 +104,7 @@ class DefaultInterface {
|
||||
if (!ni.isUp() || !ni.supportsMulticast())
|
||||
continue;
|
||||
|
||||
boolean ip4 = false, ip6 = false;
|
||||
boolean ip4 = false, ip6 = false, isNonLinkLocal = false;
|
||||
PrivilegedAction<Enumeration<InetAddress>> pa = ni::getInetAddresses;
|
||||
Enumeration<InetAddress> addrs = AccessController.doPrivileged(pa);
|
||||
while (addrs.hasMoreElements()) {
|
||||
@ -94,6 +115,9 @@ class DefaultInterface {
|
||||
} else if (addr instanceof Inet6Address) {
|
||||
ip6 = true;
|
||||
}
|
||||
if (!addr.isLinkLocalAddress()) {
|
||||
isNonLinkLocal = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,8 +128,13 @@ class DefaultInterface {
|
||||
// point-to-point interface
|
||||
if (preferred == null) {
|
||||
preferred = ni;
|
||||
} else if (ip4 && ip6){
|
||||
return ni;
|
||||
}
|
||||
if (ip4 && ip6) {
|
||||
if (isNonLinkLocal) return ni;
|
||||
if (dual == null) dual = ni;
|
||||
}
|
||||
if (nonLinkLocal == null) {
|
||||
if (isNonLinkLocal) nonLinkLocal = ni;
|
||||
}
|
||||
}
|
||||
if (ppp == null && isPPP)
|
||||
@ -116,7 +145,11 @@ class DefaultInterface {
|
||||
} catch (IOException skip) { }
|
||||
}
|
||||
|
||||
if (preferred != null) {
|
||||
if (dual != null) {
|
||||
return dual;
|
||||
} else if (nonLinkLocal != null) {
|
||||
return nonLinkLocal;
|
||||
} else if (preferred != null) {
|
||||
return preferred;
|
||||
} else {
|
||||
return (ppp != null) ? ppp : loopback;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2020, 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
|
||||
@ -26,11 +26,14 @@
|
||||
* @bug 4686717
|
||||
* @summary Test MulticastSocket.setLoopbackMode
|
||||
* @library /test/lib
|
||||
* @modules java.base/java.net:+open
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* jdk.test.lib.Platform
|
||||
* @run main/othervm SetLoopbackMode
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.UndeclaredThrowableException;
|
||||
import java.net.*;
|
||||
import java.io.IOException;
|
||||
import jdk.test.lib.NetworkConfiguration;
|
||||
@ -99,38 +102,75 @@ public class SetLoopbackMode {
|
||||
int failures = 0;
|
||||
NetworkConfiguration nc = NetworkConfiguration.probe();
|
||||
|
||||
MulticastSocket mc = new MulticastSocket();
|
||||
InetAddress grp = InetAddress.getByName("224.80.80.80");
|
||||
try (MulticastSocket mc = new MulticastSocket()) {
|
||||
InetAddress grp = InetAddress.getByName("224.80.80.80");
|
||||
|
||||
|
||||
/*
|
||||
* If IPv6 is available then use IPv6 multicast group - needed
|
||||
* to workaround Linux IPv6 bug whereby !IPV6_MULTICAST_LOOP
|
||||
* doesn't prevent loopback of IPv4 multicast packets.
|
||||
*/
|
||||
/*
|
||||
* If IPv6 is available then use IPv6 multicast group - needed
|
||||
* to workaround Linux IPv6 bug whereby !IPV6_MULTICAST_LOOP
|
||||
* doesn't prevent loopback of IPv4 multicast packets.
|
||||
*/
|
||||
|
||||
if (canUseIPv6(nc)) {
|
||||
grp = InetAddress.getByName("ff01::1");
|
||||
if (canUseIPv6(nc)) {
|
||||
System.out.println("IPv6 can be used");
|
||||
grp = InetAddress.getByName("ff01::1");
|
||||
} else {
|
||||
System.out.println("IPv6 cannot be used: using IPv4");
|
||||
}
|
||||
System.out.println("Default network interface: " + DefaultInterface.getDefaultName());
|
||||
System.out.println("\nTest will use multicast group: " + grp);
|
||||
try {
|
||||
System.out.println("NetworkInterface.getByInetAddress(grp): "
|
||||
+ getName(NetworkInterface.getByInetAddress(grp)));
|
||||
} catch (Exception x) {
|
||||
// OK
|
||||
}
|
||||
mc.joinGroup(grp);
|
||||
|
||||
System.out.println("\n******************\n");
|
||||
|
||||
mc.setLoopbackMode(true);
|
||||
if (test(mc, grp) == FAILED) failures++;
|
||||
|
||||
System.out.println("\n******************\n");
|
||||
|
||||
mc.setLoopbackMode(false);
|
||||
if (test(mc, grp) == FAILED) failures++;
|
||||
|
||||
System.out.println("\n******************\n");
|
||||
|
||||
if (failures > 0) {
|
||||
throw new RuntimeException("Test failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//mc.setNetworkInterface(NetworkInterface.getByInetAddress(lb));
|
||||
System.out.println("\nTest will use multicast group: " + grp);
|
||||
mc.joinGroup(grp);
|
||||
static String getName(NetworkInterface nif) {
|
||||
return nif == null ? null : nif.getName();
|
||||
}
|
||||
|
||||
System.out.println("\n******************\n");
|
||||
|
||||
mc.setLoopbackMode(true);
|
||||
if (test(mc, grp) == FAILED) failures++;
|
||||
|
||||
System.out.println("\n******************\n");
|
||||
|
||||
mc.setLoopbackMode(false);
|
||||
if (test(mc, grp) == FAILED) failures++;
|
||||
|
||||
System.out.println("\n******************\n");
|
||||
|
||||
if (failures > 0) {
|
||||
throw new RuntimeException("Test failed");
|
||||
static class DefaultInterface {
|
||||
static final Method GET_DEFAULT;
|
||||
static {
|
||||
try {
|
||||
GET_DEFAULT = Class.forName("java.net.DefaultInterface")
|
||||
.getDeclaredMethod("getDefault");
|
||||
GET_DEFAULT.setAccessible(true);
|
||||
} catch (Exception x) {
|
||||
throw new ExceptionInInitializerError(x);
|
||||
}
|
||||
}
|
||||
static NetworkInterface getDefault() {
|
||||
try {
|
||||
return (NetworkInterface) GET_DEFAULT
|
||||
.invoke(null);
|
||||
} catch (Exception x) {
|
||||
throw new UndeclaredThrowableException(x);
|
||||
}
|
||||
}
|
||||
static String getDefaultName() {
|
||||
return getName(getDefault());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2020, 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,9 +23,10 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4686717
|
||||
* @bug 4686717 8241786
|
||||
* @summary Test MulticastSocket.setLoopbackMode with IPv4 addresses
|
||||
* @library /test/lib
|
||||
* @modules java.base/java.net:+open
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* jdk.test.lib.Platform
|
||||
* SetLoopbackMode
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2020, 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,13 +23,15 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4742177
|
||||
* @bug 4742177 8241786
|
||||
* @library /test/lib
|
||||
* @run main/othervm SetOutgoingIf
|
||||
* @summary Re-test IPv6 (and specifically MulticastSocket) with latest Linux & USAGI code
|
||||
*/
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import jdk.test.lib.NetworkConfiguration;
|
||||
|
||||
|
||||
@ -37,6 +39,7 @@ public class SetOutgoingIf implements AutoCloseable {
|
||||
private static String osname;
|
||||
private final MulticastSocket SOCKET;
|
||||
private final int PORT;
|
||||
private final Map<NetIf, MulticastSender> sendersMap = new ConcurrentHashMap<>();
|
||||
private SetOutgoingIf() {
|
||||
try {
|
||||
SOCKET = new MulticastSocket();
|
||||
@ -71,7 +74,11 @@ public class SetOutgoingIf implements AutoCloseable {
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
SOCKET.close();
|
||||
try {
|
||||
SOCKET.close();
|
||||
} finally {
|
||||
sendersMap.values().stream().forEach(MulticastSender::close);
|
||||
}
|
||||
}
|
||||
|
||||
public void run() throws Exception {
|
||||
@ -148,9 +155,9 @@ public class SetOutgoingIf implements AutoCloseable {
|
||||
netIf.groups(groups);
|
||||
|
||||
// use a separated thread to send to those 2 groups
|
||||
Thread sender = new Thread(new Sender(netIf,
|
||||
groups,
|
||||
PORT));
|
||||
var multicastSender = new MulticastSender(netIf, groups, PORT);
|
||||
sendersMap.put(netIf, multicastSender);
|
||||
Thread sender = new Thread(multicastSender);
|
||||
sender.setDaemon(true); // we want sender to stop when main thread exits
|
||||
sender.start();
|
||||
}
|
||||
@ -162,42 +169,44 @@ public class SetOutgoingIf implements AutoCloseable {
|
||||
for (NetIf netIf : netIfs) {
|
||||
NetworkInterface nic = netIf.nic();
|
||||
for (InetAddress group : netIf.groups()) {
|
||||
MulticastSocket mcastsock = new MulticastSocket(PORT);
|
||||
mcastsock.setSoTimeout(5000); // 5 second
|
||||
DatagramPacket packet = new DatagramPacket(buf, 0, buf.length);
|
||||
try (MulticastSocket mcastsock = new MulticastSocket(PORT)) {
|
||||
mcastsock.setSoTimeout(5000); // 5 second
|
||||
DatagramPacket packet = new DatagramPacket(buf, 0, buf.length);
|
||||
|
||||
// the interface supports the IP multicast group
|
||||
debug("Joining " + group + " on " + nic.getName());
|
||||
mcastsock.joinGroup(new InetSocketAddress(group, PORT), nic);
|
||||
// the interface supports the IP multicast group
|
||||
debug("Joining " + group + " on " + nic.getName());
|
||||
mcastsock.joinGroup(new InetSocketAddress(group, PORT), nic);
|
||||
|
||||
try {
|
||||
mcastsock.receive(packet);
|
||||
debug("received packet on " + packet.getAddress());
|
||||
} catch (Exception e) {
|
||||
// test failed if any exception
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
// now check which network interface this packet comes from
|
||||
NetworkInterface from = NetworkInterface.getByInetAddress(packet.getAddress());
|
||||
NetworkInterface shouldbe = nic;
|
||||
if (from != null) {
|
||||
if (!from.equals(shouldbe)) {
|
||||
System.out.println("Packets on group "
|
||||
+ group + " should come from "
|
||||
+ shouldbe.getName() + ", but came from "
|
||||
+ from.getName());
|
||||
try {
|
||||
mcastsock.receive(packet);
|
||||
debug("received packet on " + packet.getAddress());
|
||||
} catch (Exception e) {
|
||||
// test failed if any exception
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
mcastsock.leaveGroup(new InetSocketAddress(group, PORT), nic);
|
||||
// now check which network interface this packet comes from
|
||||
NetworkInterface from = NetworkInterface.getByInetAddress(packet.getAddress());
|
||||
NetworkInterface shouldbe = nic;
|
||||
if (from != null) {
|
||||
if (!from.equals(shouldbe)) {
|
||||
System.out.println("Packets on group "
|
||||
+ group + " should come from "
|
||||
+ shouldbe.getName() + ", but came from "
|
||||
+ from.getName());
|
||||
}
|
||||
}
|
||||
|
||||
mcastsock.leaveGroup(new InetSocketAddress(group, PORT), nic);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isTestExcludedInterface(NetworkInterface nif) {
|
||||
return !NetworkConfiguration.isTestable(nif)
|
||||
|| isMacOS() && nif.getName().startsWith("utun");
|
||||
|| isMacOS() && nif.getName().startsWith("utun")
|
||||
|| !NetworkConfiguration.hasNonLinkLocalAddress(nif);
|
||||
}
|
||||
|
||||
private static boolean debug = true;
|
||||
@ -208,12 +217,14 @@ public class SetOutgoingIf implements AutoCloseable {
|
||||
}
|
||||
}
|
||||
|
||||
class Sender implements Runnable {
|
||||
private NetIf netIf;
|
||||
private List<InetAddress> groups;
|
||||
private int port;
|
||||
class MulticastSender implements Runnable, AutoCloseable {
|
||||
private final NetIf netIf;
|
||||
private final List<InetAddress> groups;
|
||||
private final int port;
|
||||
private volatile boolean closed;
|
||||
private long count;
|
||||
|
||||
public Sender(NetIf netIf,
|
||||
public MulticastSender(NetIf netIf,
|
||||
List<InetAddress> groups,
|
||||
int port) {
|
||||
this.netIf = netIf;
|
||||
@ -221,10 +232,15 @@ class Sender implements Runnable {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
closed = true;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
MulticastSocket mcastsock = new MulticastSocket();
|
||||
mcastsock.setNetworkInterface(netIf.nic());
|
||||
var nic = netIf.nic();
|
||||
try (MulticastSocket mcastsock = new MulticastSocket()) {
|
||||
mcastsock.setNetworkInterface(nic);
|
||||
List<DatagramPacket> packets = new LinkedList<DatagramPacket>();
|
||||
|
||||
byte[] buf = "hello world".getBytes();
|
||||
@ -232,14 +248,23 @@ class Sender implements Runnable {
|
||||
packets.add(new DatagramPacket(buf, buf.length, new InetSocketAddress(group, port)));
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
for (DatagramPacket packet : packets)
|
||||
while (!closed) {
|
||||
for (DatagramPacket packet : packets) {
|
||||
mcastsock.send(packet);
|
||||
|
||||
count++;
|
||||
}
|
||||
System.out.printf("Sent %d packets from %s\n", count, nic.getName());
|
||||
Thread.sleep(1000); // sleep 1 second
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
if (!closed) {
|
||||
System.err.println("Unexpected exception for MulticastSender("
|
||||
+ nic.getName() + "): " + e);
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} finally {
|
||||
System.out.printf("Sent %d packets from %s\n", count, nic.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,12 +22,12 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 8236925
|
||||
* @bug 8236925 8241786
|
||||
* @summary Test DatagramChannel socket adaptor as a MulticastSocket
|
||||
* @library /test/lib
|
||||
* @build jdk.test.lib.NetworkConfiguration
|
||||
* jdk.test.lib.net.IPSupport
|
||||
* @run main AdaptorMulticasting
|
||||
* @run main/othervm AdaptorMulticasting
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true AdaptorMulticasting
|
||||
*/
|
||||
|
||||
@ -130,6 +130,9 @@ public class AdaptorMulticasting {
|
||||
MulticastSocket s,
|
||||
InetAddress group,
|
||||
NetworkInterface ni) throws IOException {
|
||||
|
||||
System.out.format("testJoinGroup1: local socket address: %s%n", s.getLocalSocketAddress());
|
||||
|
||||
// check network interface not set
|
||||
assertTrue(s.getOption(IP_MULTICAST_IF) == null);
|
||||
|
||||
@ -180,6 +183,9 @@ public class AdaptorMulticasting {
|
||||
MulticastSocket s,
|
||||
InetAddress group,
|
||||
NetworkInterface ni) throws IOException {
|
||||
|
||||
System.out.format("testJoinGroup2: local socket address: %s%n", s.getLocalSocketAddress());
|
||||
|
||||
// check network interface not set
|
||||
assertTrue(s.getOption(IP_MULTICAST_IF) == null);
|
||||
|
||||
@ -399,6 +405,9 @@ public class AdaptorMulticasting {
|
||||
* Send a datagram to the given multicast group and check that it is received.
|
||||
*/
|
||||
static void testSendReceive(MulticastSocket s, InetAddress group) throws IOException {
|
||||
|
||||
System.out.println("testSendReceive");
|
||||
|
||||
// outgoing multicast interface needs to be set
|
||||
assertTrue(s.getOption(IP_MULTICAST_IF) != null);
|
||||
|
||||
@ -424,6 +433,9 @@ public class AdaptorMulticasting {
|
||||
* received.
|
||||
*/
|
||||
static void testSendNoReceive(MulticastSocket s, InetAddress group) throws IOException {
|
||||
|
||||
System.out.println("testSendNoReceive");
|
||||
|
||||
// outgoing multicast interface needs to be set
|
||||
assertTrue(s.getOption(IP_MULTICAST_IF) != null);
|
||||
|
||||
@ -446,7 +458,7 @@ public class AdaptorMulticasting {
|
||||
if (Arrays.equals(p.getData(), p.getOffset(), p.getLength(), message, 0, message.length)) {
|
||||
throw new RuntimeException("message shouldn't have been received");
|
||||
} else {
|
||||
System.out.println("Received unexpected message from " + p.getSocketAddress());
|
||||
System.out.format("Received unexpected message from %s%n", p.getSocketAddress());
|
||||
}
|
||||
} catch (SocketTimeoutException expected) {
|
||||
break;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2020, 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
|
||||
@ -68,16 +68,16 @@ public class MulticastSendReceiveTests {
|
||||
{
|
||||
ProtocolFamily family = (group instanceof Inet6Address) ?
|
||||
StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
|
||||
DatagramChannel dc = DatagramChannel.open(family)
|
||||
.bind(new InetSocketAddress(local, 0))
|
||||
.setOption(StandardSocketOptions.IP_MULTICAST_IF, nif);
|
||||
int id = rand.nextInt();
|
||||
byte[] msg = Integer.toString(id).getBytes("UTF-8");
|
||||
ByteBuffer buf = ByteBuffer.wrap(msg);
|
||||
System.out.format("Send message from %s -> group %s (id=0x%x)\n",
|
||||
local.getHostAddress(), group.getHostAddress(), id);
|
||||
dc.send(buf, new InetSocketAddress(group, port));
|
||||
dc.close();
|
||||
try (DatagramChannel dc = DatagramChannel.open(family)) {
|
||||
dc.bind(new InetSocketAddress(local, 0));
|
||||
dc.setOption(StandardSocketOptions.IP_MULTICAST_IF, nif);
|
||||
byte[] msg = Integer.toString(id).getBytes("UTF-8");
|
||||
ByteBuffer buf = ByteBuffer.wrap(msg);
|
||||
System.out.format("Send message from %s -> group %s (id=0x%x)\n",
|
||||
local.getHostAddress(), group.getHostAddress(), id);
|
||||
dc.send(buf, new InetSocketAddress(group, port));
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2020, 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
|
||||
@ -22,7 +22,7 @@
|
||||
*
|
||||
|
||||
/* @test
|
||||
* @bug 8014377
|
||||
* @bug 8014377 8241786
|
||||
* @summary Test for interference when two sockets are bound to the same
|
||||
* port but joined to different multicast groups
|
||||
* @library /test/lib
|
||||
@ -65,15 +65,15 @@ public class Promiscuous {
|
||||
{
|
||||
ProtocolFamily family = (group instanceof Inet6Address) ?
|
||||
StandardProtocolFamily.INET6 : StandardProtocolFamily.INET;
|
||||
DatagramChannel dc = DatagramChannel.open(family)
|
||||
.setOption(StandardSocketOptions.IP_MULTICAST_IF, nif);
|
||||
int id = rand.nextInt();
|
||||
byte[] msg = Integer.toString(id).getBytes("UTF-8");
|
||||
ByteBuffer buf = ByteBuffer.wrap(msg);
|
||||
System.out.format("Send message -> group %s (id=0x%x)\n",
|
||||
group.getHostAddress(), id);
|
||||
dc.send(buf, new InetSocketAddress(group, port));
|
||||
dc.close();
|
||||
try (DatagramChannel dc = DatagramChannel.open(family)) {
|
||||
dc.setOption(StandardSocketOptions.IP_MULTICAST_IF, nif);
|
||||
byte[] msg = Integer.toString(id).getBytes("UTF-8");
|
||||
ByteBuffer buf = ByteBuffer.wrap(msg);
|
||||
System.out.format("Send message -> group %s (id=0x%x)\n",
|
||||
group.getHostAddress(), id);
|
||||
dc.send(buf, new InetSocketAddress(group, port));
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
@ -97,12 +97,15 @@ public class NetworkConfiguration {
|
||||
if (nif.getName().contains("awdl")) {
|
||||
return false; // exclude awdl
|
||||
}
|
||||
// filter out interfaces that only have link-local addresses
|
||||
// filter out interfaces that only have link-local IPv6 addresses
|
||||
// on macOS interfaces like 'en6' fall in this category and
|
||||
// need to be skipped
|
||||
return nif.inetAddresses()
|
||||
.filter(Predicate.not(NetworkConfiguration::isIPv6LinkLocal))
|
||||
.findAny()
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
if (Platform.isWindows()) {
|
||||
String dName = nif.getDisplayName();
|
||||
if (dName != null && dName.contains("Teredo")) {
|
||||
@ -128,6 +131,12 @@ public class NetworkConfiguration {
|
||||
return ip6Interfaces.get(nif).stream().anyMatch(a -> !a.isAnyLocalAddress());
|
||||
}
|
||||
|
||||
public static boolean hasNonLinkLocalAddress(NetworkInterface nif) {
|
||||
return nif.inetAddresses()
|
||||
.filter(Predicate.not(InetAddress::isLinkLocalAddress))
|
||||
.findAny().isPresent();
|
||||
}
|
||||
|
||||
private boolean supportsIp4Multicast(NetworkInterface nif) {
|
||||
try {
|
||||
if (!nif.supportsMulticast()) {
|
||||
@ -145,6 +154,14 @@ public class NetworkConfiguration {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Platform.isOSX()) {
|
||||
// multicasting may not work on interfaces that only
|
||||
// have link local addresses
|
||||
if (!hasNonLinkLocalAddress(nif)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return hasIp4Addresses(nif);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
@ -157,6 +174,14 @@ public class NetworkConfiguration {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Platform.isOSX()) {
|
||||
// multicasting may not work on interfaces that only
|
||||
// have link local addresses
|
||||
if (!hasNonLinkLocalAddress(nif)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return hasIp6Addresses(nif);
|
||||
} catch (IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
|
Loading…
x
Reference in New Issue
Block a user