diff --git a/addons/binding/org.openhab.binding.network/META-INF/MANIFEST.MF b/addons/binding/org.openhab.binding.network/META-INF/MANIFEST.MF index cf59b41d2639f..3f446c61b8759 100644 --- a/addons/binding/org.openhab.binding.network/META-INF/MANIFEST.MF +++ b/addons/binding/org.openhab.binding.network/META-INF/MANIFEST.MF @@ -16,6 +16,7 @@ Import-Package: org.eclipse.smarthome.config.discovery, org.eclipse.smarthome.core.cache, org.eclipse.smarthome.core.library.types, + org.eclipse.smarthome.core.net, org.eclipse.smarthome.core.thing, org.eclipse.smarthome.core.thing.binding, org.eclipse.smarthome.core.types, diff --git a/addons/binding/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/utils/NetworkUtils.java b/addons/binding/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/utils/NetworkUtils.java index 152b8db9d58ef..6028b1910d1ab 100644 --- a/addons/binding/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/utils/NetworkUtils.java +++ b/addons/binding/org.openhab.binding.network/src/main/java/org/openhab/binding/network/internal/utils/NetworkUtils.java @@ -18,9 +18,9 @@ import java.net.ConnectException; import java.net.DatagramPacket; import java.net.DatagramSocket; +import java.net.Inet4Address; import java.net.InetAddress; import java.net.InetSocketAddress; -import java.net.InterfaceAddress; import java.net.NetworkInterface; import java.net.NoRouteToHostException; import java.net.PortUnreachableException; @@ -30,16 +30,20 @@ import java.net.SocketTimeoutException; import java.util.Enumeration; import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; +import java.util.stream.Collectors; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.SystemUtils; import org.apache.commons.net.util.SubnetUtils; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.smarthome.core.net.CidrAddress; +import org.eclipse.smarthome.core.net.NetUtil; import org.eclipse.smarthome.io.net.exec.ExecUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Network utility functions for pinging and for determining all interfaces and assigned IP addresses. @@ -48,45 +52,17 @@ */ @NonNullByDefault public class NetworkUtils { + private final Logger logger = LoggerFactory.getLogger(NetworkUtils.class); + /** * Gets every IPv4 Address on each Interface except the loopback * The Address format is ip/subnet * * @return The collected IPv4 Addresses */ - public Set getInterfaceIPs() { - Set interfaceIPs = new HashSet<>(); - - Enumeration interfaces; - try { - interfaces = NetworkInterface.getNetworkInterfaces(); - } catch (SocketException ignored) { - // If we are not allowed to enumerate, we return an empty result set. - return interfaceIPs; - } - - // For each interface ... - for (Enumeration en = interfaces; en.hasMoreElements();) { - NetworkInterface networkInterface = en.nextElement(); - boolean isLoopback = true; - try { - isLoopback = networkInterface.isLoopback(); - } catch (SocketException ignored) { - } - if (!isLoopback) { - // .. and for each address ... - for (Iterator it = networkInterface.getInterfaceAddresses().iterator(); it - .hasNext();) { - - // ... get IP and Subnet - InterfaceAddress interfaceAddress = it.next(); - interfaceIPs.add(interfaceAddress.getAddress().getHostAddress() + "/" - + interfaceAddress.getNetworkPrefixLength()); - } - } - } - - return interfaceIPs; + public Set getInterfaceIPs() { + return NetUtil.getAllInterfaceAddresses().stream().filter(a -> a.getAddress() instanceof Inet4Address) + .collect(Collectors.toSet()); } /** @@ -129,22 +105,38 @@ public Set getNetworkIPs(int maximumPerInterface) { * @param maximumPerInterface The maximum of IP addresses per interface or 0 to get all. * @return Every single IP which can be assigned on the Networks the computer is connected to */ - public Set getNetworkIPs(Set interfaceIPs, int maximumPerInterface) { + public Set getNetworkIPs(Set interfaceIPs, int maximumPerInterface) { LinkedHashSet networkIPs = new LinkedHashSet<>(); - for (String string : interfaceIPs) { - try { - // gets every ip which can be assigned on the given network - SubnetUtils utils = new SubnetUtils(string); - String[] addresses = utils.getInfo().getAllAddresses(); - int len = addresses.length; - if (maximumPerInterface != 0 && maximumPerInterface < len) { - len = maximumPerInterface; - } - for (int i = 0; i < len; i++) { - networkIPs.add(addresses[i]); - } - } catch (Exception ex) { + short minCidrPrefixLength = 8; // historic Class A network, addresses = 16777214 + if (maximumPerInterface != 0) { + // calculate minimum CIDR prefix length from maximumPerInterface + // (equals leading unset bits (Integer has 32 bits) + minCidrPrefixLength = (short) Integer.numberOfLeadingZeros(maximumPerInterface); + if (Integer.bitCount(maximumPerInterface) == 1) { + // if only the highest is set, decrease prefix by 1 to cover all addresses + minCidrPrefixLength--; + } + } + logger.trace("set minCidrPrefixLength to {}, maximumPerInterface is {}", minCidrPrefixLength, + maximumPerInterface); + + for (CidrAddress cidrNotation : interfaceIPs) { + if (cidrNotation.getPrefix() < minCidrPrefixLength) { + logger.info( + "CIDR prefix is smaller than /{} on interface with address {}, truncating to /{}, some addresses might be lost", + minCidrPrefixLength, cidrNotation, minCidrPrefixLength); + cidrNotation = new CidrAddress(cidrNotation.getAddress(), minCidrPrefixLength); + } + + SubnetUtils utils = new SubnetUtils(cidrNotation.toString()); + String[] addresses = utils.getInfo().getAllAddresses(); + int len = addresses.length; + if (maximumPerInterface != 0 && maximumPerInterface < len) { + len = maximumPerInterface; + } + for (int i = 0; i < len; i++) { + networkIPs.add(addresses[i]); } }