blob: 1571cf62fba8afe5d11104d512b4619d00e834e3 [file] [log] [blame]
Pavlin Radoslavov9de27722014-10-23 20:31:15 -07001package org.onlab.packet;
2
3import java.nio.ByteBuffer;
4import static com.google.common.base.Preconditions.checkNotNull;
5
6/**
7 * The class representing an IPv4 address.
8 * This class is immutable.
9 */
10public final class Ip4Address implements Comparable<Ip4Address> {
11 private final int value;
12
13 /** The length of the address in bytes (octets). */
14 public static final int BYTE_LENGTH = 4;
15
16 /** The length of the address in bits. */
17 public static final int BIT_LENGTH = BYTE_LENGTH * Byte.SIZE;
18
19 /**
20 * Default constructor.
21 */
22 public Ip4Address() {
23 this.value = 0;
24 }
25
26 /**
27 * Copy constructor.
28 *
29 * @param other the object to copy from
30 */
31 public Ip4Address(Ip4Address other) {
32 this.value = other.value;
33 }
34
35 /**
36 * Constructor from an integer value.
37 *
38 * @param value the value to use
39 */
40 public Ip4Address(int value) {
41 this.value = value;
42 }
43
44 /**
45 * Constructor from a byte array with the IPv4 address stored in network
46 * byte order (i.e., the most significant byte first).
47 *
48 * @param value the value to use
49 */
50 public Ip4Address(byte[] value) {
51 this(value, 0);
52 }
53
54 /**
55 * Constructor from a byte array with the IPv4 address stored in network
56 * byte order (i.e., the most significant byte first), and a given offset
57 * from the beginning of the byte array.
58 *
59 * @param value the value to use
60 * @param offset the offset in bytes from the beginning of the byte array
61 */
62 public Ip4Address(byte[] value, int offset) {
63 checkNotNull(value);
64
65 // Verify the arguments
66 if ((offset < 0) || (offset + BYTE_LENGTH > value.length)) {
67 String msg;
68 if (value.length < BYTE_LENGTH) {
69 msg = "Invalid IPv4 address array: array length: " +
70 value.length + ". Must be at least " + BYTE_LENGTH;
71 } else {
72 msg = "Invalid IPv4 address array: array offset: " +
73 offset + ". Must be in the interval [0, " +
74 (value.length - BYTE_LENGTH) + "]";
75 }
76 throw new IllegalArgumentException(msg);
77 }
78
79 // Read the address
80 ByteBuffer bb = ByteBuffer.wrap(value);
81 this.value = bb.getInt(offset);
82 }
83
84 /**
85 * Constructs an IPv4 address from a string representation of the address.
86 *<p>
87 * Example: "1.2.3.4"
88 *
89 * @param value the value to use
90 */
91 public Ip4Address(String value) {
92 checkNotNull(value);
93
94 String[] splits = value.split("\\.");
95 if (splits.length != 4) {
96 final String msg = "Invalid IPv4 address string: " + value;
97 throw new IllegalArgumentException(msg);
98 }
99
100 int result = 0;
101 for (int i = 0; i < BYTE_LENGTH; i++) {
102 result |= Integer.parseInt(splits[i]) <<
103 ((BYTE_LENGTH - (i + 1)) * Byte.SIZE);
104 }
105 this.value = result;
106 }
107
108 /**
109 * Gets the IPv4 address as a byte array.
110 *
111 * @return a byte array with the IPv4 address stored in network byte order
112 * (i.e., the most significant byte first).
113 */
114 public byte[] toOctets() {
115 return ByteBuffer.allocate(BYTE_LENGTH).putInt(value).array();
116 }
117
118 /**
119 * Creates an IPv4 network mask prefix.
120 *
121 * @param prefixLen the length of the mask prefix. Must be in the interval
122 * [0, 32].
123 * @return a new IPv4 address that contains a mask prefix of the
124 * specified length
125 */
126 public static Ip4Address makeMaskPrefix(int prefixLen) {
127 // Verify the prefix length
128 if ((prefixLen < 0) || (prefixLen > Ip4Address.BIT_LENGTH)) {
129 final String msg = "Invalid IPv4 prefix length: " + prefixLen +
130 ". Must be in the interval [0, 32].";
131 throw new IllegalArgumentException(msg);
132 }
133
134 long v =
135 (0xffffffffL << (Ip4Address.BIT_LENGTH - prefixLen)) & 0xffffffffL;
136 return new Ip4Address((int) v);
137 }
138
139 /**
140 * Creates an IPv4 address by masking it with a network mask of given
141 * mask length.
142 *
143 * @param addr the address to mask
144 * @param prefixLen the length of the mask prefix. Must be in the interval
145 * [0, 32].
146 * @return a new IPv4 address that is masked with a mask prefix of the
147 * specified length
148 */
149 public static Ip4Address makeMaskedAddress(final Ip4Address addr,
150 int prefixLen) {
151 Ip4Address mask = Ip4Address.makeMaskPrefix(prefixLen);
152 long v = addr.value & mask.value;
153
154 return new Ip4Address((int) v);
155 }
156
157 /**
158 * Gets the value of the IPv4 address.
159 *
160 * @return the value of the IPv4 address
161 */
162 public int getValue() {
163 return value;
164 }
165
166 /**
167 * Converts the IPv4 value to a '.' separated string.
168 *
169 * @return the IPv4 value as a '.' separated string
170 */
171 @Override
172 public String toString() {
173 return ((this.value >> 24) & 0xff) + "." +
174 ((this.value >> 16) & 0xff) + "." +
175 ((this.value >> 8) & 0xff) + "." +
176 (this.value & 0xff);
177 }
178
179 @Override
180 public boolean equals(Object o) {
181 if (!(o instanceof Ip4Address)) {
182 return false;
183 }
184 Ip4Address other = (Ip4Address) o;
185 if (this.value != other.value) {
186 return false;
187 }
188 return true;
189 }
190
191 @Override
192 public int hashCode() {
193 return this.value;
194 }
195
196 @Override
197 public int compareTo(Ip4Address o) {
198 Long lv = ((long) this.value) & 0xffffffffL;
199 Long rv = ((long) o.value) & 0xffffffffL;
200 return lv.compareTo(rv);
201 }
202}