Source for java.net.InetAddress

   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: }