Allow to listen on virtual interfaces

Previously when trying to listen on virtual interfaces during
bootstrap the application would stop working - the interface
couldn't be found by the NetworkUtils class.

The NetworkUtils utilize the underlying JDK NetworkInterface
class which, when asked to lookup by name only takes physical
interfaces into account, failing at virtual (or subinterfaces)
ones (returning null).

Note that when interating over all interfaces, both physical and
virtual ones are taken into account.

This changeset asks for all known interfaces, iterates over them
and matches on the given name as part of the loop, allowing it
to catch both physical and virtual interfaces.

As a result, elasticsearch can now also serve on virtual
interfaces.

A test case has been added which at least makes sure that all
iterable interfaces can be found by their respective name. (It's
not easily possible in a unit test to "fake" virtual interfaces).

Relates #19537
This commit is contained in:
Michael Nitschinger 2016-07-22 18:33:21 +02:00 committed by Jason Tedor
parent 2b9cfff90f
commit 4cb8b620c3
2 changed files with 25 additions and 1 deletions

View File

@ -227,7 +227,14 @@ public abstract class NetworkUtils {
/** Returns addresses for the given interface (it must be marked up) */ /** Returns addresses for the given interface (it must be marked up) */
static InetAddress[] getAddressesForInterface(String name) throws SocketException { static InetAddress[] getAddressesForInterface(String name) throws SocketException {
NetworkInterface intf = NetworkInterface.getByName(name); NetworkInterface intf = null;
for (NetworkInterface networkInterface : getInterfaces()) {
if (name.equals(networkInterface.getName())) {
intf = networkInterface;
break;
}
}
if (intf == null) { if (intf == null) {
throw new IllegalArgumentException("No interface named '" + name + "' found, got " + getInterfaces()); throw new IllegalArgumentException("No interface named '" + name + "' found, got " + getInterfaces());
} }

View File

@ -22,6 +22,10 @@ package org.elasticsearch.common.network;
import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.ESTestCase;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
/** /**
* Tests for network utils. Please avoid using any methods that cause DNS lookups! * Tests for network utils. Please avoid using any methods that cause DNS lookups!
@ -74,4 +78,17 @@ public class NetworkUtilsTests extends ESTestCase {
assertArrayEquals(new InetAddress[] { InetAddress.getByName("127.0.0.1") }, NetworkUtils.filterIPV4(addresses)); assertArrayEquals(new InetAddress[] { InetAddress.getByName("127.0.0.1") }, NetworkUtils.filterIPV4(addresses));
assertArrayEquals(new InetAddress[] { InetAddress.getByName("::1") }, NetworkUtils.filterIPV6(addresses)); assertArrayEquals(new InetAddress[] { InetAddress.getByName("::1") }, NetworkUtils.filterIPV6(addresses));
} }
/**
* Test that selecting by name is possible and properly matches the addresses on all interfaces and virtual
* interfaces.
*/
public void testAddressInterfaceLookup() throws Exception {
for (NetworkInterface netIf : NetworkUtils.getInterfaces()) {
String name = netIf.getName();
InetAddress[] expectedAddresses = Collections.list(netIf.getInetAddresses()).toArray(new InetAddress[0]);
InetAddress[] foundAddresses = NetworkUtils.getAddressesForInterface(name);
assertArrayEquals(expectedAddresses, foundAddresses);
}
}
} }