blob: 6d5d9e1e213c4b6c1adeab6af92c613f5dc8cd5a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
*
* 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 org.onlab.packet;
import java.nio.ByteBuffer;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* The class representing an IPv4 address.
* This class is immutable.
*/
public final class Ip4Address implements Comparable<Ip4Address> {
private final int value;
/** The length of the address in bytes (octets). */
public static final int BYTE_LENGTH = 4;
/** The length of the address in bits. */
public static final int BIT_LENGTH = BYTE_LENGTH * Byte.SIZE;
/**
* Default constructor.
*/
public Ip4Address() {
this.value = 0;
}
/**
* Copy constructor.
*
* @param other the object to copy from
*/
public Ip4Address(Ip4Address other) {
this.value = other.value;
}
/**
* Constructor from an integer value.
*
* @param value the value to use
*/
public Ip4Address(int value) {
this.value = value;
}
/**
* Constructor from a byte array with the IPv4 address stored in network
* byte order (i.e., the most significant byte first).
*
* @param value the value to use
*/
public Ip4Address(byte[] value) {
this(value, 0);
}
/**
* Constructor from a byte array with the IPv4 address stored in network
* byte order (i.e., the most significant byte first), and a given offset
* from the beginning of the byte array.
*
* @param value the value to use
* @param offset the offset in bytes from the beginning of the byte array
*/
public Ip4Address(byte[] value, int offset) {
checkNotNull(value);
// Verify the arguments
if ((offset < 0) || (offset + BYTE_LENGTH > value.length)) {
String msg;
if (value.length < BYTE_LENGTH) {
msg = "Invalid IPv4 address array: array length: " +
value.length + ". Must be at least " + BYTE_LENGTH;
} else {
msg = "Invalid IPv4 address array: array offset: " +
offset + ". Must be in the interval [0, " +
(value.length - BYTE_LENGTH) + "]";
}
throw new IllegalArgumentException(msg);
}
// Read the address
ByteBuffer bb = ByteBuffer.wrap(value);
this.value = bb.getInt(offset);
}
/**
* Constructs an IPv4 address from a string representation of the address.
*<p>
* Example: "1.2.3.4"
*
* @param value the value to use
*/
public Ip4Address(String value) {
checkNotNull(value);
String[] splits = value.split("\\.");
if (splits.length != 4) {
final String msg = "Invalid IPv4 address string: " + value;
throw new IllegalArgumentException(msg);
}
int result = 0;
for (int i = 0; i < BYTE_LENGTH; i++) {
result |= Integer.parseInt(splits[i]) <<
((BYTE_LENGTH - (i + 1)) * Byte.SIZE);
}
this.value = result;
}
/**
* Gets the IPv4 address as a byte array.
*
* @return a byte array with the IPv4 address stored in network byte order
* (i.e., the most significant byte first).
*/
public byte[] toOctets() {
return ByteBuffer.allocate(BYTE_LENGTH).putInt(value).array();
}
/**
* Creates an IPv4 network mask prefix.
*
* @param prefixLen the length of the mask prefix. Must be in the interval
* [0, 32].
* @return a new IPv4 address that contains a mask prefix of the
* specified length
*/
public static Ip4Address makeMaskPrefix(int prefixLen) {
// Verify the prefix length
if ((prefixLen < 0) || (prefixLen > Ip4Address.BIT_LENGTH)) {
final String msg = "Invalid IPv4 prefix length: " + prefixLen +
". Must be in the interval [0, 32].";
throw new IllegalArgumentException(msg);
}
long v =
(0xffffffffL << (Ip4Address.BIT_LENGTH - prefixLen)) & 0xffffffffL;
return new Ip4Address((int) v);
}
/**
* Creates an IPv4 address by masking it with a network mask of given
* mask length.
*
* @param addr the address to mask
* @param prefixLen the length of the mask prefix. Must be in the interval
* [0, 32].
* @return a new IPv4 address that is masked with a mask prefix of the
* specified length
*/
public static Ip4Address makeMaskedAddress(final Ip4Address addr,
int prefixLen) {
Ip4Address mask = Ip4Address.makeMaskPrefix(prefixLen);
long v = addr.value & mask.value;
return new Ip4Address((int) v);
}
/**
* Gets the value of the IPv4 address.
*
* @return the value of the IPv4 address
*/
public int getValue() {
return value;
}
/**
* Converts the IPv4 value to a '.' separated string.
*
* @return the IPv4 value as a '.' separated string
*/
@Override
public String toString() {
return ((this.value >> 24) & 0xff) + "." +
((this.value >> 16) & 0xff) + "." +
((this.value >> 8) & 0xff) + "." +
(this.value & 0xff);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof Ip4Address)) {
return false;
}
Ip4Address other = (Ip4Address) o;
if (this.value != other.value) {
return false;
}
return true;
}
@Override
public int hashCode() {
return this.value;
}
@Override
public int compareTo(Ip4Address o) {
Long lv = ((long) this.value) & 0xffffffffL;
Long rv = ((long) o.value) & 0xffffffffL;
return lv.compareTo(rv);
}
}