All Downloads are FREE. Search and download functionalities are using the official Maven repository.

inet.ipaddr.format.validate.IPAddressProvider Maven / Gradle / Ivy

There is a newer version: 5.5.1
Show newest version
/*
 * Copyright 2016-2018 Sean C Foley
 *
 * 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
 *     or at
 *     https://github.com/seancfoley/IPAddress/blob/master/LICENSE
 *
 * 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 inet.ipaddr.format.validate;

import java.io.Serializable;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.util.Arrays;
import java.util.Objects;

import inet.ipaddr.HostIdentifierString;
import inet.ipaddr.IPAddress;
import inet.ipaddr.IPAddress.IPVersion;
import inet.ipaddr.IPAddressNetwork;
import inet.ipaddr.IPAddressSeqRange;
import inet.ipaddr.IPAddressStringParameters;
import inet.ipaddr.IncompatibleAddressException;
import inet.ipaddr.format.IPAddressDivisionSeries;
import inet.ipaddr.format.large.IPAddressLargeDivision;
import inet.ipaddr.format.large.IPAddressLargeDivisionGrouping;
import inet.ipaddr.format.standard.IPAddressBitsDivision;
import inet.ipaddr.format.standard.IPAddressDivisionGrouping;
import inet.ipaddr.format.validate.ParsedIPAddress.CachedIPAddresses;
import inet.ipaddr.ipv4.IPv4Address;
import inet.ipaddr.ipv6.IPv6Address;

/**
 * Provides an address corresponding to a parsed string.
 * 
 * @author sfoley
 *
 */
public interface IPAddressProvider extends Serializable {
	//All IP address strings corresponds to exactly one of these types.
	//In cases where there is no corresponding default IPAddress value (INVALID, ALL, and possibly EMPTY), these types can be used for comparison.
	//EMPTY means a zero-length string (useful for validation, we can set validation to allow empty strings) that has no corresponding IPAddress value (validation options allow you to map empty to the loopback)
	//INVALID means it is known that it is not any of the other allowed types (validation options can restrict the allowed types)
	//ALL means it is wildcard(s) with no separators, like "*", which represents all addresses, whether IPv4, IPv6 or other, and thus has no corresponding IPAddress value
	//this enum is ordered by address space size, from smallest to largest, and the ordering affects comparisons
	enum IPType {
		INVALID, EMPTY, IPV4, IPV6, PREFIX_ONLY, ALL;
		
		static IPAddressProvider.IPType from(IPVersion version) {
			switch(version) {
				case IPV4:
					return IPV4;
				case IPV6:
					return IPV6;
				default:
					return null;
			}
		}
	}
	
	@SuppressWarnings("serial")
	public static final NullProvider INVALID_PROVIDER = new NullProvider(IPType.INVALID) {
		@Override
		public boolean isInvalid() {
			return true;
		}
	};
	
	@SuppressWarnings("serial")
	public static final NullProvider NO_TYPE_PROVIDER = new NullProvider(null) {
		@Override
		public boolean isUninitialized() {
			return true;
		}
	};
	
	@SuppressWarnings("serial")
	static final NullProvider EMPTY_PROVIDER = new NullProvider(IPType.EMPTY) {
		@Override
		public boolean isProvidingEmpty() {
			return true;
		}
	};
	
	IPAddressProvider.IPType getType();
	
	IPAddress getProviderHostAddress() throws IncompatibleAddressException;
	
	IPAddress getProviderAddress() throws IncompatibleAddressException;
	
	IPAddress getProviderAddress(IPVersion version) throws IncompatibleAddressException;
	
	default boolean isSequential() {
		try {
			IPAddress addr = getProviderAddress();
			if(addr != null) {
				return addr.isSequential();
			}
		} catch(IncompatibleAddressException e) {}
		return false;
	}

	default IPAddressSeqRange getProviderSeqRange() {
		IPAddress addr = getProviderAddress();
		if(addr != null) {
			return addr.toSequentialRange();
		}
		return null;
	}
	
	default IPAddress getProviderMask() {
		return null;
	}

	default IPAddressDivisionSeries getDivisionGrouping() throws IncompatibleAddressException {
		return getProviderAddress();
	}

