/* * Copyright (C) 2015 Jörg Prante * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.xbib.elasticsearch.helper.network; import java.io.IOException; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Enumeration; import java.util.List; import java.util.Locale; public abstract class NetworkUtils { public static final String IPv4_SETTING = "java.net.preferIPv4Stack"; public static final String IPv6_SETTING = "java.net.preferIPv6Addresses"; private final static InetAddress localAddress; static { InetAddress address; try { address = InetAddress.getLocalHost(); } catch (Throwable e) { address = InetAddress.getLoopbackAddress(); } localAddress = address; } private NetworkUtils() { } public static InetAddress getLocalAddress() { return localAddress; } public static InetAddress getFirstNonLoopbackAddress(ProtocolVersion ip_version) throws SocketException { InetAddress address; for (NetworkInterface networkInterface : getNetworkInterfaces()) { try { if (!networkInterface.isUp() || networkInterface.isLoopback()) { continue; } } catch (Exception e) { continue; } address = getFirstNonLoopbackAddress(networkInterface, ip_version); if (address != null) { return address; } } return null; } public static InetAddress getFirstNonLoopbackAddress(NetworkInterface networkInterface, ProtocolVersion ipVersion) throws SocketException { if (networkInterface == null) { throw new IllegalArgumentException("network interface is null"); } for (Enumeration<InetAddress> addresses = networkInterface.getInetAddresses(); addresses.hasMoreElements(); ) { InetAddress address = addresses.nextElement(); if (!address.isLoopbackAddress()) { if ((address instanceof Inet4Address && ipVersion == ProtocolVersion.IPv4) || (address instanceof Inet6Address && ipVersion == ProtocolVersion.IPv6)) { return address; } } } return null; } public static InetAddress getFirstAddress(NetworkInterface networkInterface, ProtocolVersion ipVersion) throws SocketException { if (networkInterface == null) { throw new IllegalArgumentException("network interface is null"); } for (Enumeration<InetAddress> addresses = networkInterface.getInetAddresses(); addresses.hasMoreElements(); ) { InetAddress address = addresses.nextElement(); if ((address instanceof Inet4Address && ipVersion == ProtocolVersion.IPv4) || (address instanceof Inet6Address && ipVersion == ProtocolVersion.IPv6)) { return address; } } return null; } public static List<NetworkInterface> getAllAvailableInterfaces() throws SocketException { List<NetworkInterface> allInterfaces = new ArrayList<>(); for (Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); interfaces.hasMoreElements(); ) { NetworkInterface networkInterface = interfaces.nextElement(); allInterfaces.add(networkInterface); Enumeration<NetworkInterface> subInterfaces = networkInterface.getSubInterfaces(); if (subInterfaces.hasMoreElements()) { while (subInterfaces.hasMoreElements()) { allInterfaces.add(subInterfaces.nextElement()); } } } sortInterfaces(allInterfaces); return allInterfaces; } public static List<InetAddress> getAllAvailableAddresses() throws SocketException { List<InetAddress> allAddresses = new ArrayList<>(); for (NetworkInterface networkInterface : getNetworkInterfaces()) { Enumeration<InetAddress> addrs = networkInterface.getInetAddresses(); while (addrs.hasMoreElements()) { allAddresses.add(addrs.nextElement()); } } sortAddresses(allAddresses); return allAddresses; } public static ProtocolVersion getProtocolVersion() throws SocketException { switch (findAvailableProtocols()) { case IPv4: return ProtocolVersion.IPv4; case IPv6: return ProtocolVersion.IPv6; case IPv46: if (Boolean.getBoolean(System.getProperty(IPv4_SETTING))) { return ProtocolVersion.IPv4; } if (Boolean.getBoolean(System.getProperty(IPv6_SETTING))) { return ProtocolVersion.IPv6; } return ProtocolVersion.IPv6; } return ProtocolVersion.NONE; } public static ProtocolVersion findAvailableProtocols() throws SocketException { boolean hasIPv4 = false; boolean hasIPv6 = false; for (InetAddress addr : getAllAvailableAddresses()) { if (addr instanceof Inet4Address) { hasIPv4 = true; } if (addr instanceof Inet6Address) { hasIPv6 = true; } } if (hasIPv4 && hasIPv6) { return ProtocolVersion.IPv46; } if (hasIPv4) { return ProtocolVersion.IPv4; } if (hasIPv6) { return ProtocolVersion.IPv6; } return ProtocolVersion.NONE; } public static InetAddress resolveInetAddress(String host, String defaultValue) throws IOException { if (host == null) { host = defaultValue; } String origHost = host; int pos = host.indexOf(':'); if (pos > 0) { host = host.substring(0, pos - 1); } if ((host.startsWith("#") && host.endsWith("#")) || (host.startsWith("_") && host.endsWith("_"))) { host = host.substring(1, host.length() - 1); if (host.equals("local")) { return getLocalAddress(); } else if (host.startsWith("non_loopback")) { if (host.toLowerCase(Locale.ROOT).endsWith(":ipv4")) { return getFirstNonLoopbackAddress(ProtocolVersion.IPv4); } else if (host.toLowerCase(Locale.ROOT).endsWith(":ipv6")) { return getFirstNonLoopbackAddress(ProtocolVersion.IPv6); } else { return getFirstNonLoopbackAddress(getProtocolVersion()); } } else { ProtocolVersion protocolVersion = getProtocolVersion(); if (host.toLowerCase(Locale.ROOT).endsWith(":ipv4")) { protocolVersion = ProtocolVersion.IPv4; host = host.substring(0, host.length() - 5); } else if (host.toLowerCase(Locale.ROOT).endsWith(":ipv6")) { protocolVersion = ProtocolVersion.IPv6; host = host.substring(0, host.length() - 5); } for (NetworkInterface ni : getAllAvailableInterfaces()) { if (!ni.isUp()) { continue; } if (host.equals(ni.getName()) || host.equals(ni.getDisplayName())) { if (ni.isLoopback()) { return getFirstAddress(ni, protocolVersion); } else { return getFirstNonLoopbackAddress(ni, protocolVersion); } } } } throw new IOException("failed to find network interface for [" + origHost + "]"); } return InetAddress.getByName(host); } private static List<NetworkInterface> getNetworkInterfaces() throws SocketException { List<NetworkInterface> networkInterfaces = new ArrayList<>(); Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); while (interfaces.hasMoreElements()) { NetworkInterface networkInterface = interfaces.nextElement(); networkInterfaces.add(networkInterface); Enumeration<NetworkInterface> subInterfaces = networkInterface.getSubInterfaces(); if (subInterfaces.hasMoreElements()) { while (subInterfaces.hasMoreElements()) { networkInterfaces.add(subInterfaces.nextElement()); } } } sortInterfaces(networkInterfaces); return networkInterfaces; } private static void sortInterfaces(List<NetworkInterface> interfaces) { Collections.sort(interfaces, new Comparator<NetworkInterface>() { @Override public int compare(NetworkInterface o1, NetworkInterface o2) { return Integer.compare(o1.getIndex(), o2.getIndex()); } }); } private static void sortAddresses(List<InetAddress> addressList) { Collections.sort(addressList, new Comparator<InetAddress>() { @Override public int compare(InetAddress o1, InetAddress o2) { return compareBytes(o1.getAddress(), o2.getAddress()); } }); } private static int compareBytes(byte[] left, byte[] right) { for (int i = 0, j = 0; i < left.length && j < right.length; i++, j++) { int a = (left[i] & 0xff); int b = (right[j] & 0xff); if (a != b) { return a - b; } } return left.length - right.length; } public static enum ProtocolVersion { IPv4, IPv6, IPv46, NONE } }