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