	default int providerCompare(IPAddressProvider other) throws IncompatibleAddressException {
		if(this == other) {
			return 0;
		}
		IPAddress value = getProviderAddress();
		if(value != null) {
			IPAddress otherValue = other.getProviderAddress();
			if(otherValue != null) {
				return value.compareTo(otherValue);
			}
		}
		IPType thisType = getType(), otherType = other.getType();
		if(thisType == null) {
			return otherType == null ? 0 : -1;
		} else if(otherType == null) {
			return 1;
		}
		return thisType.ordinal() - otherType.ordinal();
	}
	
	/**
	 * When a value provider produces no value, equality and comparison are based on the enum IPType,
	 * which can by null.
	 * @param o
	 * @return
	 */
	default boolean providerEquals(IPAddressProvider other) throws IncompatibleAddressException {
		if(this == other) {
			return true;
		}
		IPAddress value = getProviderAddress();
		if(value != null) {
			IPAddress otherValue = other.getProviderAddress();
			if(otherValue != null) {
				return value.equals(otherValue);
			} else {
				return false;
			}
		}
		//this works with both null and also non-null since the type is an enum
		return getType() == other.getType();
	}
	
	default int providerHashCode() throws IncompatibleAddressException {
		IPAddress value = getProviderAddress();
		if(value != null) {
			return value.hashCode();
		}
		return Objects.hashCode(getType());
	}

	default IPVersion getProviderIPVersion() {
		return null;
	}
	
	default boolean isProvidingIPAddress() {
		return false;
	}
	
	default boolean isProvidingIPv4() {
		return false;
	}
	
	default boolean isProvidingIPv6() {
		return false;
	}
	
	default boolean isProvidingPrefixOnly() {
		return false;
	}
	
	default boolean isProvidingAllAddresses() {
		return false;
	}
	
	default boolean isProvidingEmpty() {
		return false;
	}
	
	default boolean isProvidingMixedIPv6() {
		return false;
	}
	
	default boolean isProvidingBase85IPv6() {
		return false;
	}
	
	default Integer getProviderNetworkPrefixLength() {
		return null;
	}

	default boolean isInvalid() {
		return false;
	}
	
	default boolean isUninitialized() {
		return false;
	}
	
	/**
	 * An optimized contains that does not need to create address objects to return an answer.
	 * Unconventional addresses may require that the address objects are created, in such cases null is returned.
	 * 
	 * Addresses constructed from canonical or normalized representations with no wildcards will not return null.
	 * 
	 * @param other
	 * @return
	 */
	default Boolean contains(IPAddressProvider other) {
		return null;
	}

	/**
	 * An optimized contains that does not need to fully parse the other address to return an answer.
	 * 
	 * Unconventional addresses may require full parsing, in such cases null is returned.
	 * 
	 * Addresses constructed from canonical or normalized representations with no wildcards will not return null.
	 * 
	 * @param other
	 * @return
	 */
	default Boolean contains(String other) {
		return null;
	}
	
	/**
	 * An optimized prefix comparison that does not need to fully parse the other address to return an answer.
	 * 
	 * Unconventional addresses may require full parsing, in such cases null is returned.
	 * 
	 * Addresses constructed from canonical or normalized representations with no wildcards will not return null.
	 * 
	 * @param other
	 * @return
	 */
	default Boolean prefixEquals(String other) {
		return null;
	}

	/**
	 * An optimized prefix comparison that does not need to create addresses to return an answer.
	 * 
	 * Unconventional addresses may require the address objects, in such cases null is returned.
	 * 
	 * @param other
	 * @return
	 */
	default Boolean prefixEquals(IPAddressProvider other) {
		return null;
	}
	
	/**
	 * An optimized prefix comparison that does not need to create addresses to return an answer.
	 * 
	 * Unconventional addresses may require the address objects, in such cases null is returned.
	 * 
	 * @param other
	 * @return
	 */
	default Boolean prefixContains(String other) {
		return null;
	}
	
	/**
	 * An optimized prefix comparison that does not need to create addresses to return an answer.
	 * 
	 * Unconventional addresses may require the address objects, in such cases null is returned.
	 * 
	 * @param other
	 * @return
	 */
	default Boolean prefixContains(IPAddressProvider other) {
		return null;
	}
	
