1 //
2 // This file is part of the OpenNMS(R) Application.
3 //
4 // OpenNMS(R) is Copyright (C) 2002-2003 The OpenNMS Group, Inc.  All rights reserved.
5 // OpenNMS(R) is a derivative work, containing both original code, included code and modified
6 // code that was published under the GNU General Public License. Copyrights for modified
7 // and included code are below.
8 //
9 // OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
10 //
11 // Modifications:
12 //
13 // 2003 Aug 21: Changes to support ScriptD.
14 //
15 // Original code base Copyright (C) 1999-2001 Oculan Corp.  All rights reserved.
16 //
17 // This program is free software; you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation; either version 2 of the License, or
20 // (at your option) any later version.
21 //
22 // This program is distributed in the hope that it will be useful,
23 // but WITHOUT ANY WARRANTY; without even the implied warranty of
24 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 // GNU General Public License for more details.
26 //
27 // You should have received a copy of the GNU General Public License
28 // along with this program; if not, write to the Free Software
29 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 //
31 // For more information contact:
32 //      OpenNMS Licensing       <license@opennms.org>
33 //      http://www.opennms.org/
34 //      http://www.opennms.com/
35 //
36 
37 package org.opennms.protocols.ip;
38 
39 import java.io.Serializable;
40 import java.net.InetAddress;
41 import java.util.StringTokenizer;
42 
43 /**
44  * Represents an Internet Protocol version 4 address. An IPv4 address is a
45  * 32-bit address that can be considered four eight bit octets. Each octet
46  * represents a number in the range of [0..256). A string representation is a
47  * dotted decimal address in the form of "xxx.xxx.xxx.xxx" where xxx is a single
48  * octet.
49  *
50  * The main purpose of the class is to represent an IPv4 Address without the
51  * associated lookup baggage in the java.net.InetAddress class.
52  *
53  *
54  * @author Brian Weaver &lt;weave@oculan.com&gt;
55  */
56 public class IPv4Address extends Object implements Serializable {
57     static final long serialVersionUID = 1946711645921732057L; // generated by
58                                                                 // serialver
59                                                                 // tool
60 
61     private byte[] m_addr; // 4 byte address
62 
63     /**
64      * Duplicates the array of bytes.
65      *
66      * @param src
67      *            The source bytes to duplicate.
68      *
69      * @return The duplicated array of bytes.
70      */
dup(byte[] src)71     private byte[] dup(byte[] src) {
72         byte[] cpy = null;
73         if (src != null) {
74             cpy = new byte[src.length];
75             for (int x = 0; x < src.length; x++) {
76                 cpy[x] = src[x];
77             }
78         }
79         return cpy;
80     }
81 
82     /**
83      * Converts a byte to an integer, treating the byte as unsigned.
84      *
85      * @param b
86      *            The byte to convert.
87      *
88      * @return The converted value.
89      *
90      */
byteToInt(byte b)91     private static int byteToInt(byte b) {
92         int r = (int) b;
93         if (r < 0)
94             r += 256;
95         return r;
96     }
97 
98     /**
99      * Converts the passed 32-bit IPv4 address to a dotted decimal IP address
100      * string.
101      *
102      * @param ipv4Addr
103      *            The 32-bit address
104      *
105      * @return The dotted decimal address in the format "xxx.xxx.xxx.xxx" where
106      *         0 <= xxx < 256
107      *
108      */
addressToString(int ipv4Addr)109     public static String addressToString(int ipv4Addr) {
110         StringBuffer buf = new StringBuffer();
111         buf.append((ipv4Addr >> 24) & 0xff);
112         buf.append('.');
113         buf.append((ipv4Addr >> 16) & 0xff);
114         buf.append('.');
115         buf.append((ipv4Addr >> 8) & 0xff);
116         buf.append('.');
117         buf.append(ipv4Addr & 0xff);
118 
119         return buf.toString();
120     }
121 
122     /**
123      * Converts the passed IPv4 address buffer to a dotted decimal IP address
124      * string.
125      *
126      * @param buf
127      *            The 4 byte buffer
128      *
129      * @return The dotted decimal address in the format "xxx.xxx.xxx.xxx" where
130      *         0 <= xxx < 256
131      *
132      * @exception IllegalArgumentException
133      *                Thrown if the buffer is not exactly 4 bytes in length.
134      */
addressToString(byte[] buf)135     public static String addressToString(byte[] buf) {
136         if (buf.length != 4)
137             throw new IllegalArgumentException("IPv4 Address must be 4-bytes in length");
138 
139         int a = byteToInt(buf[0]);
140         int b = byteToInt(buf[1]);
141         int c = byteToInt(buf[2]);
142         int d = byteToInt(buf[3]);
143 
144         StringBuffer sbuf = new StringBuffer();
145         sbuf.append(a).append('.').append(b).append('.').append(c).append('.').append(d);
146 
147         return sbuf.toString();
148     }
149 
150     /**
151      * Constructs a new IPv4Address object. The default value for the object is
152      * "0.0.0.0"
153      *
154      */
IPv4Address()155     public IPv4Address() {
156         m_addr = new byte[4];
157         m_addr[0] = 0;
158         m_addr[1] = 0;
159         m_addr[2] = 0;
160         m_addr[3] = 0;
161     }
162 
163     /**
164      * Constructs a new address object based upon the value of the first object.
165      *
166      * @param second
167      *            The object to copy the address from.
168      */
IPv4Address(IPv4Address second)169     public IPv4Address(IPv4Address second) {
170         m_addr = dup(second.m_addr);
171     }
172 
173     /**
174      * Constructs a new object based on the value stored in the passed array. An
175      * IPv4 Address is 32-bits in length, thus the array must have exactly 4
176      * elements.
177      *
178      * @param addr
179      *            The IPv4Address data
180      *
181      * @exception IllegalArgumentException
182      *                Thrown if the passed buffer is not in the correct format
183      *                for an IPv4Address.
184      *
185      */
IPv4Address(byte[] addr)186     public IPv4Address(byte[] addr) {
187         if (addr.length != 4)
188             throw new IllegalArgumentException("Invalid address length");
189 
190         m_addr = dup(addr);
191     }
192 
193     /**
194      * Constructs a new address object based on the 32-bit passed value. The
195      * 32-bit integer is split into four eight bit values that represent the
196      * IPv4 address.
197      *
198      * @param ipv4Addr
199      *            The 32-bit IP address.
200      *
201      */
IPv4Address(int ipv4Addr)202     public IPv4Address(int ipv4Addr) {
203         m_addr = new byte[4];
204         m_addr[0] = (byte) (ipv4Addr >>> 24);
205         m_addr[1] = (byte) ((ipv4Addr >> 16) & 0xff);
206         m_addr[2] = (byte) ((ipv4Addr >> 8) & 0xff);
207         m_addr[3] = (byte) (ipv4Addr & 0xff);
208     }
209 
210     /**
211      * Creates a new object by decomposing the passed string into it four
212      * components. The string must be in the format of "xxx.xxx.xxx.xxx" where
213      * xxx is in the range of [0..256).
214      *
215      * @param ipv4Addr
216      *            The dotted decimal address.
217      *
218      * @exception IllegalArgumentException
219      *                Thrown if the string is a malformed dotted decimal
220      *                address.
221      *
222      */
IPv4Address(String ipv4Addr)223     public IPv4Address(String ipv4Addr) {
224         StringTokenizer tok = new StringTokenizer(ipv4Addr, ".");
225         if (tok.countTokens() != 4)
226             throw new IllegalArgumentException("Invalid Dotted Decimal IPv4 Address");
227         m_addr = new byte[4];
228 
229         int x;
230         for (x = 0; x < 4; x++) {
231             int converted = Integer.parseInt(tok.nextToken());
232             if (converted < 0 || converted > 255)
233                 throw new IllegalArgumentException("Invalid IPv4 Address string");
234 
235             m_addr[x] = (byte) (converted & 0xff);
236         }
237     }
238 
239     /**
240      * Creates a new IPv4Address from the passed InetAddress object.
241      *
242      * @param addr
243      *            The Internet Address containing the IPv4 address.
244      *
245      */
IPv4Address(InetAddress addr)246     public IPv4Address(InetAddress addr) {
247         m_addr = dup(addr.getAddress());
248     }
249 
250     /**
251      * Returns the 32-bit IPv4 address.
252      *
253      * @return 32-bit IPv4 address
254      *
255      */
getAddress()256     public int getAddress() {
257         int addr = byteToInt(m_addr[0]) << 24;
258         addr |= byteToInt(m_addr[1]) << 16;
259         addr |= byteToInt(m_addr[2]) << 8;
260         addr |= byteToInt(m_addr[3]);
261 
262         return addr;
263     }
264 
265     /**
266      * Returns the IPv4 address in the form of an array of 4 bytes
267      *
268      * @return the IPv4 address bytes
269      *
270      */
getAddressBytes()271     public byte[] getAddressBytes() {
272         return m_addr.clone();
273     }
274 
275     /**
276      * Sets the current address based upon the value of the passed object.
277      *
278      * @param second
279      *            The new address.
280      */
setAddress(IPv4Address second)281     public void setAddress(IPv4Address second) {
282         m_addr = dup(second.m_addr);
283     }
284 
285     /**
286      * Sets the object based on the value stored in the passed array. An IPv4
287      * Address is 32-bits in length, thus the array must have exactly 4
288      * elements.
289      *
290      * @param addr
291      *            The IPv4Address data
292      *
293      * @exception IllegalArgumentException
294      *                Thrown if the passed buffer is not in the correct format
295      *                for an IPv4Address.
296      *
297      */
setAddress(byte[] addr)298     public void setAddress(byte[] addr) {
299         if (addr.length != 4)
300             throw new IllegalArgumentException("Invalid address length");
301 
302         m_addr = dup(addr);
303     }
304 
305     /**
306      * Sets the address object based on the 32-bit passed value. The 32-bit
307      * integer is split into four eight bit values that represent the IPv4
308      * address.
309      *
310      * @param ipv4Addr
311      *            The 32-bit IP address.
312      *
313      */
setAddress(int ipv4Addr)314     public void setAddress(int ipv4Addr) {
315         m_addr = new byte[4];
316         m_addr[0] = (byte) (ipv4Addr >>> 24);
317         m_addr[1] = (byte) ((ipv4Addr >> 16) & 0xff);
318         m_addr[2] = (byte) ((ipv4Addr >> 8) & 0xff);
319         m_addr[3] = (byte) (ipv4Addr & 0xff);
320     }
321 
322     /**
323      * Sets the object by decomposing the passed string into it four components.
324      * The string must be in the format of "xxx.xxx.xxx.xxx" where xxx is in the
325      * range of [0..256).
326      *
327      * @param ipv4Addr
328      *            The dotted decimal address.
329      *
330      * @exception IllegalArgumentException
331      *                Thrown if the string is a malformed dotted decimal
332      *                address.
333      *
334      */
setAddress(String ipv4Addr)335     public void setAddress(String ipv4Addr) {
336         StringTokenizer tok = new StringTokenizer(ipv4Addr, ".");
337         if (tok.countTokens() != 4)
338             throw new IllegalArgumentException("Invalid Dotted Decimal IPv4 Address");
339         m_addr = new byte[4];
340 
341         int x;
342         for (x = 0; x < 4; x++) {
343             int converted = Integer.parseInt(tok.nextToken());
344             if (converted < 0 || converted > 255)
345                 throw new IllegalArgumentException("Invalid IPv4 Address string");
346 
347             m_addr[x] = (byte) (converted & 0xff);
348         }
349     }
350 
351     /**
352      * Sets the IPv4Address from the passed InetAddress object.
353      *
354      * @param addr
355      *            The Internet Address containing the IPv4 address.
356      *
357      */
setAddress(InetAddress addr)358     public void setAddress(InetAddress addr) {
359         m_addr = dup(addr.getAddress());
360     }
361 
362     /**
363      * Test to determine if the passed object is equal to self. The object may
364      * be an Integer, String, or IPv4Address. If the object is a String then it
365      * must be in the dotted decimal string format.
366      *
367      * @param obj
368      *            The object to use in the comparison.
369      *
370      * @return True if equal, false if not equal.
371      */
equals(Object obj)372     public boolean equals(Object obj) {
373         boolean bRC = false;
374 
375         if (obj instanceof IPv4Address) {
376             byte[] t = ((IPv4Address) obj).m_addr;
377             int x;
378 
379             bRC = true;
380             for (x = 0; x < 4; x++) {
381                 if (m_addr[x] != t[x]) {
382                     bRC = false;
383                 }
384             }
385         } else if (obj instanceof Integer) {
386             if (((Integer) obj).intValue() == getAddress()) {
387                 bRC = true;
388             }
389         } else if (obj instanceof String) {
390             try {
391                 IPv4Address addr = new IPv4Address((String) obj);
392                 bRC = this.equals(addr);
393             } catch (IllegalArgumentException e) {
394                 bRC = false;
395             }
396         }
397 
398         return bRC;
399     }
400 
401     /**
402      * If you override equals() you need to make a hashCode implementation as well
403      */
hashCode()404     public int hashCode() {
405     	return toString().hashCode();
406     }
407 
408     /**
409      * Converts the object to a string and returns the string to the caller.
410      *
411      * @return The dotted decimal string for the address
412      *
413      */
toString()414     public String toString() {
415         return addressToString(m_addr);
416     }
417 
418 }
419