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 <weave@oculan.com> 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