	/**
	 * An optimized equality comparison that does not need to create addresses to return an answer.
	 * 
	 * Unconventional addresses may require the address objects, in such cases null is returned.
	 * 
	 * @param other
	 * @return
	 */
	default Boolean parsedEquals(IPAddressProvider other) {
		return null;
	}
	
	default boolean hasPrefixSeparator() {
		return getProviderNetworkPrefixLength() != null;
	}
	
	/**
	 * If the address was created by parsing, this provides the parameters used when creating the address.
	 * 
	 * @return the parameters used to create the address, or null if no such parameters were used.
	 */
	default IPAddressStringParameters getParameters() {
		return null;
	}
	
	//for addresses that cannot produce an ipv4 or ipv6 value and has no prefix either
	abstract static class NullProvider implements IPAddressProvider {
		private static final long serialVersionUID = 4L;
		private IPType type;
		
		public NullProvider(IPAddressProvider.IPType type) {
			this.type = type;
		}
		
		@Override
		public IPAddressProvider.IPType getType() {
			return type;
		}
		
		@Override
		public IPAddress getProviderHostAddress() {
			return null;
		}
		
		@Override
		public IPAddress getProviderAddress() {
			return null;
		}
		
		@Override
		public IPAddress getProviderAddress(IPVersion version) {
			return null;
		}
		
		@Override
		public int providerHashCode() {
			return Objects.hashCode(getType());
		}
		
		/**
		 * When a value provider produces no value, equality and comparison are based on the enum IPType,
		 * which can be null.
		 * @param o
		 * @return
		 */
		@Override
		public boolean providerEquals(IPAddressProvider o) {
			if(this == o) {
				return true;
			}
			if(o instanceof NullProvider) {
				NullProvider other = (NullProvider) o;
				//this works with both null and also non-null since the type is an enum
				return getType() == other.getType();
			}
			return false;
		}
		
		@Override
		public String toString() {
			return String.valueOf(getType());
		}
	}
	
	/**
	 * Wraps an IPAddress for IPAddressString in the cases where no parsing is provided, the address exists already
	 * @param value
	 * @return
	 */
	public static IPAddressProvider getProviderFor(IPAddress address, IPAddress hostAddress) {
		return new CachedAddressProvider(address, hostAddress);
	}
	
	static class CachedAddressProvider implements IPAddressProvider {
		private static final long serialVersionUID = 4L;
		CachedIPAddresses values;
		
		CachedAddressProvider() {}
		
		//constructor where we already have a value
		private CachedAddressProvider(IPAddress address, IPAddress hostAddress) {
			this.values = new CachedIPAddresses(address, hostAddress);
		}
		
		@Override
		public IPAddress getProviderAddress(IPVersion version) {
			IPVersion thisVersion = getProviderIPVersion();
			if(!version.equals(thisVersion)) {
				return null;
			}
			return getProviderAddress();
		}

		CachedIPAddresses createAddresses() {
			 return null;
		}
		
		private CachedIPAddresses getCachedAddresses()  {
			CachedIPAddresses val = values;
			if(val == null) {
				synchronized(this) {
					val = values;
					if(val == null) {
						values = val = createAddresses();
					}
				}
			}
			return val;
		}
		
		@Override
		public IPAddress getProviderHostAddress()  {
			return getCachedAddresses().getHostAddress();
		}
		
		@Override
		public IPAddress getProviderAddress()  {
			return getCachedAddresses().getAddress();
		}
		
		@Override
		public Integer getProviderNetworkPrefixLength() {
			return getProviderAddress().getNetworkPrefixLength();
		}

		@Override
		public IPVersion getProviderIPVersion() {
			return getProviderAddress().getIPVersion();
		}
		
		@Override
		public IPAddressProvider.IPType getType() {
			return IPType.from(getProviderIPVersion());
		}
		
		@Override
		public boolean isProvidingIPAddress() {
			return true;
		}
		
		@Override
		public boolean isProvidingIPv4() {
			return getProviderAddress().isIPv4();
		}
		
		@Override
		public boolean isProvidingIPv6() {
			return getProviderAddress().isIPv6();
		}

		@Override
		public String toString() {
			return String.valueOf(getProviderAddress());
		}
	}
	
