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

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

/*
 * Copyright 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 inet.ipaddr.Address.SegmentValueProvider;
import inet.ipaddr.AddressNetwork.PrefixConfiguration;
import inet.ipaddr.ipv4.IPv4Address;

public class ParsedAddressGrouping {
	
	/**
	 * Returns the index of the segment containing the last byte within the network prefix
	 * When networkPrefixLength is zero (so there are no segments containing bytes within the network prefix), returns -1
	 * 
	 * @param networkPrefixLength
	 * @param byteLength
	 * @return
	 */
	public static int getNetworkSegmentIndex(int networkPrefixLength, int bytesPerSegment, int bitsPerSegment) {
		if(bytesPerSegment > 1) {
			if(bytesPerSegment == 2) {
				return (networkPrefixLength - 1) >> 4;//note this is intentionally a signed shift and not >>> so that networkPrefixLength of 0 returns -1
			}
			return (networkPrefixLength - 1) / bitsPerSegment;
		}
		return (networkPrefixLength - 1) >> 3;
	}
	
	/**
	 * Returns the index of the segment containing the first byte outside the network prefix.
	 * When networkPrefixLength is null, or it matches or exceeds the bit length, returns the segment count.
	 * 
	 * @param networkPrefixLength
	 * @param byteLength
	 * @return
	 */
	public static int getHostSegmentIndex(int networkPrefixLength, int bytesPerSegment, int bitsPerSegment) {
		if(bytesPerSegment > 1) {
			if(bytesPerSegment == 2) {
				return networkPrefixLength >> 4;
			}
			return networkPrefixLength / bitsPerSegment;
		}
		return networkPrefixLength >> 3;
	}
	
	/**
	 * Across an address prefixes are:
	 * IPv6: (null):...:(null):(1 to 16):(0):...:(0)
	 * or IPv4: ...(null).(1 to 8).(0)...
	 */
	public static Integer getSegmentPrefixLength(int bitsPerSegment, Integer prefixLength, int segmentIndex) {
		if(prefixLength != null) {
			return getPrefixedSegmentPrefixLength(bitsPerSegment, prefixLength, segmentIndex);
		}
		return null;
	}

	public static Integer getPrefixedSegmentPrefixLength(int bitsPerSegment, int prefixLength, int segmentIndex) {
		int decrement = (bitsPerSegment == 8) ? segmentIndex << 3 : ((bitsPerSegment == 16) ? segmentIndex << 4 :  segmentIndex * bitsPerSegment);
		return getSegmentPrefixLength(bitsPerSegment, prefixLength - decrement);
	}
	
	/**
	 * Across an address prefixes are:
	 * IPv6: (null):...:(null):(1 to 16):(0):...:(0)
	 * or IPv4: ...(null).(1 to 8).(0)...
	 */
	public static Integer getSegmentPrefixLength(int segmentBits, int segmentPrefixedBits) {
		if(segmentPrefixedBits <= 0) {
			return 0; //none of the bits in this segment matter
		} else if(segmentPrefixedBits <= segmentBits) {
			return segmentPrefixedBits;//some of the bits in this segment matter
		}
		return null; //all the bits in this segment matter
	}
	
	/**
	 * Translates a non-null segment prefix length into an address prefix length.  
	 * When calling this for the first segment with a non-null prefix length, this gives the overall prefix length.
	 * 

* Across an address prefixes are: * IPv6: (null):...:(null):(1 to 16):(0):...:(0) * or IPv4: ...(null).(1 to 8).(0)... */ public static Integer getNetworkPrefixLength(int bitsPerSegment, int segmentPrefixLength, int segmentIndex) { int increment = (bitsPerSegment == 8) ? segmentIndex << 3 : ((bitsPerSegment == 16) ? segmentIndex << 4 : segmentIndex * bitsPerSegment); return increment + segmentPrefixLength; } public static boolean isPrefixSubnet( SegmentValueProvider lowerValueProvider, SegmentValueProvider upperValueProvider, int segmentCount, int bytesPerSegment, int bitsPerSegment, int segmentMaxValue, Integer networkPrefixLength, PrefixConfiguration prefixConfiguration, boolean fullRangeOnly) { if(networkPrefixLength == null || prefixConfiguration.prefixedSubnetsAreExplicit()) { return false; } if(networkPrefixLength < 0) { networkPrefixLength = 0; } else { int totalBitCount = (bitsPerSegment == 8) ? segmentCount << 3 : ((bitsPerSegment == 16) ? segmentCount << 4 : segmentCount * bitsPerSegment); if(networkPrefixLength >= totalBitCount) { return false; } } if(prefixConfiguration.allPrefixedAddressesAreSubnets()) { return true; } int prefixedSegment = getHostSegmentIndex(networkPrefixLength, bytesPerSegment, bitsPerSegment); int i = prefixedSegment; if(i < segmentCount) { int segmentPrefixLength = getSegmentPrefixLength(bitsPerSegment, networkPrefixLength, i); do { //we want to see if there is a sequence of zeros followed by a sequence of full-range bits from the prefix onwards //once we start seeing full range bits, the remained of the section must be full range //for instance x marks the start of zeros and y marks the start of full range: //segment 1 segment 2 ... //upper: 10101010 10100111 11111111 11111111 //lower: 00111010 00100000 00000000 00000000 // x y //upper: 10101010 10100000 00000000 00111111 //lower: 00111010 00100000 10000000 00000000 // x y // //the bit marked x in each set of 4 segment of 8 bits is a sequence of zeros, followed by full range bits starting at bit y int lower = lowerValueProvider.getValue(i); if(segmentPrefixLength == 0) { if(lower != 0) { return false; } int upper = upperValueProvider.getValue(i); if(fullRangeOnly) { if(upper != segmentMaxValue) { return false; } } else { int upperOnes = Integer.numberOfTrailingZeros(~upper); if(upperOnes > 0) { if((upper >>> upperOnes) != 0) { return false; } fullRangeOnly = true; } else if(upper != 0) { return false; } } } else { int segHostBits = bitsPerSegment - segmentPrefixLength; if(fullRangeOnly) { int hostMask = ~(~0 << segHostBits); if((hostMask & lower) != 0) { return false; } int upper = upperValueProvider.getValue(i); if((hostMask & upper) != hostMask) { return false; } } else { int lowerZeros = Integer.numberOfTrailingZeros(lower); if(lowerZeros < segHostBits) { return false; } int upper = upperValueProvider.getValue(i); int upperOnes = Integer.numberOfTrailingZeros(~upper); int upperZeros = Integer.numberOfTrailingZeros((upper | (~0 << bitsPerSegment)) >>> upperOnes); if(upperOnes + upperZeros < segHostBits) { return false; } if(upperOnes > 0) { fullRangeOnly = true; } } } segmentPrefixLength = 0; } while(++i < segmentCount); } return true; } private static final Integer cache[] = new Integer[IPv4Address.MAX_VALUE_PER_SEGMENT + 1]; static { for(int i = 0; i < cache.length; i++) { cache[i] = i; } } public static Integer cache(int i) { if(i >= 0 && i < cache.length) { return cache[i]; } return i; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy