/*
* Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.groupbasedpolicy.util;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.apache.commons.net.util.SubnetUtils;
import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
import com.google.common.base.Strings;
import com.google.common.net.InetAddresses;
import com.googlecode.ipv6.IPv6NetworkMask;
public final class NetUtils {
/**
* Extract prefix length from prefix form
* Works for both IPv4 and IPv6
*
* @param prefix {@code String} to extract prefix length from
* @return prefix length as {@code int}
*/
public static int getMaskFromPrefix(@Nullable String prefix) {
String newPrefix = Strings.nullToEmpty(prefix);
int slashIndex = newPrefix.indexOf("/");
if (slashIndex == -1) {
slashIndex = newPrefix.length() - 1;
}
return Integer.parseInt(newPrefix.substring(slashIndex + 1));
}
/**
* Extract IP adress from prefix form
* Works for both IPv4 and IPv6
*
* @param prefix {@code String} to extract IP address from
* @return IP address as a {@code String}
*/
public static @Nonnull String getIpAddrFromPrefix(@Nullable String prefix) {
String newPrefix = Strings.nullToEmpty(prefix);
int slashIndex = newPrefix.indexOf("/");
if (slashIndex == -1) {
slashIndex = newPrefix.length();
}
return newPrefix.substring(0, slashIndex);
}
/**
* Mask IPv6 address from prefix with provided prefix length
*
* @param ipv6Prefix {@link Ipv6Prefix} to apply mask on
* @param ipv6MaskLength prefix length
* @return resulting network IP address as {@link Ipv6Address}
*/
public static @Nullable Ipv6Address applyMaskOnIpv6Prefix(@Nullable Ipv6Prefix ipv6Prefix, int ipv6MaskLength) {
if (ipv6Prefix == null) {
return null;
}
return applyMaskOnIpv6Address(new Ipv6Address(getIpAddrFromPrefix(ipv6Prefix.getValue())), ipv6MaskLength);
}
/**
* Mask IPv6 address with provided prefix length
*
* @param ipv6Address {@link Ipv6Prefix} to apply mask on
* @param ipv6MaskLength prefix length
* @return resulting network address as {@link Ipv6Address}, {@code null} if provided address is null
*/
public static @Nullable Ipv6Address applyMaskOnIpv6Address(@Nullable Ipv6Address ipv6Address, int ipv6MaskLength) {
if (ipv6Address == null) {
return null;
}
com.googlecode.ipv6.IPv6Address ip = com.googlecode.ipv6.IPv6Address.fromString(ipv6Address.getValue());
IPv6NetworkMask mask = IPv6NetworkMask.fromPrefixLength(ipv6MaskLength);
ip = ip.maskWithNetworkMask(mask);
return new Ipv6Address(ip.toString());
}
/**
* Check if two IpPrefixes represents same network. Must be identical in network address and prefix length.
* Works for both IPv4 and IPv6
*
* @param prefix1 {@link IpPrefix} to compare
* @param prefix2 {@link IpPrefix} to compare
* @return {@code true} if provided prefixes are identical, otherwise return {@code false}
*/
public static boolean samePrefix(@Nullable IpPrefix prefix1, @Nullable IpPrefix prefix2) {
if (prefix1 == null || prefix2 == null) {
return false;
}
if (prefix1.getIpv4Prefix() != null && prefix2.getIpv4Prefix() != null) {
SubnetUtils fromPrefix1 = new SubnetUtils(prefix1.getIpv4Prefix().getValue());
SubnetUtils fromPrefix2 = new SubnetUtils(prefix2.getIpv4Prefix().getValue());
if (fromPrefix1.getInfo().getNetworkAddress().equals(fromPrefix2.getInfo().getNetworkAddress())
&& fromPrefix1.getInfo().getNetmask().equals(fromPrefix2.getInfo().getNetmask())) {
return true;
}
} else if (prefix1.getIpv6Prefix() != null && prefix2.getIpv6Prefix() != null) {
int ipv6MaskLength1 = getMaskFromPrefix(prefix1.getIpv6Prefix().getValue());
int ipv6MaskLength2 = getMaskFromPrefix(prefix2.getIpv6Prefix().getValue());
if (ipv6MaskLength1 != ipv6MaskLength2) {
return false;
}
Ipv6Address ipv6Network = applyMaskOnIpv6Prefix(prefix1.getIpv6Prefix(), ipv6MaskLength1);
Ipv6Address hostv6Network = applyMaskOnIpv6Prefix(prefix2.getIpv6Prefix(), ipv6MaskLength1);
if (ipv6Network.getValue().equals(hostv6Network.getValue())) {
return true;
}
}
return false;
}
/**
* @param prefix subnet prefix
* @param ipAddress ip address
* @return true if the parameter address is in the range of usable endpoint
* addresses for a given subnet. This excludes the network and broadcast adresses.
*/
public static boolean isInRange(@Nullable IpPrefix prefix, @Nullable String ipAddress) {
if (ipAddress != null && !ipAddress.isEmpty()) {
try {
InetAddress inetAddr = InetAddress.getByName(ipAddress);
if (prefix.getIpv4Prefix() != null && inetAddr instanceof Inet4Address) {
SubnetUtils ipv4Subnet = new SubnetUtils(prefix.getIpv4Prefix().getValue());
return ipv4Subnet.getInfo().isInRange(ipAddress);
}
if (prefix.getIpv6Prefix() != null && inetAddr instanceof Inet6Address) {
SubnetUtils ipv6Subnet = new SubnetUtils(prefix.getIpv6Prefix().getValue());
return ipv6Subnet.getInfo().isInRange(ipAddress);
}
} catch (UnknownHostException e) {
e.printStackTrace();
}
}
return false;
}
}