	static abstract class VersionedAddressCreator extends CachedAddressProvider {
		private static final long serialVersionUID = 4L;
		IPAddress versionedValues[];
		protected final IPAddressStringParameters options;
		
		VersionedAddressCreator(IPAddressStringParameters options) {
			this.options = options;
		}
		
		@Override
		public IPAddressStringParameters getParameters() {
			return options;
		}
		
		private IPAddress checkResult(IPVersion version, int index) {
			IPAddress result = versionedValues[index];
			if(result == null) {
				versionedValues[index] = result = createVersionedAddress(version);
			}
			return result;
		}
		
		@Override
		public IPAddress getProviderAddress(IPVersion version) {
			int index = version.ordinal();
			IPAddress result;
			if(versionedValues == null) {
				synchronized(this) {
					if(versionedValues == null) {
						versionedValues = new IPAddress[IPVersion.values().length];
						versionedValues[index] = result = createVersionedAddress(version);
					} else {
						result = checkResult(version, index);
					}
				}
			} else {
				result = versionedValues[index];
				if(result == null) {
					synchronized(this) {
						result = checkResult(version, index);
					}
				}
			}
			return result;
		}
	
		abstract IPAddress createVersionedAddress(IPVersion version);
	}

	static abstract class AdjustedAddressCreator extends VersionedAddressCreator {
		private static final long serialVersionUID = 4L;
		protected final IPVersion adjustedVersion;
		protected final Integer networkPrefixLength;
		
		AdjustedAddressCreator(Integer networkPrefixLength, IPAddressStringParameters options) {
			this(networkPrefixLength, null, options);
		}
		
		AdjustedAddressCreator(Integer networkPrefixLength, IPVersion adjustedVersion, IPAddressStringParameters options) {
			super(options);
			this.networkPrefixLength = networkPrefixLength;
			this.adjustedVersion = adjustedVersion;
		}
		
		@Override
		public boolean isProvidingIPAddress() {
			return adjustedVersion != null;
		}
		
		@Override
		public boolean isProvidingIPv4() {
			return isProvidingIPAddress() && adjustedVersion.isIPv4();
		}
		
		@Override
		public boolean isProvidingIPv6() {
			return isProvidingIPAddress() && adjustedVersion.isIPv6();
		}
		
		@Override
		public IPVersion getProviderIPVersion() {
			return adjustedVersion;
		}
		
		@Override
		public Integer getProviderNetworkPrefixLength() {
			return networkPrefixLength;
		}
		
		@Override
		public IPAddress getProviderAddress()  {
			if(adjustedVersion == null) {
				return null;
			}
			return super.getProviderAddress();
		}
		
		@Override
		public IPAddress getProviderHostAddress()  {
			if(adjustedVersion == null) {
				return null;
			}
			return super.getProviderHostAddress();
		}
	}
	
	static class MaskCreator extends AdjustedAddressCreator {
		private static final long serialVersionUID = 4L;
		
		MaskCreator(Integer networkPrefixLength, IPAddressStringParameters options) {
			super(networkPrefixLength, options);
		}
		
		MaskCreator(Integer networkPrefixLength, IPVersion adjustedVersion, IPAddressStringParameters options) {
			super(networkPrefixLength, adjustedVersion, options);
		}
		
		@Override
		public int providerHashCode() {
			if(adjustedVersion == null) {
				return getProviderNetworkPrefixLength();
			}
			return getProviderAddress().hashCode();
		}
		
		@Override
		public boolean providerEquals(IPAddressProvider valueProvider) {
			if(valueProvider == this) {
				return true;
			}
			if(adjustedVersion == null) {
				if(valueProvider.getType() == IPType.PREFIX_ONLY) {//both are PREFIX_ONLY
					return valueProvider.getProviderNetworkPrefixLength().intValue() == getProviderNetworkPrefixLength().intValue();
				}
				return false;
			}
			return super.providerEquals(valueProvider);
		}
		
		@Override
		public int providerCompare(IPAddressProvider other) throws IncompatibleAddressException {
			if(this == other) {
				return 0;
			}
			if(adjustedVersion == null) {
				if(other.getType() == IPType.PREFIX_ONLY) {//both are PREFIX_ONLY
					return other.getProviderNetworkPrefixLength().intValue() - getProviderNetworkPrefixLength().intValue();
				}
				return IPType.PREFIX_ONLY.ordinal() - other.getType().ordinal();
			}
			IPAddress otherValue = other.getProviderAddress();
			if(otherValue != null) {
				return getProviderAddress().compareTo(otherValue);
			}
			return IPType.from(adjustedVersion).ordinal() - other.getType().ordinal();
		}

