inet.ipaddr.ipv4.IPv4Address Maven / Gradle / Ivy
Show all versions of ipaddress Show documentation
/*
* 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.ipv4;
import java.net.Inet4Address;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import inet.ipaddr.Address;
import inet.ipaddr.AddressConversionException;
import inet.ipaddr.AddressNetwork.PrefixConfiguration;
import inet.ipaddr.AddressValueException;
import inet.ipaddr.IPAddress;
import inet.ipaddr.IPAddressConverter;
import inet.ipaddr.IPAddressSection.IPStringBuilderOptions;
import inet.ipaddr.IPAddressSegmentSeries;
import inet.ipaddr.IPAddressStringParameters;
import inet.ipaddr.IncompatibleAddressException;
import inet.ipaddr.PrefixLenException;
import inet.ipaddr.format.string.IPAddressStringDivisionSeries;
import inet.ipaddr.format.util.AddressComponentSpliterator;
import inet.ipaddr.format.util.AddressComponentRangeSpliterator;
import inet.ipaddr.format.util.IPAddressPartStringCollection;
import inet.ipaddr.ipv4.IPv4AddressNetwork.IPv4AddressCreator;
import inet.ipaddr.ipv4.IPv4AddressSection.IPv4AddressCache;
import inet.ipaddr.ipv4.IPv4AddressSection.IPv4StringBuilderOptions;
import inet.ipaddr.ipv4.IPv4AddressSection.IPv4StringCollection;
import inet.ipaddr.ipv6.IPv6Address;
import inet.ipaddr.ipv6.IPv6Address.IPv6AddressConverter;
import inet.ipaddr.ipv6.IPv6AddressNetwork;
import inet.ipaddr.ipv6.IPv6AddressNetwork.IPv6AddressCreator;
import inet.ipaddr.ipv6.IPv6AddressSection;
import inet.ipaddr.ipv6.IPv6AddressSegment;
/**
* An IPv4 address, or a subnet of multiple IPv4 addresses. Each segment can represent a single value or a range of values.
*
* You can construct an IPv4 address from a byte array, from an int, from a {@link inet.ipaddr.Address.SegmentValueProvider},
* from Inet4Address, from an {@link IPv4AddressSection} of 4 segments, or from an array of 4 {@link IPv4AddressSegment} objects.
*
* To construct one from a {@link java.lang.String} use
* {@link inet.ipaddr.IPAddressString#toAddress()} or {@link inet.ipaddr.IPAddressString#getAddress()}, {@link inet.ipaddr.IPAddressString#toHostAddress()} or {@link inet.ipaddr.IPAddressString#getHostAddress()}
*
*
* @custom.core
* @author sfoley
*
*/
public class IPv4Address extends IPAddress implements Iterable {
private static final long serialVersionUID = 4L;
public static final char SEGMENT_SEPARATOR = '.';
public static final int BITS_PER_SEGMENT = 8;
public static final int BYTES_PER_SEGMENT = 1;
public static final int SEGMENT_COUNT = 4;
public static final int BYTE_COUNT = 4;
public static final int BIT_COUNT = 32;
public static final int DEFAULT_TEXTUAL_RADIX = 10;
public static final int MAX_VALUE_PER_SEGMENT = 0xff;
public static final int MAX_VALUE = 0xffffffff;
public static final String REVERSE_DNS_SUFFIX = ".in-addr.arpa";
transient IPv4AddressCache addressCache;
/**
* Constructs an IPv4 address or subnet.
* @param segments the address segments
* @throws AddressValueException if segments is not length 4
*/
public IPv4Address(IPv4AddressSegment[] segments) throws AddressValueException {
this(segments, null);
}
/**
* Constructs an IPv4 address or subnet.
*
* When networkPrefixLength is non-null, depending on the prefix configuration (see {@link inet.ipaddr.AddressNetwork#getPrefixConfiguration()},
* this object may represent either a single address with that network prefix length, or the prefix subnet block containing all addresses with the same network prefix.
*
* @param segments the address segments
* @param networkPrefixLength
* @throws AddressValueException if segments is not length 4
*/
public IPv4Address(IPv4AddressSegment[] segments, Integer networkPrefixLength) throws AddressValueException {
super(thisAddress -> ((IPv4Address) thisAddress).getAddressCreator().createSection(segments, networkPrefixLength));
if(getSegmentCount() != SEGMENT_COUNT) {
throw new AddressValueException("ipaddress.error.ipv4.invalid.segment.count", getSegmentCount());
}
}
/**
* Constructs an IPv4 address or subnet.
* @param section the address segments
* @throws AddressValueException if section does not have 4 segments
*/
public IPv4Address(IPv4AddressSection section) throws AddressValueException {
super(section);
if(section.getSegmentCount() != SEGMENT_COUNT) {
throw new AddressValueException("ipaddress.error.ipv4.invalid.segment.count", section.getSegmentCount());
}
}
/**
* Constructs an IPv4 address.
*
* @param address the 4 byte IPv4 address
*/
public IPv4Address(int address) {
this(address, null);
}
/**
* Constructs an IPv4 address or subnet.
*
* When networkPrefixLength is non-null, depending on the prefix configuration (see {@link inet.ipaddr.AddressNetwork#getPrefixConfiguration()},
* this object may represent either a single address with that network prefix length, or the prefix subnet block containing all addresses with the same network prefix.
*
*
* @param address the 4 byte IPv4 address
* @param networkPrefixLength the CIDR network prefix length, which can be null for no prefix
*/
public IPv4Address(int address, Integer networkPrefixLength) throws AddressValueException {
super(thisAddress -> ((IPv4Address) thisAddress).getAddressCreator().createSectionInternal(address, networkPrefixLength));
}
/**
* Constructs an IPv4 address.
*
* @param inet4Address the java.net address object
*/
public IPv4Address(Inet4Address inet4Address, Integer networkPrefixLength) {
this(inet4Address, inet4Address.getAddress(), networkPrefixLength);
}
/**
* Constructs an IPv4 address.
*
* @param inet4Address the java.net address object
*/
public IPv4Address(Inet4Address inet4Address) {
this(inet4Address, inet4Address.getAddress(), null);
}
private IPv4Address(Inet4Address inet4Address, byte[] bytes, Integer networkPrefixLength) throws AddressValueException {
super(thisAddress -> ((IPv4Address) thisAddress).getAddressCreator().createSection(bytes, 0, bytes.length, IPv4Address.SEGMENT_COUNT, networkPrefixLength));
getSection().setInetAddress(inet4Address);
}
/**
* Constructs an IPv4 address.
*
* @param bytes the 4 byte IPv4 address in network byte order - if longer than 4 bytes the additional bytes must be zero, if shorter than 4 bytes then then the bytes are sign-extended to 4 bytes.
* @throws AddressValueException if bytes not equivalent to a 4 byte address
*/
public IPv4Address(byte[] bytes) throws AddressValueException {
this(bytes, null);
}
/**
* Constructs an IPv4 address or subnet.
*
* Similar to {@link #IPv4Address(byte[])} except that you can specify the start and end of the address in the given byte array.
*
* @param bytes
* @throws AddressValueException
*/
public IPv4Address(byte[] bytes, int byteStartIndex, int byteEndIndex) throws AddressValueException {
this(bytes, byteStartIndex, byteEndIndex, null);
}
/**
* Constructs an IPv4 address or subnet.
*
* When networkPrefixLength is non-null, depending on the prefix configuration (see {@link inet.ipaddr.AddressNetwork#getPrefixConfiguration()},
* this object may represent either a single address with that network prefix length, or the prefix subnet block containing all addresses with the same network prefix.
*
*
* @param bytes the 4 byte IPv4 address in network byte order - if longer than 4 bytes the additional bytes must be zero, if shorter than 4 bytes then the bytes are sign-extended to 4 bytes.
* @param networkPrefixLength the CIDR network prefix length, which can be null for no prefix
* @throws AddressValueException if bytes not equivalent to a 4 byte address
*/
public IPv4Address(byte[] bytes, Integer networkPrefixLength) throws AddressValueException {
this(bytes, 0, bytes.length, networkPrefixLength);
}
/**
* Constructs an IPv4 address or subnet.
*
* Similar to {@link #IPv4Address(byte[],Integer)} except that you can specify the start and end of the address in the given byte array.
*
* When networkPrefixLength is non-null, depending on the prefix configuration (see {@link inet.ipaddr.AddressNetwork#getPrefixConfiguration()},
* this object may represent either a single address with that network prefix length, or the prefix subnet block containing all addresses with the same network prefix.
*
*
* @param bytes the 4 byte IPv4 address - if longer than 4 bytes the additional bytes must be zero, if shorter than 4 bytes then the bytes are sign-extended to 4 bytes.
* @param networkPrefixLength the CIDR network prefix length, which can be null for no prefix
* @throws AddressValueException if bytes not equivalent to a 4 byte address
*/
public IPv4Address(byte[] bytes, int byteStartIndex, int byteEndIndex, Integer networkPrefixLength) throws AddressValueException {
super(thisAddress -> ((IPv4Address) thisAddress).getAddressCreator().createSection(bytes, byteStartIndex, byteEndIndex, IPv4Address.SEGMENT_COUNT, networkPrefixLength));
}
/**
* Constructs an IPv4 address or subnet.
*
* When networkPrefixLength is non-null, depending on the prefix configuration (see {@link inet.ipaddr.AddressNetwork#getPrefixConfiguration()},
* this object may represent either a single address with that network prefix length, or the prefix subnet block containing all addresses with the same network prefix.
*
*
* @param lowerValueProvider supplies the 1 byte lower values for each segment
* @param upperValueProvider supplies the 1 byte upper values for each segment
* @param networkPrefixLength the CIDR network prefix length, which can be null for no prefix
*/
public IPv4Address(SegmentValueProvider lowerValueProvider, SegmentValueProvider upperValueProvider, Integer networkPrefixLength) throws AddressValueException {
super(thisAddress -> ((IPv4Address) thisAddress).getAddressCreator().createFullSectionInternal(lowerValueProvider, upperValueProvider, networkPrefixLength));
}
/**
* Constructs an IPv4 address or subnet.
*
* @param lowerValueProvider supplies the 1 byte lower values for each segment
* @param upperValueProvider supplies the 1 byte upper values for each segment
*/
public IPv4Address(SegmentValueProvider lowerValueProvider, SegmentValueProvider upperValueProvider) {
this(lowerValueProvider, upperValueProvider, null);
}
/**
* Constructs an IPv4 address.
*
* When networkPrefixLength is non-null, depending on the prefix configuration (see {@link inet.ipaddr.AddressNetwork#getPrefixConfiguration()},
* this object may represent either a single address with that network prefix length, or the prefix subnet block containing all addresses with the same network prefix.
*
*
* @param valueProvider supplies the 1 byte value for each segment
* @param networkPrefixLength the CIDR network prefix length, which can be null for no prefix
*/
public IPv4Address(SegmentValueProvider valueProvider, Integer networkPrefixLength) throws AddressValueException {
this(valueProvider, valueProvider, networkPrefixLength);
}
/**
* Constructs an IPv4 address.
*
* @param valueProvider supplies the 1 byte value for each segment
*/
public IPv4Address(SegmentValueProvider valueProvider) {
this(valueProvider, (Integer) null);
}
@Override
public IPv4AddressSection getSection() {
return (IPv4AddressSection) super.getSection();
}
@Override
public IPv4AddressSection getSection(int index) {
return getSection().getSection(index);
}
@Override
public IPv4AddressSection getSection(int index, int endIndex) {
return getSection().getSection(index, endIndex);
}
@Override
public IPv4AddressSegment getDivision(int index) {
return getSegment(index);
}
@Override
public IPv4AddressSegment getSegment(int index) {
return getSection().getSegment(index);
}
@Override
public IPv4AddressSegment[] getSegments() {
return getSection().getSegments();
}
@Override
public IPAddressStringDivisionSeries[] getParts(IPStringBuilderOptions options) {
return getParts(IPv4StringBuilderOptions.from(options));
}
public IPAddressStringDivisionSeries[] getParts(IPv4StringBuilderOptions options) {
IPAddressStringDivisionSeries parts[] = getSection().getParts(options);
IPv6Address ipv6Addr = getConverted(options);
if(ipv6Addr != null) {
IPAddressStringDivisionSeries ipv6Parts[] = ipv6Addr.getParts(options.ipv6ConverterOptions);
IPAddressStringDivisionSeries tmp[] = parts;
parts = new IPAddressStringDivisionSeries[tmp.length + ipv6Parts.length];
System.arraycopy(tmp, 0, parts, 0, tmp.length);
System.arraycopy(ipv6Parts, 0, parts, tmp.length, ipv6Parts.length);
}
return parts;
}
@Override
public int getSegmentCount() {
return SEGMENT_COUNT;
}
@Override
public int getByteCount() {
return BYTE_COUNT;
}
@Override
public int getBitCount() {
return BIT_COUNT;
}
@Override
public boolean isIPv4() {
return true;
}
@Override
public IPv4Address toIPv4() {
return this;
}
@Override
public boolean isIPv4Convertible() {
return true;
}
/**
* Create an IPv6 mixed address using the given ipv6 segments and using this address for the embedded IPv4 segments
*
* @param segs
* @return
*/
public IPv6Address getIPv6Address(IPv6AddressSegment segs[]) {
IPv6AddressCreator creator = getIPv6Network().getAddressCreator();
return creator.createAddress(IPv6AddressSection.createSection(creator, segs, this)); /* address creation */
}
public IPv6Address getIPv4MappedAddress() {
IPv6AddressCreator creator = getIPv6Network().getAddressCreator();
IPv6AddressSegment zero = creator.createSegment(0);
IPv6AddressSegment segs[] = creator.createSegmentArray(IPv6Address.MIXED_ORIGINAL_SEGMENT_COUNT);
segs[0] = segs[1] = segs[2] = segs[3] = segs[4] = zero;
segs[5] = creator.createSegment(IPv6Address.MAX_VALUE_PER_SEGMENT);
return getIPv6Address(segs);
}
/**
* Override this method to convert in your own way.
* The default behaviour uses IPv4-mapped conversion.
*
* You should also override {@link #toIPv6()} to match the conversion.
*
* @see IPv4Address#toIPv6()
*/
@Override
public boolean isIPv6Convertible() {
IPAddressConverter conv = DEFAULT_ADDRESS_CONVERTER;
return conv.isIPv6Convertible(this);
}
/**
* Returns this address converted to IPv6.
*
* You can also use {@link #isIPv6Convertible()} to determine convertibility. Both use an instance of {@link IPAddressConverter.DefaultAddressConverter} which uses IPv4-mapped address mappings from rfc 4038.
*
* Override this method and {@link IPv6Address#isIPv6Convertible()} if you wish to map IPv4 to IPv6 according to the mappings defined by
* in {@link IPv6Address#isIPv4Compatible()}, {@link IPv6Address#isIPv4Mapped()}, {@link IPv6Address#is6To4()} or some other mapping.
*
* If you override this method, you should also override the {@link IPv4Address#isIPv6Convertible()} method to match this behaviour,
* and potentially also override the reverse conversion {@link IPv6Address#toIPv4()} in your {@link IPv6Address} subclass.
*/
@Override
public IPv6Address toIPv6() {
IPAddressConverter conv = DEFAULT_ADDRESS_CONVERTER;
return conv.toIPv6(this);
}
/**
* The broadcast address has the same prefix but a host that is all 1 bits.
* If this address or subnet is not prefixed, this returns the address of all 1 bits, the "max" address.
*
* @return
*/
public IPv4Address toBroadcastAddress() {
return toMaxHost();
}
/**
* The network address has the same prefix but a zero host.
* If this address or subnet is not prefixed, this returns the zero "any" address.
*
* @return
*/
public IPv4Address toNetworkAddress() {
return toZeroHost();
}
void cache(IPv4Address lower, IPv4Address upper) {
getSection().cache(this, lower, upper);
}
@Override
public IPv4Address getLowerNonZeroHost() {
return getSection().getLowestOrHighest(this, true, true);
}
@Override
public IPv4Address getLower() {
return getSection().getLowestOrHighest(this, true, false);
}
@Override
public IPv4Address getUpper() {
return getSection().getLowestOrHighest(this, false, false);
}
/**
* Returns the address (or lowest value of the address if a subnet) as a signed integer
* @return the signed integer lower address value
*/
public int intValue() {
return getSection().intValue();
}
/**
* Returns the address (or highest value of the address if a subnet) as a signed integer
* @return the signed integer upper address value
*/
public int upperIntValue() {
return getSection().upperIntValue();
}
/**
* Returns the address (or lowest value of the address if a subnet) as a positive integer
* @return the positive integer lower address value
*/
public long longValue() {
return getSection().longValue();
}
/**
* Returns the address (or highest value of the address if a subnet) as a positive integer
* @return the positive integer upper address value
*/
public long upperLongValue() {
return getSection().upperLongValue();
}
/**
* Replaces segments starting from startIndex and ending before endIndex with the same number of segments starting at replacementStartIndex from the replacement section
*
* @param startIndex
* @param endIndex
* @param replacement
* @param replacementIndex
* @throws IndexOutOfBoundsException
* @return
*/
public IPv4Address replace(int startIndex, int endIndex, IPv4Address replacement, int replacementIndex) {
return checkIdentity(getSection().replace(startIndex, endIndex, replacement.getSection(), replacementIndex, replacementIndex + (endIndex - startIndex)));
}
@Override
public IPv4Address reverseBits(boolean perByte) {
return checkIdentity(getSection().reverseBits(perByte));
}
@Override
public IPv4Address reverseBytes() {
return checkIdentity(getSection().reverseBytes());
}
@Override
public IPv4Address reverseBytesPerSegment() {
return this;
}
@Override
public IPv4Address reverseSegments() {
return checkIdentity(getSection().reverseSegments());
}
private IPv4Address checkIdentity(IPv4AddressSection newSection) {
IPv4AddressSection section = getSection();
if(newSection == section) {
return this;
}
return getAddressCreator().createAddress(newSection);
}
@Override
public IPv4Address adjustPrefixBySegment(boolean nextSegment) {
return checkIdentity(getSection().adjustPrefixBySegment(nextSegment));
}
@Override
public IPv4Address adjustPrefixBySegment(boolean nextSegment, boolean zeroed) {
return checkIdentity(getSection().adjustPrefixBySegment(nextSegment, zeroed));
}
@Override
public IPv4Address adjustPrefixLength(int adjustment) {
return checkIdentity(getSection().adjustPrefixLength(adjustment));
}
@Override
public IPv4Address adjustPrefixLength(int adjustment, boolean zeroed) {
return checkIdentity(getSection().adjustPrefixLength(adjustment, zeroed));
}
@Override
public IPv4Address setPrefixLength(int prefixLength) {
return setPrefixLength(prefixLength, true);
}
@Override
public IPv4Address setPrefixLength(int prefixLength, boolean zeroed) {
return checkIdentity(getSection().setPrefixLength(prefixLength, zeroed));
}
@Override
public IPv4Address setPrefixLength(int prefixLength, boolean zeroed, boolean zeroHostIsBlock) throws PrefixLenException {
return checkIdentity(getSection().setPrefixLength(prefixLength, zeroed, zeroHostIsBlock));
}
@Deprecated
@Override
public IPv4Address applyPrefixLength(int networkPrefixLength) throws PrefixLenException {
return checkIdentity(getSection().applyPrefixLength(networkPrefixLength));
}
@Override @Deprecated
public IPv4Address removePrefixLength(boolean zeroed) {
return checkIdentity(getSection().removePrefixLength(zeroed));
}
@Override
public IPv4Address withoutPrefixLength() {
return removePrefixLength(false);
}
@Override
@Deprecated
public IPv4Address removePrefixLength() {
return removePrefixLength(true);
}
@Override
public Iterator segmentsNonZeroHostIterator() {
return getSection().segmentsNonZeroHostIterator();
}
@Override
public Iterator segmentsIterator() {
return getSection().segmentsIterator();
}
@Override
public AddressComponentRangeSpliterator segmentsSpliterator() {
return getSection().segmentsSpliterator(this, getAddressCreator());
}
@Override
public Stream segmentsStream() {
return StreamSupport.stream(segmentsSpliterator(), false);
}
@Override
public Iterator iterator() {
return getSection().iterator(this, getAddressCreator(), null);
}
@Override
public AddressComponentSpliterator spliterator() {
return getSection().spliterator(this, getAddressCreator(), false);
}
@Override
public Stream stream() {
return StreamSupport.stream(spliterator(), false);
}
@Override
public Iterator nonZeroHostIterator() {
Predicate excludeFunc = null;
if(includesZeroHost()) {
int prefLength = getNetworkPrefixLength();
excludeFunc = s -> getSection().isZeroHost(s, prefLength);
}
return getSection().iterator(this, getAddressCreator(), excludeFunc);
}
@Override
public Iterator prefixBlockIterator() {
return getSection().prefixIterator(this, getAddressCreator(), true);
}
@Override
public AddressComponentSpliterator prefixBlockSpliterator() {
return getSection().prefixSpliterator(this, getAddressCreator(), true);
}
@Override
public Stream prefixBlockStream() {
return StreamSupport.stream(prefixBlockSpliterator(), false);
}
@Override
public Iterator prefixBlockIterator(int prefixLength) {
return getSection().prefixIterator(this, getAddressCreator(), true, prefixLength);
}
@Override
public AddressComponentSpliterator prefixBlockSpliterator(int prefixLength) {
return getSection().prefixSpliterator(this, getAddressCreator(), true, prefixLength);
}
@Override
public Stream prefixBlockStream(int prefixLength) {
return StreamSupport.stream(prefixBlockSpliterator(prefixLength), false);
}
@Override
public Iterator prefixIterator() {
return getSection().prefixIterator(this, getAddressCreator(), false);
}
@Override
public AddressComponentSpliterator prefixSpliterator() {
return getSection().prefixSpliterator(this, getAddressCreator(), false);
}
@Override
public Stream prefixStream() {
return StreamSupport.stream(prefixSpliterator(), false);
}
@Override
public Iterator prefixIterator(int prefixLength) {
return getSection().prefixIterator(this, getAddressCreator(), false, prefixLength);
}
@Override
public AddressComponentSpliterator prefixSpliterator(int prefixLength) {
return getSection().prefixSpliterator(this, getAddressCreator(), false, prefixLength);
}
@Override
public Stream prefixStream(int prefixLength) {
return StreamSupport.stream(prefixSpliterator(prefixLength), false);
}
@Override
public Iterator blockIterator(int segmentCount) {
return getSection().blockIterator(this, getAddressCreator(), segmentCount);
}
@Override
public AddressComponentSpliterator blockSpliterator(int segmentCount) {
return getSection().blockSpliterator(this, getAddressCreator(), segmentCount);
}
@Override
public Stream blockStream(int segmentCount) {
return StreamSupport.stream(blockSpliterator(segmentCount), false);
}
@SuppressWarnings("unchecked")
@Override
public Iterator sequentialBlockIterator() {
return (Iterator) super.sequentialBlockIterator();
}
@SuppressWarnings("unchecked")
@Override
public AddressComponentSpliterator sequentialBlockSpliterator() {
return (AddressComponentSpliterator) super.sequentialBlockSpliterator();
}
@SuppressWarnings("unchecked")
@Override
public Stream sequentialBlockStream() {
return (Stream) super.sequentialBlockStream();
}
@Override
public Iterable getIterable() {
return this;
}
@Override
public IPv4Address increment(long increment) {
return checkIdentity(getSection().increment(increment));
}
@Override
public IPv4Address incrementBoundary(long increment) {
return checkIdentity(getSection().incrementBoundary(increment));
}
IPv4AddressCreator getAddressCreator() {
return getNetwork().getAddressCreator();
}
@Override
public IPv4AddressNetwork getNetwork() {
return defaultIpv4Network();
}
/**
* Returns the IPv6 network used by {@link #getIPv4MappedAddress()} and {@link #getIPv6Address(IPv6AddressSegment[])}
*
* @return
*/
public IPv6AddressNetwork getIPv6Network() {
return defaultIpv6Network();
}
@Override
protected IPv4Address convertArg(IPAddress arg) throws AddressConversionException {
IPv4Address converted = arg.toIPv4();
if(converted == null) {
throw new AddressConversionException(this, arg);
}
return converted;
}
@Override
public IPv4Address intersect(IPAddress other) throws AddressConversionException {
IPv4AddressSection thisSection = getSection();
IPv4AddressSection section = thisSection.intersect(convertArg(other).getSection());
if(section == null) {
return null;
}
IPv4AddressCreator creator = getAddressCreator();
IPv4Address result = creator.createAddress(section); /* address creation */
return result;
}
@Override
public IPv4Address[] subtract(IPAddress other) throws AddressConversionException {
IPv4AddressSection thisSection = getSection();
IPv4AddressSection sections[] = thisSection.subtract(convertArg(other).getSection());
if(sections == null) {
return null;
}
IPv4AddressCreator creator = getAddressCreator();
IPv4Address result[] = new IPv4Address[sections.length];
for(int i = 0; i < result.length; i++) {
result[i] = creator.createAddress(sections[i]); /* address creation */
}
return result;
}
@Override
public IPv4Address toZeroHost() {
return toZeroHost(false);
}
@Override
protected IPv4Address toZeroHost(boolean boundariesOnly) {
if(!isPrefixed()) {
IPv4AddressNetwork network = getNetwork();
PrefixConfiguration config = network.getPrefixConfiguration();
IPv4Address addr = network.getNetworkMask(0, !config.allPrefixedAddressesAreSubnets());
if(config.zeroHostsAreSubnets()) {
addr = addr.getLower();
}
return addr;
}
if(includesZeroHost() && isSingleNetwork()) {
return getLower();//cached
}
return checkIdentity(getSection().createZeroHost(boundariesOnly));
}
@Override
public IPv4Address toZeroHost(int prefixLength) {
if(isPrefixed() && prefixLength == getNetworkPrefixLength()) {
return toZeroHost();
}
return checkIdentity(getSection().toZeroHost(prefixLength));
}
@Override
public IPv4Address toZeroNetwork() {
if(!isPrefixed()) {
return getNetwork().getHostMask(getBitCount());
}
return checkIdentity(getSection().createZeroNetwork());
}
@Override
public IPv4Address toMaxHost() {
if(!isPrefixed()) {
IPv4Address resultNoPrefix = getNetwork().getHostMask(0);
if(getNetwork().getPrefixConfiguration().allPrefixedAddressesAreSubnets()) {
return resultNoPrefix;
}
return resultNoPrefix.setPrefixLength(0);
}
if(includesMaxHost() && isSingleNetwork()) {
return getUpper();//cached
}
return checkIdentity(getSection().createMaxHost());
}
@Override
public IPv4Address toMaxHost(int prefixLength) {
if(isPrefixed() && prefixLength == getNetworkPrefixLength()) {
return toMaxHost();
}
return checkIdentity(getSection().toMaxHost(prefixLength));
}
@Override
public IPv4Address mask(IPAddress mask, boolean retainPrefix) throws IncompatibleAddressException, AddressConversionException {
return checkIdentity(getSection().mask(convertArg(mask).getSection(), retainPrefix));
}
@Override
public IPv4Address mask(IPAddress mask) throws IncompatibleAddressException, AddressConversionException {
return mask(mask, false);
}
@Override
public IPv4Address maskNetwork(IPAddress mask, int networkPrefixLength) throws IncompatibleAddressException, PrefixLenException, AddressConversionException {
return checkIdentity(getSection().maskNetwork(convertArg(mask).getSection(), networkPrefixLength));
}
@Override
public IPv4Address bitwiseOr(IPAddress mask, boolean retainPrefix) throws IncompatibleAddressException, AddressConversionException {
return checkIdentity(getSection().bitwiseOr(convertArg(mask).getSection(), retainPrefix));
}
@Override
public IPv4Address bitwiseOr(IPAddress mask) throws IncompatibleAddressException, AddressConversionException {
return bitwiseOr(mask, false);
}
@Override
public IPv4Address bitwiseOrNetwork(IPAddress mask, int networkPrefixLength) throws IncompatibleAddressException, PrefixLenException, AddressConversionException {
return checkIdentity(getSection().bitwiseOrNetwork(convertArg(mask).getSection(), networkPrefixLength));
}
@Override
public IPv4Address getHostMask() {
return (IPv4Address) super.getHostMask();
}
@Override
public IPv4Address getNetworkMask() {
return (IPv4Address) super.getNetworkMask();
}
@Override
public IPv4AddressSection getNetworkSection() {
return getSection().getNetworkSection();
}
@Override
public IPv4AddressSection getNetworkSection(int networkPrefixLength) throws PrefixLenException {
return getSection().getNetworkSection(networkPrefixLength);
}
@Override
public IPv4AddressSection getNetworkSection(int networkPrefixLength, boolean withPrefixLength) throws PrefixLenException {
return getSection().getNetworkSection(networkPrefixLength, withPrefixLength);
}
@Override
public IPv4AddressSection getHostSection() {
return getSection().getHostSection();
}
@Override
public IPv4AddressSection getHostSection(int networkPrefixLength) throws PrefixLenException {
return getSection().getHostSection(networkPrefixLength);
}
@Override
public IPv4Address toPrefixBlock() {
Integer prefixLength = getNetworkPrefixLength();
if(prefixLength == null || getNetwork().getPrefixConfiguration().allPrefixedAddressesAreSubnets()) {
return this;
}
return toPrefixBlock(prefixLength);
}
@Override
public IPv4Address toPrefixBlock(int networkPrefixLength) throws PrefixLenException {
return checkIdentity(getSection().toPrefixBlock(networkPrefixLength));
}
@Override
public IPv4Address assignPrefixForSingleBlock() {
return (IPv4Address) super.assignPrefixForSingleBlock();
}
@Override
public IPv4Address assignMinPrefixForBlock() {
return (IPv4Address) super.assignMinPrefixForBlock();
}
@Override
public IPv4Address coverWithPrefixBlock() {
return (IPv4Address) IPv4AddressSection.coverWithPrefixBlock(this, getLower(), getUpper());
}
@Override
public IPv4Address coverWithPrefixBlock(IPAddress other) throws AddressConversionException {
return IPv4AddressSection.coverWithPrefixBlock(
this,
convertArg(other),
IPv4Address::getLower,
IPv4Address::getUpper,
Address.ADDRESS_LOW_VALUE_COMPARATOR::compare);
}
/**
* Produces an array of prefix blocks that cover the same set of addresses as this.
*
* Unlike {@link #spanWithPrefixBlocks(IPAddress)} this method only includes addresses that are a part of this subnet.
*/
@Override
public IPv4Address[] spanWithPrefixBlocks() {
if(isSequential()) {
if(isSinglePrefixBlock()) {
return new IPv4Address[] {this};
}
return spanWithPrefixBlocks(this);
}
@SuppressWarnings("unchecked")
ArrayList list = (ArrayList) spanWithBlocks(true);
return list.toArray(new IPv4Address[list.size()]);
}
@Override
public IPv4Address[] spanWithPrefixBlocks(IPAddress other) throws AddressConversionException {
return IPAddress.getSpanningPrefixBlocks(
this,
convertArg(other),
IPv4Address::getLower,
IPv4Address::getUpper,
Address.ADDRESS_LOW_VALUE_COMPARATOR::compare,
IPv4Address::assignPrefixForSingleBlock,
IPv4Address::withoutPrefixLength,
getAddressCreator()::createAddressArray);
}
/**
* Produces an array of blocks that are sequential that cover the same set of addresses as this.
*
* This array can be shorter than that produced by {@link #spanWithPrefixBlocks()} and is never longer.
*
* Unlike {@link #spanWithSequentialBlocks(IPAddress)} this method only includes addresses that are a part of this subnet.
*/
@Override
public IPv4Address[] spanWithSequentialBlocks() throws AddressConversionException {
if(isSequential()) {
return new IPv4Address[] { withoutPrefixLength() };
}
@SuppressWarnings("unchecked")
ArrayList list = (ArrayList) spanWithBlocks(false);
return list.toArray(new IPv4Address[list.size()]);
}
@Override
public IPv4Address[] spanWithSequentialBlocks(IPAddress other) throws AddressConversionException {
return IPAddress.getSpanningSequentialBlocks(
this,
convertArg(other),
IPv4Address::getLower,
IPv4Address::getUpper,
Address.ADDRESS_LOW_VALUE_COMPARATOR::compare,
IPv4Address::withoutPrefixLength,
getAddressCreator());
}
@Override
public IPv4AddressSeqRange spanWithRange(IPAddress other) throws AddressConversionException {
return toSequentialRange(other);
}
@Override
public IPv4Address[] mergeToPrefixBlocks(IPAddress ...addresses) throws AddressConversionException {
if(addresses.length == 0) {
if(isSinglePrefixBlock()) {
return new IPv4Address[] {this};
}
}
IPAddress[] converted = getConverted(addresses);
List blocks = getMergedPrefixBlocks(converted);
return blocks.toArray(new IPv4Address[blocks.size()]);
}
private IPAddress[] getConverted(IPAddress... addresses) {
IPAddress converted[] = new IPAddress[addresses.length + 1];
for(int i = 0, j = 1; i < addresses.length; i = j++) {
converted[j] = convertArg(addresses[i]);
}
converted[0] = this;
return converted;
}
@Override
public IPv4Address[] mergeToSequentialBlocks(IPAddress ...addresses) throws AddressConversionException {
if(addresses.length == 0) {
if(isSequential()) {
return new IPv4Address[] {this};
}
}
IPAddress[] converted = getConverted(addresses);
List blocks = getMergedSequentialBlocks(converted, getAddressCreator());
return blocks.toArray(new IPv4Address[blocks.size()]);
}
@Override
public Inet4Address toUpperInetAddress() {
return (Inet4Address) super.toUpperInetAddress();
}
@Override
public Inet4Address toInetAddress() {
return (Inet4Address) super.toInetAddress();
}
@Override
@Deprecated
public IPv4AddressSeqRange toSequentialRange(IPAddress other) {
return new IPv4AddressSeqRange(this, convertArg(other));
}
@Override
public IPv4AddressSeqRange toSequentialRange() {
IPv4Address thiz = withoutPrefixLength();
return new IPv4AddressSeqRange(thiz.getLower(), thiz.getUpper(), true);
}
@Override
public boolean isLocal() {
if(isMulticast()) {
//1110...
IPv4AddressSegment seg0 = getSegment(0);
//http://www.tcpipguide.com/free/t_IPMulticastAddressing.htm
//rfc4607 and https://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml
//239.0.0.0-239.255.255.255 organization local
if(seg0.matches(239)) {
return true;
}
IPv4AddressSegment seg1 = getSegment(1), seg2 = getSegment(2);
return
// 224.0.0.0 to 224.0.0.255 local
// includes link local multicast name resolution https://tools.ietf.org/html/rfc4795 224.0.0.252
(seg0.matches(224) && seg1.isZero() && seg2.isZero())
//232.0.0.1 - 232.0.0.255 Reserved for IANA allocation [RFC4607]
//232.0.1.0 - 232.255.255.255 Reserved for local host allocation [RFC4607]
|| (seg0.matches(232) && !(seg1.isZero() && seg2.isZero()));
}
return isLinkLocal() || isPrivate() || isAnyLocal();
}
/**
* @see java.net.InetAddress#isLinkLocalAddress()
*/
@Override
public boolean isLinkLocal() {
if(isMulticast()) {
//224.0.0.252 Link-local Multicast Name Resolution [RFC4795]
return getSegment(0).matches(224) && getSegment(1).isZero() && getSegment(2).isZero() && getSegment(3).matches(252);
}
return getSegment(0).matches(169) && getSegment(1).matches(254);
}
/**
* Unicast addresses allocated for private use
*
* @see java.net.InetAddress#isSiteLocalAddress()
*/
public boolean isPrivate() {
// refer to RFC 1918
// 10/8 prefix
// 172.16/12 prefix (172.16.0.0 – 172.31.255.255)
// 192.168/16 prefix
IPv4AddressSegment seg0 = getSegment(0);
IPv4AddressSegment seg1 = getSegment(1);
return seg0.matches(10)
|| (seg0.matches(172) && seg1.matchesWithPrefixMask(16, 4))
|| (seg0.matches(192) && seg1.matches(168));
}
@Override
public boolean isMulticast() {
// 1110...
//224.0.0.0/4
return getSegment(0).matchesWithPrefixMask(0xe0, 4);
}
/**
* @see java.net.InetAddress#isLoopbackAddress()
*/
@Override
public boolean isLoopback() {
return getSegment(0).matches(127);
}
/**
* @custom.core
* @author sfoley
*
*/
public interface IPv4AddressConverter {
/**
* If the given address is IPv4, or can be converted to IPv4, returns that {@link IPv4Address}. Otherwise, returns null.
*/
IPv4Address toIPv4(IPAddress address);
}
////////////////string creation below ///////////////////////////////////////////////////////////////////////////////////////////
@Override
protected IPAddressStringParameters createFromStringParams() {
return new IPAddressStringParameters.Builder().
getIPv4AddressParametersBuilder().setNetwork(getNetwork()).getParentBuilder().
getIPv6AddressParametersBuilder().setNetwork(getIPv6Network()).getParentBuilder().toParams();
}
/**
* Creates the normalized string for an address without having to create the address objects first.
*
* @param lowerValueProvider
* @param upperValueProvider
* @param prefixLength
* @param network use {@link #defaultIpv4Network()} if there is no custom network in use
* @return
*/
public static String toNormalizedString(IPv4AddressNetwork network, SegmentValueProvider lowerValueProvider, SegmentValueProvider upperValueProvider, Integer prefixLength) {
return toNormalizedString(network.getPrefixConfiguration(), lowerValueProvider, upperValueProvider, prefixLength, SEGMENT_COUNT, BYTES_PER_SEGMENT, BITS_PER_SEGMENT, MAX_VALUE_PER_SEGMENT, SEGMENT_SEPARATOR, DEFAULT_TEXTUAL_RADIX, null);
}
/**
* @author sfoley
*
*/
public static enum inet_aton_radix {
OCTAL, HEX, DECIMAL;
int getRadix() {
if(this == OCTAL) {
return 8;
} else if(this == HEX) {
return 16;
}
return 10;
}
String getSegmentStrPrefix() {
if(this == OCTAL) {
return "0";
} else if(this == HEX) {
return "0x";
}
return null;
}
@Override
public String toString() {
if(this == OCTAL) {
return "octal";
} else if(this == HEX) {
return "hexadecimal";
}
return "decimal";
}
}
/**
* Returns a string like the inet_aton style string
* @return
*/
public String toInetAtonString(IPv4Address.inet_aton_radix radix) {
return getSection().toInetAtonString(radix);
}
public String toInetAtonString(IPv4Address.inet_aton_radix radix, int joinedCount) throws IncompatibleAddressException {
return getSection().toInetAtonString(radix, joinedCount);
}
@Override
public String toSegmentedBinaryString() {
return getSection().toSegmentedBinaryString();
}
@Override
public String toUNCHostName() {
return super.toCanonicalString();
}
@Override
public IPAddressPartStringCollection toStandardStringCollection() {
return toStringCollection(IPv4StringBuilderOptions.STANDARD_OPTS);
}
@Override
public IPAddressPartStringCollection toAllStringCollection() {
return toStringCollection(IPv4StringBuilderOptions.ALL_OPTS);
}
@Override
public IPAddressPartStringCollection toStringCollection(IPStringBuilderOptions opts) {
return toStringCollection(IPv4StringBuilderOptions.from(opts));
}
private IPv6Address getConverted(IPv4StringBuilderOptions opts) {
if(opts.includes(IPv4StringBuilderOptions.IPV6_CONVERSIONS)) {
IPv6AddressConverter converter = opts.converter;
return converter.toIPv6(this);
}
return null;
}
public IPAddressPartStringCollection toStringCollection(IPv4StringBuilderOptions opts) {
IPv4StringCollection coll = new IPv4StringCollection();
IPAddressPartStringCollection sectionColl = getSection().toStringCollection(opts);
coll.addAll(sectionColl);
IPv6Address ipv6Addr = getConverted(opts);
if(ipv6Addr != null) {
IPAddressPartStringCollection ipv6StringCollection = ipv6Addr.toStringCollection(opts.ipv6ConverterOptions);
coll.addAll(ipv6StringCollection);
}
return coll;
}
}