/** * Copyright (c) 2015 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.openflowplugin.applications.statistics.manager.impl.helper; import com.google.common.annotations.VisibleForTesting; import com.google.common.net.InetAddresses; import com.google.common.primitives.UnsignedBytes; import java.math.BigInteger; import java.net.Inet4Address; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Arrays; 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.Ipv4Prefix; 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 org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.MacAddressFilter; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddress; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchArbitraryBitMask; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match; import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6MatchArbitraryBitMask; import org.opendaylight.yang.gen.v1.urn.opendaylight.opendaylight.ipv6.arbitrary.bitmask.fields.rev160224.Ipv6ArbitraryMask; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author joe * @author sai.marapareddy@gmail.com * */ public class MatchComparatorHelper { private static final Logger LOG = LoggerFactory.getLogger(MatchComparatorHelper.class); private static final int DEFAULT_SUBNET = 32; private static final int IPV4_MASK_LENGTH = 32; private static final int SHIFT_OCTET_1 = 24; private static final int SHIFT_OCTET_2 = 16; private static final int SHIFT_OCTET_3 = 8; private static final int SHIFT_OCTET_4 = 0; private static final int POSITION_OCTET_1 = 0; private static final int POSITION_OCTET_2 = 1; private static final int POSITION_OCTET_3 = 2; private static final int POSITION_OCTET_4 = 3; private static final String DEFAULT_ARBITRARY_BIT_MASK = "255.255.255.255"; private static final String DEFAULT_IPV6_ARBITRARY_BIT_MASK = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; private static final String PREFIX_SEPARATOR = "/"; private static final int IPV4_ADDRESS_LENGTH = 32; private static final int IPV6_ADDRESS_LENGTH = 128; private static final int BYTE_SIZE = 8; /* * Custom EthernetMatch is required because mac address string provided by user in EthernetMatch can be in any case * (upper or lower or mix). Ethernet Match which controller receives from switch is always an upper case string. * Default EthernetMatch equals doesn't use equalsIgnoreCase() and hence it fails. E.g User provided mac address * string in flow match is aa:bb:cc:dd:ee:ff and when controller fetch statistic data, openflow driver library * returns AA:BB:CC:DD:EE:FF and default eqauls fails here. */ @VisibleForTesting static boolean ethernetMatchEquals(final EthernetMatch statsEthernetMatch, final EthernetMatch storedEthernetMatch) { boolean verdict = true; final Boolean checkNullValues = checkNullValues(statsEthernetMatch, storedEthernetMatch); if (checkNullValues != null) { verdict = checkNullValues; } else { verdict = ethernetMatchFieldsEquals(statsEthernetMatch.getEthernetSource(), storedEthernetMatch.getEthernetSource()); if (verdict) { verdict = ethernetMatchFieldsEquals(statsEthernetMatch.getEthernetDestination(), storedEthernetMatch.getEthernetDestination()); } if (verdict) { if (statsEthernetMatch.getEthernetType() == null) { if (storedEthernetMatch.getEthernetType() != null) { verdict = false; } } else { verdict = statsEthernetMatch.getEthernetType().equals(storedEthernetMatch.getEthernetType()); } } } return verdict; } static boolean ethernetMatchFieldsEquals(final MacAddressFilter statsEthernetMatchFields, final MacAddressFilter storedEthernetMatchFields) { boolean verdict = true; final Boolean checkNullValues = checkNullValues(statsEthernetMatchFields, storedEthernetMatchFields); if (checkNullValues != null) { verdict = checkNullValues; } else { verdict = macAddressEquals(statsEthernetMatchFields.getAddress(), storedEthernetMatchFields.getAddress()); if (verdict) { verdict = macAddressEquals(statsEthernetMatchFields.getMask(), storedEthernetMatchFields.getMask()); } } return verdict; } static boolean macAddressEquals(final MacAddress statsMacAddress, final MacAddress storedMacAddress) { boolean verdict = true; final Boolean checkNullValues = checkNullValues(statsMacAddress, storedMacAddress); if (checkNullValues != null) { verdict = checkNullValues; } else { verdict = statsMacAddress.getValue().equalsIgnoreCase(storedMacAddress.getValue()); } return verdict; } @VisibleForTesting static boolean layer3MatchEquals(final Layer3Match statsLayer3Match, final Layer3Match storedLayer3Match) { boolean verdict = true; if (statsLayer3Match instanceof Ipv4Match && storedLayer3Match instanceof Ipv4Match) { final Ipv4Match statsIpv4Match = (Ipv4Match) statsLayer3Match; final Ipv4Match storedIpv4Match = (Ipv4Match) storedLayer3Match; verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(storedIpv4Match.getIpv4Destination(), statsIpv4Match.getIpv4Destination()); if (verdict) { verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(statsIpv4Match.getIpv4Source(), storedIpv4Match.getIpv4Source()); } } else if (statsLayer3Match instanceof Ipv6Match && storedLayer3Match instanceof Ipv6Match) { final Ipv6Match statsIpv6Match = (Ipv6Match) statsLayer3Match; final Ipv6Match storedIpv6Match = (Ipv6Match) storedLayer3Match; verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(storedIpv6Match.getIpv6Destination(), statsIpv6Match.getIpv6Destination()); if (verdict) { verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(statsIpv6Match.getIpv6Source(), storedIpv6Match.getIpv6Source()); } } else if (statsLayer3Match instanceof Ipv4MatchArbitraryBitMask && storedLayer3Match instanceof Ipv4MatchArbitraryBitMask) { // At this moment storedIpv4MatchArbitraryBitMask & statsIpv4MatchArbitraryBitMask will always have non null arbitrary masks. // In case of no / null arbitrary mask, statsLayer3Match will be an instance of Ipv4Match. // Eg:- stats -> 1.0.1.0/255.0.255.0 stored -> 1.1.1.0/255.0.255.0 final Ipv4MatchArbitraryBitMask statsIpv4MatchArbitraryBitMask= (Ipv4MatchArbitraryBitMask) statsLayer3Match; final Ipv4MatchArbitraryBitMask storedIpv4MatchArbitraryBitMask = (Ipv4MatchArbitraryBitMask) storedLayer3Match; if ((storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask() != null | storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() != null)) { if (storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask() != null) { String storedDstIpAddress = normalizeIpv4Address(storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask(), storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask()); String statsDstIpAddress = normalizeIpv4Address(statsIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask(), statsIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask()); if (MatchComparatorHelper.compareStringNullSafe(storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask().getValue(), statsIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask().getValue())) { verdict = MatchComparatorHelper.compareStringNullSafe(storedDstIpAddress, statsDstIpAddress); } else { verdict = false; return verdict; } } if (storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() != null) { String storedSrcIpAddress = normalizeIpv4Address(storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() ,storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask()); String statsSrcIpAddress = normalizeIpv4Address(statsIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() ,statsIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask()); if (MatchComparatorHelper.compareStringNullSafe(storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask().getValue(), statsIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask().getValue())) { verdict = MatchComparatorHelper.compareStringNullSafe(storedSrcIpAddress, statsSrcIpAddress); } else { verdict = false; } } } else { final Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match); if (nullCheckOut != null) { verdict = nullCheckOut; } else { verdict = storedLayer3Match.equals(statsLayer3Match); } } } else if (statsLayer3Match instanceof Ipv4Match && storedLayer3Match instanceof Ipv4MatchArbitraryBitMask) { // Here stored netmask is an instance of Ipv4MatchArbitraryBitMask, when it is pushed in to switch // it automatically converts it in to cidr format in case of certain subnet masks ( consecutive ones or zeroes) // Eg:- stats src/dest -> 1.1.1.0/24 stored src/dest -> 1.1.1.0/255.255.255.0 final Ipv4Match statsIpv4Match = (Ipv4Match) statsLayer3Match; final Ipv4MatchArbitraryBitMask storedIpv4MatchArbitraryBitMask = (Ipv4MatchArbitraryBitMask) storedLayer3Match; if (storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask() != null) { Ipv4Prefix ipv4PrefixDestination; if (storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask() != null) { byte[] destByteMask = convertArbitraryMaskToByteArray(storedIpv4MatchArbitraryBitMask.getIpv4DestinationArbitraryBitmask()); ipv4PrefixDestination = createPrefix(storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask(), destByteMask); } else { ipv4PrefixDestination = createPrefix(storedIpv4MatchArbitraryBitMask.getIpv4DestinationAddressNoMask()); } verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixDestination, statsIpv4Match.getIpv4Destination()); if (verdict == false) { return verdict; } } if (storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask() != null) { Ipv4Prefix ipv4PrefixSource; if (storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask() != null) { byte[] srcByteMask = convertArbitraryMaskToByteArray(storedIpv4MatchArbitraryBitMask.getIpv4SourceArbitraryBitmask()); ipv4PrefixSource = createPrefix(storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask(), srcByteMask); } else { ipv4PrefixSource = createPrefix(storedIpv4MatchArbitraryBitMask.getIpv4SourceAddressNoMask()); } verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixSource, statsIpv4Match.getIpv4Source()); } } else if (statsLayer3Match instanceof Ipv6MatchArbitraryBitMask && storedLayer3Match instanceof Ipv6MatchArbitraryBitMask) { // At this moment storedIpv6MatchArbitraryBitMask & statsIpv6MatchArbitraryBitMask will always have non null arbitrary masks. // In case of no / null arbitrary mask, statsLayer3Match will be an instance of Ipv6Match. // Eg:- stats src/dest -> 2001:2001:2001:2001:2001:2001:2001:2001/FFFF:FFFF:FFFF:FFFF:0000:FFFF:FFFF:FFF0 // stored src/dest -> 2001:2001:2001:2001:2001:2001:2001:2001/FFFF:FFFF:FFFF:FFFF:0000:FFFF:FFFF:FFF0 final Ipv6MatchArbitraryBitMask statsIpv6MatchArbitraryBitMask= (Ipv6MatchArbitraryBitMask) statsLayer3Match; final Ipv6MatchArbitraryBitMask storedIpv6MatchArbitraryBitMask = (Ipv6MatchArbitraryBitMask) storedLayer3Match; if ((storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask() != null | storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask() != null)) { if (storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask() != null) { String storedDstIpAddress = normalizeIpv6Address(storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask(), storedIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask()); String statsDstIpAddress = normalizeIpv6Address(statsIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask(), statsIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask()); String storedDstMask = extractIpv6CanonicalForm(storedIpv6MatchArbitraryBitMask. getIpv6DestinationArbitraryBitmask().getValue()).getHostAddress(); String statsDstMask = extractIpv6CanonicalForm(statsIpv6MatchArbitraryBitMask. getIpv6DestinationArbitraryBitmask().getValue()).getHostAddress(); if (MatchComparatorHelper.compareStringNullSafe(storedDstMask,statsDstMask)) { verdict = MatchComparatorHelper.compareStringNullSafe(storedDstIpAddress, statsDstIpAddress); } else { verdict = false; return verdict; } } if (storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask() != null) { String storedSrcIpAddress = normalizeIpv6Address(storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask() ,storedIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask()); String statsSrcIpAddress = normalizeIpv6Address(statsIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask() ,statsIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask()); String storedSrcMask = extractIpv6CanonicalForm(storedIpv6MatchArbitraryBitMask. getIpv6SourceArbitraryBitmask().getValue()).getHostAddress(); String statsSrcMask = extractIpv6CanonicalForm(statsIpv6MatchArbitraryBitMask. getIpv6SourceArbitraryBitmask().getValue()).getHostAddress(); if (MatchComparatorHelper.compareStringNullSafe(storedSrcMask, statsSrcMask)) { verdict = MatchComparatorHelper.compareStringNullSafe(storedSrcIpAddress, statsSrcIpAddress); } else { verdict = false; } } } else { final Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match); if (nullCheckOut != null) { verdict = nullCheckOut; } else { verdict = storedLayer3Match.equals(statsLayer3Match); } } } else if (statsLayer3Match instanceof Ipv6Match && storedLayer3Match instanceof Ipv6MatchArbitraryBitMask) { // Here stored netmask is an instance of Ipv6MatchArbitraryBitMask, when it is pushed in to switch // it automatically converts it in to cidr format in case of certain subnet masks ( consecutive ones or zeroes) // Eg:- stats src/dest -> 2001:2001:2001:2001:2001:2001:2001:2001/124 // stored src/dest -> 2001:2001:2001:2001:2001:2001:2001:2001/FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFF0 final Ipv6Match statsIpv6Match = (Ipv6Match) statsLayer3Match; final Ipv6MatchArbitraryBitMask storedIpv6MatchArbitraryBitMask = (Ipv6MatchArbitraryBitMask) storedLayer3Match; if (storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask() != null) { Ipv6Prefix ipv6PrefixDestination; if (storedIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask() != null) { byte[] destByteMask = convertIpv6ArbitraryMaskToByteArray(storedIpv6MatchArbitraryBitMask.getIpv6DestinationArbitraryBitmask()); ipv6PrefixDestination = createPrefix(storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask(), destByteMask); } else { ipv6PrefixDestination = createPrefix(storedIpv6MatchArbitraryBitMask.getIpv6DestinationAddressNoMask()); } verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(ipv6PrefixDestination, statsIpv6Match.getIpv6Destination()); if (verdict == false) { return verdict; } } if (storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask() != null) { Ipv6Prefix ipv6PrefixSource; if (storedIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask() != null) { byte[] srcByteMask = convertIpv6ArbitraryMaskToByteArray(storedIpv6MatchArbitraryBitMask.getIpv6SourceArbitraryBitmask()); ipv6PrefixSource = createPrefix(storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask(), srcByteMask); } else { ipv6PrefixSource = createPrefix(storedIpv6MatchArbitraryBitMask.getIpv6SourceAddressNoMask()); } verdict = MatchComparatorHelper.compareIpv6PrefixNullSafe(ipv6PrefixSource, statsIpv6Match.getIpv6Source()); } } else if (statsLayer3Match instanceof ArpMatch && storedLayer3Match instanceof ArpMatch) { verdict = arpMatchEquals((ArpMatch)statsLayer3Match, (ArpMatch)storedLayer3Match); } else { final Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match); if (nullCheckOut != null) { verdict = nullCheckOut; } else { verdict = storedLayer3Match.equals(statsLayer3Match); } } return verdict; } static boolean arpMatchEquals(final ArpMatch statsArpMatch, final ArpMatch storedArpMatch) { Integer statsOp = statsArpMatch.getArpOp(); Integer storedOp = storedArpMatch.getArpOp(); Boolean nullCheck = checkNullValues(statsOp, storedOp); if (nullCheck != null) { if (nullCheck == false) { return false; } } else if (!statsOp.equals(storedOp)) { return false; } Ipv4Prefix statsIp = statsArpMatch.getArpSourceTransportAddress(); Ipv4Prefix storedIp = storedArpMatch.getArpSourceTransportAddress(); if (!compareIpv4PrefixNullSafe(statsIp, storedIp)) { return false; } statsIp = statsArpMatch.getArpTargetTransportAddress(); storedIp = storedArpMatch.getArpTargetTransportAddress(); if (!compareIpv4PrefixNullSafe(statsIp, storedIp)) { return false; } MacAddressFilter statsMac = statsArpMatch.getArpSourceHardwareAddress(); MacAddressFilter storedMac = storedArpMatch.getArpSourceHardwareAddress(); if (!ethernetMatchFieldsEquals(statsMac, storedMac)) { return false; } statsMac = statsArpMatch.getArpTargetHardwareAddress(); storedMac = storedArpMatch.getArpTargetHardwareAddress(); if (!ethernetMatchFieldsEquals(statsMac, storedMac)) { return false; } return true; } /** * TODO: why don't we use the default Ipv4Prefix.equals()? * * @param statsIpAddress * @param storedIpAddress * @return true if IPv4prefixes equals */ static boolean IpAddressEquals(final Ipv4Prefix statsIpAddress, final Ipv4Prefix storedIpAddress) { final IntegerIpAddress statsIpAddressInt = MatchComparatorHelper.strIpToIntIp(statsIpAddress.getValue()); final IntegerIpAddress storedIpAddressInt = MatchComparatorHelper.strIpToIntIp(storedIpAddress.getValue()); if (ipAndMaskBasedMatch(statsIpAddressInt, storedIpAddressInt)) { return true; } if (ipBasedMatch(statsIpAddressInt, storedIpAddressInt)) { return true; } return false; } static boolean ipAndMaskBasedMatch(final IntegerIpAddress statsIpAddressInt, final IntegerIpAddress storedIpAddressInt) { return ((statsIpAddressInt.getIp() & statsIpAddressInt.getMask()) == (storedIpAddressInt.getIp() & storedIpAddressInt .getMask())); } static boolean ipBasedMatch(final IntegerIpAddress statsIpAddressInt, final IntegerIpAddress storedIpAddressInt) { return (statsIpAddressInt.getIp() == storedIpAddressInt.getIp()); } private static boolean IpAddressEquals(Ipv6Prefix statsIpv6, Ipv6Prefix storedIpv6) { final String[] statsIpMask = statsIpv6.getValue().split("/"); final String[] storedIpMask = storedIpv6.getValue().split("/"); if (! (statsIpMask.length > 1 && storedIpMask.length > 1 && statsIpMask[1].equals(storedIpMask[1]))){ return false; } final int prefix = Integer.parseInt(statsIpMask[1]); final int byteIndex = prefix/BYTE_SIZE; final int lastByteBits = BYTE_SIZE - (prefix % BYTE_SIZE); final InetAddress statsIp = InetAddresses.forString(statsIpMask[0]); final InetAddress storedIp = InetAddresses.forString(storedIpMask[0]); byte[] statsIpArr = Arrays.copyOfRange(statsIp.getAddress(),0,byteIndex+1); byte[] storedIpArr = Arrays.copyOfRange(storedIp.getAddress(),0,byteIndex+1); statsIpArr[byteIndex] = (byte) (statsIpArr[byteIndex] & (0XFF << lastByteBits)); storedIpArr[byteIndex] = (byte) (storedIpArr[byteIndex] & (0XFF << lastByteBits)); if(Arrays.equals(statsIpArr,storedIpArr)) { return true; } return false; } static Boolean checkNullValues(final Object v1, final Object v2) { Boolean verdict = null; if (v1 == null && v2 != null) { verdict = Boolean.FALSE; } else if (v1 != null && v2 == null) { verdict = Boolean.FALSE; } else if (v1 == null && v2 == null) { verdict = Boolean.TRUE; } return verdict; } static boolean compareIpv4PrefixNullSafe(final Ipv4Prefix statsIpv4, final Ipv4Prefix storedIpv4) { boolean verdict = true; final Boolean checkDestNullValuesOut = checkNullValues(storedIpv4, statsIpv4); if (checkDestNullValuesOut != null) { verdict = checkDestNullValuesOut; } else if (!IpAddressEquals(statsIpv4, storedIpv4)) { verdict = false; } return verdict; } static boolean compareStringNullSafe(final String stringA, final String stringB) { boolean verdict = true; final Boolean checkDestNullValuesOut = checkNullValues(stringA,stringB); if (checkDestNullValuesOut != null) { verdict = checkDestNullValuesOut; } else if (!stringA.equals(stringB)) { verdict = false; } return verdict; } private static boolean compareIpv6PrefixNullSafe(Ipv6Prefix statsIpv6, Ipv6Prefix storedIpv6) { boolean verdict = true; final Boolean checkDestNullValuesOut = checkNullValues(statsIpv6, storedIpv6); if (checkDestNullValuesOut != null) { verdict = checkDestNullValuesOut; } else if (!IpAddressEquals(statsIpv6, storedIpv6)) { verdict = false; } return verdict; } /** * Method return integer version of ip address. Converted int will be mask if mask specified */ static IntegerIpAddress strIpToIntIp(final String ipAddresss) { final String[] parts = ipAddresss.split("/"); final String ip = parts[0]; int prefix; if (parts.length < 2) { prefix = DEFAULT_SUBNET; } else { prefix = Integer.parseInt(parts[1]); if (prefix < 0 || prefix > IPV4_MASK_LENGTH) { final StringBuilder stringBuilder = new StringBuilder( "Valid values for mask are from range 0 - 32. Value "); stringBuilder.append(prefix); stringBuilder.append(" is invalid."); throw new IllegalStateException(stringBuilder.toString()); } } IntegerIpAddress integerIpAddress = null; final Inet4Address addr = ((Inet4Address) InetAddresses.forString(ip)); final byte[] addrBytes = addr.getAddress(); // FIXME: what is meaning of anding with 0xFF? Probably could be removed. final int ipInt = ((addrBytes[POSITION_OCTET_1] & 0xFF) << SHIFT_OCTET_1) | ((addrBytes[POSITION_OCTET_2] & 0xFF) << SHIFT_OCTET_2) | ((addrBytes[POSITION_OCTET_3] & 0xFF) << SHIFT_OCTET_3) | ((addrBytes[POSITION_OCTET_4] & 0xFF) << SHIFT_OCTET_4); // FIXME: Is this valid? final int mask = 0xffffffff << DEFAULT_SUBNET - prefix; integerIpAddress = new IntegerIpAddress(ipInt, mask); return integerIpAddress; } static boolean isArbitraryBitMask(byte[] byteMask) { if (byteMask == null) { return false; } else { ArrayList<Integer> integerMaskArrayList = new ArrayList<Integer>(); String maskInBits; // converting byte array to bits maskInBits = new BigInteger(1, byteMask).toString(2); ArrayList<String> stringMaskArrayList = new ArrayList<String>(Arrays.asList(maskInBits.split("(?!^)"))); for(String string:stringMaskArrayList){ integerMaskArrayList.add(Integer.parseInt(string)); } return checkArbitraryBitMask(integerMaskArrayList); } } static boolean checkArbitraryBitMask(ArrayList<Integer> arrayList) { if (arrayList.size()>0 && arrayList.size()< IPV4_MASK_LENGTH ) { // checks 0*1* case - Leading zeros in arrayList are truncated return true; } else { //checks 1*0*1 case for(int i=0; i<arrayList.size()-1;i++) { if(arrayList.get(i) ==0 && arrayList.get(i+1) == 1) { return true; } } } return false; } static final byte[] convertArbitraryMaskToByteArray(DottedQuad mask) { String maskValue; if (mask.getValue() != null) { maskValue = mask.getValue(); } else { maskValue = DEFAULT_ARBITRARY_BIT_MASK; } InetAddress maskInIpFormat = null; try { maskInIpFormat = InetAddress.getByName(maskValue); } catch (UnknownHostException e) { LOG.error("Failed to recognize the host while converting mask ", e); } byte[] bytes = maskInIpFormat.getAddress(); return bytes; } private static final byte[] convertIpv6ArbitraryMaskToByteArray ( final Ipv6ArbitraryMask mask) { String maskValue; if (mask.getValue() != null) { maskValue = mask.getValue(); } else { maskValue = DEFAULT_IPV6_ARBITRARY_BIT_MASK; } InetAddress maskInIpv6Format = null; try { maskInIpv6Format = InetAddress.getByName(maskValue); } catch (UnknownHostException e) { LOG.error("Failed to convert string mask value to ipv6 format ", e); } return maskInIpv6Format.getAddress(); } static String normalizeIpv4Address(Ipv4Address ipAddress, DottedQuad netMask) { String actualIpAddress=""; String[] netMaskParts = netMask.getValue().split("\\."); String[] ipAddressParts = ipAddress.getValue().split("\\."); for (int i=0; i<ipAddressParts.length;i++) { int integerFormatIpAddress=Integer.parseInt(ipAddressParts[i]); int integerFormatNetMask=Integer.parseInt(netMaskParts[i]); int ipAddressPart=(integerFormatIpAddress) & (integerFormatNetMask); actualIpAddress += ipAddressPart; if (i != ipAddressParts.length -1 ) { actualIpAddress = actualIpAddress+"."; } } return actualIpAddress; } private static String normalizeIpv6Address(final Ipv6Address ipAddress, final Ipv6ArbitraryMask netMask) { byte[] ipAddressParts = convertIpv6ToBytes(ipAddress.getValue()); byte[] netMaskParts = convertIpv6ToBytes(netMask.getValue()); byte[] actualIpv6Bytes = new byte[16]; for (int i=0; i<ipAddressParts.length;i++) { byte ipAddressPart= (byte) (ipAddressParts[i] & netMaskParts[i]); actualIpv6Bytes[i] = ipAddressPart; } InetAddress ipv6Address = null; try { ipv6Address = InetAddress.getByAddress(actualIpv6Bytes); } catch (UnknownHostException e) { LOG.error("Failed to recognize the host while normalizing IPv6 address from bytes ", e); } return ipv6Address.getHostAddress(); } private static byte[] convertIpv6ToBytes(final String ipv6Address) { return extractIpv6CanonicalForm(ipv6Address).getAddress(); } private static InetAddress extractIpv6CanonicalForm(final String ipv6Address) { InetAddress address = null; try { address = InetAddress.getByName(ipv6Address); } catch (UnknownHostException e) { LOG.error("Failed to recognize the host while converting IPv6 to bytes ", e); } return address; } static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address, final byte [] bytemask){ return createPrefix(ipv4Address, String.valueOf(countBits(bytemask))); } private static Ipv6Prefix createPrefix(final Ipv6Address ipv6Address, final byte [] bytemask) { return createPrefix(ipv6Address, String.valueOf(countBits(bytemask))); } private static Ipv6Prefix createPrefix(final Ipv6Address ipv6Address, final String mask) { if (mask != null && !mask.isEmpty()) { return new Ipv6Prefix(ipv6Address.getValue() + PREFIX_SEPARATOR + mask); } else { return new Ipv6Prefix(ipv6Address.getValue() + PREFIX_SEPARATOR + IPV6_ADDRESS_LENGTH); } } private static Ipv6Prefix createPrefix(final Ipv6Address ipv6Address) { return new Ipv6Prefix(ipv6Address.getValue() + PREFIX_SEPARATOR + IPV6_ADDRESS_LENGTH); } static int countBits(final byte[] mask) { int netmask = 0; for (byte b : mask) { netmask += Integer.bitCount(UnsignedBytes.toInt(b)); } return netmask; } static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address){ return new Ipv4Prefix(ipv4Address.getValue() + PREFIX_SEPARATOR + IPV4_ADDRESS_LENGTH); } static Ipv4Prefix createPrefix(final Ipv4Address ipv4Address, final String mask){ /* * Ipv4Address has already validated the address part of the prefix, * It is mandated to comply to the same regexp as the address * There is absolutely no point rerunning additional checks vs this * Note - there is no canonical form check here!!! */ if (null != mask && !mask.isEmpty()) { return new Ipv4Prefix(ipv4Address.getValue() + PREFIX_SEPARATOR + mask); } else { return new Ipv4Prefix(ipv4Address.getValue() + PREFIX_SEPARATOR + IPV4_ADDRESS_LENGTH); } } }