		private IPAddress createVersionedMask(IPVersion version, int bits, boolean withPrefixLength) {
			IPAddressNetwork network = version.isIPv4() ? options.getIPv4Parameters().getNetwork() : options.getIPv6Parameters().getNetwork();
			return withPrefixLength ? network.getNetworkAddress(bits) : network.getNetworkMask(bits, false);
		}

		@Override
		IPAddress createVersionedAddress(IPVersion version) {
			return createVersionedMask(version, getProviderNetworkPrefixLength(), true);
		}

		@Override
		public IPAddressProvider.IPType getType() {
			if(adjustedVersion != null) {
				return IPType.from(adjustedVersion);
			}
			return IPType.PREFIX_ONLY;
		}
		
		@Override
		public boolean isProvidingPrefixOnly() {
			return adjustedVersion == null;
		}
		
		@Override
		CachedIPAddresses createAddresses() {
			return new CachedIPAddresses(
					createVersionedMask(adjustedVersion, getProviderNetworkPrefixLength(), true),
					createVersionedMask(adjustedVersion, getProviderNetworkPrefixLength(), false));
		}
	}
	
	static class LoopbackCreator extends VersionedAddressCreator {
		private static final long serialVersionUID = 4L;
		private final CharSequence zone;
		
		LoopbackCreator(IPAddressStringParameters options) {
			this(null, options);
		}

		LoopbackCreator(CharSequence zone, IPAddressStringParameters options) {
			super(options);
			this.zone = zone;
		}
		
		@Override
		IPAddress createVersionedAddress(IPVersion version) {
			if(values != null && version.equals(values.getAddress().getIPVersion())) {
				return values.getAddress();
			}
			IPAddressNetwork network = version.isIPv4() ? options.getIPv4Parameters().getNetwork() : options.getIPv6Parameters().getNetwork();
			IPAddress address = network.getLoopback();
			if(zone != null && zone.length() > 0 && version.isIPv6()) {
				ParsedAddressCreator addressCreator = network.getAddressCreator();
				return addressCreator.createAddressInternal(address.getBytes(), zone);
			}
			return address;
		}
		
		@Override
		CachedIPAddresses createAddresses() {
			InetAddress loopback = InetAddress.getLoopbackAddress();
			boolean isIPv6 = loopback instanceof Inet6Address;
			IPAddress result;
			if(zone != null && zone.length() > 0 && isIPv6) {
				ParsedAddressCreator addressCreator = options.getIPv6Parameters().getNetwork().getAddressCreator();
				result = addressCreator.createAddressInternal(loopback.getAddress(), zone);
			} else if(isIPv6) {
				result = options.getIPv6Parameters().getNetwork().getLoopback();
			} else {
				result = options.getIPv4Parameters().getNetwork().getLoopback();
			}
			return new CachedIPAddresses(result);
		}
		
		@Override
		public Integer getProviderNetworkPrefixLength() {
			return null;
		}
	}
	
	static class AllCreator extends AdjustedAddressCreator {
		private static final long serialVersionUID = 4L;
		HostIdentifierString originator;
		ParsedHostIdentifierStringQualifier qualifier;
		
		AllCreator(ParsedHostIdentifierStringQualifier qualifier, HostIdentifierString originator, IPAddressStringParameters options) {
			super(qualifier.getEquivalentPrefixLength(), options);
			this.originator = originator;
			this.qualifier = qualifier;
		}
		
		AllCreator(ParsedHostIdentifierStringQualifier qualifier, IPVersion adjustedVersion, HostIdentifierString originator, IPAddressStringParameters options) {
			super(qualifier.getEquivalentPrefixLength(), adjustedVersion, options);
			this.originator = originator;
			this.qualifier = qualifier;
		}
		
		@Override
		IPAddress createVersionedAddress(IPVersion version) {
			return ParsedIPAddress.createAllAddress(version, qualifier, originator, options);
		}

