GNU Classpath (0.20) | |
Frames | No Frames |
1: /* InetAddress.java -- Class to model an Internet address 2: Copyright (C) 1998, 1999, 2002, 2004, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.net; 40: 41: import java.io.IOException; 42: import java.io.ObjectInputStream; 43: import java.io.ObjectOutputStream; 44: import java.io.ObjectStreamException; 45: import java.io.Serializable; 46: import java.util.StringTokenizer; 47: 48: /** 49: * This class models an Internet address. It does not have a public 50: * constructor. Instead, new instances of this objects are created 51: * using the static methods getLocalHost(), getByName(), and 52: * getAllByName(). 53: * 54: * <p>This class fulfills the function of the C style functions gethostname(), 55: * gethostbyname(), and gethostbyaddr(). It resolves Internet DNS names 56: * into their corresponding numeric addresses and vice versa.</p> 57: * 58: * @author Aaron M. Renn (arenn@urbanophile.com) 59: * @author Per Bothner 60: * 61: * @specnote This class is not final since JK 1.4 62: */ 63: public class InetAddress implements Serializable 64: { 65: private static final long serialVersionUID = 3286316764910316507L; 66: 67: /** 68: * The special IP address INADDR_ANY. 69: */ 70: private static InetAddress inaddr_any; 71: 72: /** 73: * Dummy InetAddress, used to bind socket to any (all) network interfaces. 74: */ 75: static InetAddress ANY_IF; 76: 77: /** 78: * Stores static localhost address object. 79: */ 80: static InetAddress LOCALHOST; 81: 82: static 83: { 84: // precompute the ANY_IF address 85: try 86: { 87: ANY_IF = getInaddrAny(); 88: 89: byte[] ip_localhost = { 127, 0, 0, 1 }; 90: LOCALHOST = new Inet4Address(ip_localhost, "localhost"); 91: } 92: catch (UnknownHostException uhe) 93: { 94: // Hmmm, make one up and hope that it works. 95: byte[] zeros = { 0, 0, 0, 0 }; 96: ANY_IF = new Inet4Address(zeros, "0.0.0.0"); 97: } 98: } 99: 100: /** 101: * The Serialized Form specifies that an int 'address' is saved/restored. 102: * This class uses a byte array internally so we'll just do the conversion 103: * at serialization time and leave the rest of the algorithm as is. 104: */ 105: private int address; 106: 107: /** 108: * An array of octets representing an IP address. 109: */ 110: transient byte[] addr; 111: 112: /** 113: * The name of the host for this address. 114: */ 115: String hostName; 116: 117: /** 118: * The field 'family' seems to be the AF_ value. 119: * FIXME: Much of the code in the other java.net classes does not make 120: * use of this family field. A better implementation would be to make 121: * use of getaddrinfo() and have other methods just check the family 122: * field rather than examining the length of the address each time. 123: */ 124: int family; 125: 126: /** 127: * Initializes this object's addr instance variable from the passed in 128: * byte array. Note that this constructor is protected and is called 129: * only by static methods in this class. 130: * 131: * @param ipaddr The IP number of this address as an array of bytes 132: * @param hostname The hostname of this IP address. 133: */ 134: InetAddress(byte[] ipaddr, String hostname) 135: { 136: addr = (null == ipaddr) ? null : (byte[]) ipaddr.clone(); 137: hostName = hostname; 138: 139: family = 2; /* AF_INET */ 140: } 141: 142: /** 143: * Returns true if this address is a multicast address, false otherwise. 144: * An address is multicast if the high four bits are "1110". These are 145: * also known as "Class D" addresses. 146: * 147: * @return true if mulitcast, false if not 148: * 149: * @since 1.1 150: */ 151: public boolean isMulticastAddress() 152: { 153: // Mask against high order bits of 1110 154: if (addr.length == 4) 155: return (addr[0] & 0xf0) == 0xe0; 156: 157: return false; 158: } 159: 160: /** 161: * Utility routine to check if the InetAddress in a wildcard address 162: * 163: * @since 1.4 164: */ 165: public boolean isAnyLocalAddress() 166: { 167: // This is the IPv4 implementation. 168: // Any class derived from InetAddress should override this. 169: return equals(ANY_IF); 170: } 171: 172: /** 173: * Utility routine to check if the InetAddress is a loopback address 174: * 175: * @since 1.4 176: */ 177: public boolean isLoopbackAddress() 178: { 179: // This is the IPv4 implementation. 180: // Any class derived from InetAddress should override this. 181: return (addr[0] & 0xff) == 0x7f; 182: } 183: 184: /** 185: * Utility routine to check if InetAddress is a link local address 186: * 187: * @since 1.4 188: */ 189: public boolean isLinkLocalAddress() 190: { 191: // This is the IPv4 implementation. 192: // Any class derived from InetAddress should override this. 193: // XXX: This seems to not exist with IPv4 addresses 194: return false; 195: } 196: 197: /** 198: * Utility routine to check if InetAddress is a site local address 199: * 200: * @since 1.4 201: */ 202: public boolean isSiteLocalAddress() 203: { 204: // This is the IPv4 implementation. 205: // Any class derived from InetAddress should override this. 206: 207: // 10.0.0.0/8 208: if ((addr[0] & 0xff) == 0x0a) 209: return true; 210: 211: // 172.16.0.0/12 212: if ((addr[0] & 0xff) == 0xac && (addr[1] & 0xf0) == 0x10) 213: return true; 214: 215: // 192.168.0.0/16 216: if ((addr[0] & 0xff) == 0xc0 && (addr[1] & 0xff) == 0xa8) 217: return true; 218: 219: // XXX: Do we need to check more addresses here ? 220: return false; 221: } 222: 223: /** 224: * Utility routine to check if InetAddress is a global multicast address 225: * 226: * @since 1.4 227: */ 228: public boolean isMCGlobal() 229: { 230: // This is the IPv4 implementation. 231: // Any class derived from InetAddress should override this. 232: // XXX: This seems to not exist with IPv4 addresses 233: return false; 234: } 235: 236: /** 237: * Utility routine to check if InetAddress is a node local multicast address. 238: * 239: * @since 1.4 240: */ 241: public boolean isMCNodeLocal() 242: { 243: // This is the IPv4 implementation. 244: // Any class derived from InetAddress should override this. 245: // XXX: This seems to not exist with IPv4 addresses 246: return false; 247: } 248: 249: /** 250: * Utility routine to check if InetAddress is a link local multicast address. 251: * 252: * @since 1.4 253: */ 254: public boolean isMCLinkLocal() 255: { 256: // This is the IPv4 implementation. 257: // Any class derived from InetAddress should override this. 258: if (! isMulticastAddress()) 259: return false; 260: 261: return ((addr[0] & 0xff) == 0xe0 262: && (addr[1] & 0xff) == 0x00 263: && (addr[2] & 0xff) == 0x00); 264: } 265: 266: /** 267: * Utility routine to check if InetAddress is a site local multicast address. 268: * 269: * @since 1.4 270: */ 271: public boolean isMCSiteLocal() 272: { 273: // This is the IPv4 implementation. 274: // Any class derived from InetAddress should override this. 275: // XXX: This seems to not exist with IPv4 addresses 276: return false; 277: } 278: 279: /** 280: * Utility routine to check if InetAddress is a organization local 281: * multicast address. 282: * 283: * @since 1.4 284: */ 285: public boolean isMCOrgLocal() 286: { 287: // This is the IPv4 implementation. 288: // Any class derived from InetAddress should override this. 289: // XXX: This seems to not exist with IPv4 addresses 290: return false; 291: } 292: 293: /** 294: * Returns the hostname for this address. This will return the IP address 295: * as a String if there is no hostname available for this address 296: * 297: * @return The hostname for this address 298: */ 299: public String getHostName() 300: { 301: if (hostName != null) 302: return hostName; 303: 304: try 305: { 306: hostName = VMInetAddress.getHostByAddr(addr); 307: return hostName; 308: } 309: catch (UnknownHostException e) 310: { 311: return getHostAddress(); 312: } 313: } 314: 315: /** 316: * Returns the canonical hostname represented by this InetAddress 317: * 318: * @since 1.4 319: */ 320: public String getCanonicalHostName() 321: { 322: SecurityManager sm = System.getSecurityManager(); 323: if (sm != null) 324: { 325: try 326: { 327: sm.checkConnect(hostName, -1); 328: } 329: catch (SecurityException e) 330: { 331: return getHostAddress(); 332: } 333: } 334: 335: // Try to find the FDQN now 336: InetAddress address; 337: byte[] ipaddr = getAddress(); 338: 339: if (ipaddr.length == 16) 340: address = new Inet6Address(getAddress(), null); 341: else 342: address = new Inet4Address(getAddress(), null); 343: 344: return address.getHostName(); 345: } 346: 347: /** 348: * Returns the IP address of this object as a byte array. 349: * 350: * @return IP address 351: */ 352: public byte[] getAddress() 353: { 354: // An experiment shows that JDK1.2 returns a different byte array each 355: // time. This makes sense, in terms of security. 356: return (byte[]) addr.clone(); 357: } 358: 359: /** 360: * Returns the IP address of this object as a String. The address is in 361: * the dotted octet notation, for example, "127.0.0.1". 362: * 363: * @return The IP address of this object in String form 364: * 365: * @since 1.0.2 366: */ 367: public String getHostAddress() 368: { 369: StringBuffer sb = new StringBuffer(40); 370: 371: int len = addr.length; 372: int i = 0; 373: 374: for ( ; ; ) 375: { 376: sb.append(addr[i] & 0xff); 377: i++; 378: 379: if (i == len) 380: break; 381: 382: sb.append('.'); 383: } 384: 385: return sb.toString(); 386: } 387: 388: /** 389: * Returns a hash value for this address. Useful for creating hash 390: * tables. Overrides Object.hashCode() 391: * 392: * @return A hash value for this address. 393: */ 394: public int hashCode() 395: { 396: // There hashing algorithm is not specified, but a simple experiment 397: // shows that it is equal to the address, as a 32-bit big-endian integer. 398: int hash = 0; 399: int len = addr.length; 400: int i = len > 4 ? len - 4 : 0; 401: 402: for (; i < len; i++) 403: hash = (hash << 8) | (addr[i] & 0xff); 404: 405: return hash; 406: } 407: 408: /** 409: * Tests this address for equality against another InetAddress. The two 410: * addresses are considered equal if they contain the exact same octets. 411: * This implementation overrides Object.equals() 412: * 413: * @param obj The address to test for equality 414: * 415: * @return true if the passed in object's address is equal to this one's, 416: * false otherwise 417: */ 418: public boolean equals(Object obj) 419: { 420: if (! (obj instanceof InetAddress)) 421: return false; 422: 423: // "The Java Class Libraries" 2nd edition says "If a machine has 424: // multiple names instances of InetAddress for different name of 425: // that same machine are not equal. This is because they have 426: // different host names." This violates the description in the 427: // JDK 1.2 API documentation. A little experimentation 428: // shows that the latter is correct. 429: byte[] addr2 = ((InetAddress) obj).addr; 430: 431: if (addr.length != addr2.length) 432: return false; 433: 434: for (int i = 0; i < addr.length; i++) 435: if (addr[i] != addr2[i]) 436: return false; 437: 438: return true; 439: } 440: 441: /** 442: * Converts this address to a String. This string contains the IP in 443: * dotted decimal form. For example: "127.0.0.1" This method is equivalent 444: * to getHostAddress() and overrides Object.toString() 445: * 446: * @return This address in String form 447: */ 448: public String toString() 449: { 450: String addr = getHostAddress(); 451: String host = (hostName != null) ? hostName : ""; 452: return host + "/" + addr; 453: } 454: 455: /** 456: * Returns an InetAddress object given the raw IP address. 457: * 458: * The argument is in network byte order: the highest order byte of the 459: * address is in getAddress()[0]. 460: * 461: * @param addr The IP address to create the InetAddress object from 462: * 463: * @exception UnknownHostException If IP address has illegal length 464: * 465: * @since 1.4 466: */ 467: public static InetAddress getByAddress(byte[] addr) 468: throws UnknownHostException 469: { 470: return getByAddress(null, addr); 471: } 472: 473: /** 474: * Creates an InetAddress based on the provided host name and IP address. 475: * No name service is checked for the validity of the address. 476: * 477: * @param host The hostname of the InetAddress object to create 478: * @param addr The IP address to create the InetAddress object from 479: * 480: * @exception UnknownHostException If IP address is of illegal length 481: * 482: * @since 1.4 483: */ 484: public static InetAddress getByAddress(String host, byte[] addr) 485: throws UnknownHostException 486: { 487: if (addr.length == 4) 488: return new Inet4Address(addr, host); 489: 490: if (addr.length == 16) 491: return new Inet6Address(addr, host); 492: 493: throw new UnknownHostException("IP address has illegal length"); 494: } 495: 496: /** 497: * If hostname is a valid numeric IP address, return the numeric address. 498: * Otherwise, return null. 499: * 500: * @param hostname the name of the host 501: */ 502: private static byte[] aton(String hostname) 503: { 504: StringTokenizer st = new StringTokenizer(hostname, "."); 505: 506: if (st.countTokens() == 4) 507: { 508: int index; 509: byte[] address = new byte[4]; 510: 511: for (index = 0; index < 4; index++) 512: { 513: try 514: { 515: short n = Short.parseShort(st.nextToken()); 516: 517: if ((n < 0) || (n > 255)) 518: break; 519: 520: address[index] = (byte) n; 521: } 522: catch (NumberFormatException e) 523: { 524: break; 525: } 526: } 527: 528: if (index == 4) 529: return address; 530: } 531: 532: return null; 533: } 534: 535: /** 536: * Returns an InetAddress object representing the IP address of the given 537: * hostname. This name can be either a hostname such as "www.urbanophile.com" 538: * or an IP address in dotted decimal format such as "127.0.0.1". If the 539: * hostname is null or "", the hostname of the local machine is supplied by 540: * default. This method is equivalent to returning the first element in 541: * the InetAddress array returned from GetAllByName. 542: * 543: * @param hostname The name of the desired host, or null for the local 544: * loopback address. 545: * 546: * @return The address of the host as an InetAddress object. 547: * 548: * @exception UnknownHostException If no IP address for the host could 549: * be found 550: * @exception SecurityException If a security manager exists and its 551: * checkConnect method doesn't allow the operation 552: */ 553: public static InetAddress getByName(String hostname) 554: throws UnknownHostException 555: { 556: InetAddress[] addresses = getAllByName(hostname); 557: return addresses[0]; 558: } 559: 560: /** 561: * Returns an array of InetAddress objects representing all the host/ip 562: * addresses of a given host, given the host's name. This name can be 563: * either a hostname such as "www.urbanophile.com" or an IP address in 564: * dotted decimal format such as "127.0.0.1". If the value is null, the 565: * hostname of the local machine is supplied by default. 566: * 567: * @param hostname The name of the desired host, or null for the 568: * local loopback address. 569: * 570: * @return All addresses of the host as an array of InetAddress objects. 571: * 572: * @exception UnknownHostException If no IP address for the host could 573: * be found 574: * @exception SecurityException If a security manager exists and its 575: * checkConnect method doesn't allow the operation 576: */ 577: public static InetAddress[] getAllByName(String hostname) 578: throws UnknownHostException 579: { 580: SecurityManager s = System.getSecurityManager(); 581: if (s != null) 582: s.checkConnect(hostname, -1); 583: 584: InetAddress[] addresses; 585: 586: if (hostname != null) 587: hostname = hostname.trim(); 588: 589: // Default to current host if necessary 590: if (hostname == null || hostname.equals("")) 591: { 592: addresses = new InetAddress[1]; 593: addresses[0] = LOCALHOST; 594: return addresses; 595: } 596: 597: // Not in cache, try the lookup 598: byte[][] iplist = VMInetAddress.getHostByName(hostname); 599: 600: if (iplist.length == 0) 601: throw new UnknownHostException(hostname); 602: 603: addresses = new InetAddress[iplist.length]; 604: 605: for (int i = 0; i < iplist.length; i++) 606: { 607: if (iplist[i].length != 4) 608: throw new UnknownHostException(hostname); 609: 610: addresses[i] = new Inet4Address(iplist[i], hostname); 611: } 612: 613: return addresses; 614: } 615: 616: /** 617: * Returns the special address INADDR_ANY used for binding to a local 618: * port on all IP addresses hosted by a the local host. 619: * 620: * @return An InetAddress object representing INDADDR_ANY 621: * 622: * @exception UnknownHostException If an error occurs 623: */ 624: static InetAddress getInaddrAny() throws UnknownHostException 625: { 626: if (inaddr_any == null) 627: { 628: byte[] tmp = VMInetAddress.lookupInaddrAny(); 629: inaddr_any = new Inet4Address(tmp, null); 630: inaddr_any.hostName = inaddr_any.getHostName(); 631: } 632: 633: return inaddr_any; 634: } 635: 636: /** 637: * Returns an InetAddress object representing the address of the current 638: * host. 639: * 640: * @return The local host's address 641: * 642: * @exception UnknownHostException If no IP address for the host could 643: * be found 644: */ 645: public static InetAddress getLocalHost() throws UnknownHostException 646: { 647: String hostname = VMInetAddress.getLocalHostname(); 648: return getByName(hostname); 649: } 650: 651: /* 652: * Needed for serialization 653: */ 654: private void readResolve() throws ObjectStreamException 655: { 656: // FIXME: implement this 657: } 658: 659: private void readObject(ObjectInputStream ois) 660: throws IOException, ClassNotFoundException 661: { 662: ois.defaultReadObject(); 663: addr = new byte[4]; 664: addr[3] = (byte) address; 665: 666: for (int i = 2; i >= 0; --i) 667: addr[i] = (byte) (address >>= 8); 668: 669: family = 2; /* AF_INET */ 670: } 671: 672: private void writeObject(ObjectOutputStream oos) throws IOException 673: { 674: // Build a 32 bit address from the last 4 bytes of a 4 byte IPv4 address 675: // or a 16 byte IPv6 address. 676: int len = addr.length; 677: int i = len - 4; 678: 679: for (; i < len; i++) 680: address = address << 8 | (addr[i] & 0xff); 681: 682: oos.defaultWriteObject(); 683: } 684: }
GNU Classpath (0.20) |