		@Override
		public IPAddressProvider.IPType getType() {
			if(adjustedVersion != null) {
				return IPType.from(adjustedVersion);
			}
			return IPType.ALL;
		}
		
		@Override
		public Boolean contains(IPAddressProvider otherProvider) {
			if(otherProvider.isInvalid()) {
				return Boolean.FALSE;
			} else if(adjustedVersion == null) {
				return Boolean.TRUE;
			}
			return adjustedVersion == otherProvider.getProviderIPVersion();
		}
		
		@Override
		public boolean isProvidingAllAddresses() {
			return adjustedVersion == null;
		}
		
		@Override
		public Integer getProviderNetworkPrefixLength() {
			return qualifier.getEquivalentPrefixLength();
		}
		
		@Override
		public int providerHashCode() {
			if(adjustedVersion == null) {
				return IPAddress.SEGMENT_WILDCARD_STR.hashCode();
			}
			return super.hashCode();
		}
		
		@Override
		CachedIPAddresses createAddresses() {
			if(qualifier.equals(ParsedHost.NO_QUALIFIER)) {
				return new CachedIPAddresses(ParsedIPAddress.createAllAddress(adjustedVersion, qualifier, originator, options));
			}
			return new CachedIPAddresses(ParsedIPAddress.createAllAddress(adjustedVersion, qualifier, originator, options),
					ParsedIPAddress.createAllAddress(adjustedVersion, qualifier.getZone() != null ? new ParsedHostIdentifierStringQualifier(qualifier.getZone()) : ParsedHost.NO_QUALIFIER, originator, options));
		}
		
		@Override
		public IPAddress getProviderMask() {
			return qualifier.getMaskLower();
		}

		@Override
		public IPAddressSeqRange getProviderSeqRange() {
			if(isProvidingAllAddresses()) {
				return null;
			}
			IPAddress mask = getProviderMask();
			if(mask != null && mask.getBlockMaskPrefixLength(true) == null) {
				// we must apply the mask
				IPAddress all = ParsedIPAddress.createAllAddress(adjustedVersion, ParsedHost.NO_QUALIFIER, null, options);
				IPAddress upper = all.getUpper().mask(mask);
				IPAddress lower = all.getLower();
				return lower.spanWithRange(upper);
			}
			return super.getProviderSeqRange();
		}

		@Override
		public boolean isSequential() {
			return !isProvidingAllAddresses();
		}

		@Override
		public IPAddressDivisionSeries getDivisionGrouping() throws IncompatibleAddressException {
			if(isProvidingAllAddresses()) {
				return null;
			}
			IPAddressNetwork network = adjustedVersion.isIPv4() ?
					options.getIPv4Parameters().getNetwork() : options.getIPv6Parameters().getNetwork();
			IPAddress mask = getProviderMask();
			if(mask != null && mask.getBlockMaskPrefixLength(true) == null) {
				// there is a mask
				Integer hostMaskPrefixLen = mask.getBlockMaskPrefixLength(false);
				if(hostMaskPrefixLen == null) { // not a host mask
					throw new IncompatibleAddressException(getProviderAddress(), mask, "ipaddress.error.maskMismatch");
				}
				IPAddress hostMask = network.getHostMask(hostMaskPrefixLen);
				return hostMask.toPrefixBlock();
			}
			IPAddressDivisionSeries grouping;
			if(adjustedVersion.isIPv4()) {
				grouping = new IPAddressDivisionGrouping(new IPAddressBitsDivision[] {
							new IPAddressBitsDivision(0, IPv4Address.MAX_VALUE, IPv4Address.BIT_COUNT, IPv4Address.DEFAULT_TEXTUAL_RADIX, network, qualifier.getEquivalentPrefixLength())
						}, network);
			} else if(adjustedVersion.isIPv6()) {
				byte upperBytes[] = new byte[16];
				Arrays.fill(upperBytes, (byte) 0xff);
				grouping = new IPAddressLargeDivisionGrouping(new IPAddressLargeDivision[] {new IPAddressLargeDivision(new byte[IPv6Address.BYTE_COUNT], upperBytes, IPv6Address.BIT_COUNT, IPv6Address.DEFAULT_TEXTUAL_RADIX, network, qualifier.getEquivalentPrefixLength())}, network);
			} else {
				grouping = null;
			}
			return grouping;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy