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.HashMap;
  47: import java.util.StringTokenizer;
  48: 
  49: /**
  50:  * This class models an Internet address.  It does not have a public
  51:  * constructor.  Instead, new instances of this objects are created
  52:  * using the static methods getLocalHost(), getByName(), and
  53:  * getAllByName().
  54:  *
  55:  * <p>This class fulfills the function of the C style functions gethostname(),
  56:  * gethostbyname(), and gethostbyaddr().  It resolves Internet DNS names
  57:  * into their corresponding numeric addresses and vice versa.</p>
  58:  *
  59:  * @author Aaron M. Renn (arenn@urbanophile.com)
  60:  * @author Per Bothner
  61:  *
  62:  * @specnote This class is not final since JK 1.4
  63:  */
  64: public class InetAddress implements Serializable
  65: {
  66:   private static final long serialVersionUID = 3286316764910316507L;
  67: 
  68:   /**
  69:    * The default DNS hash table size,
  70:    * Use a prime number happy with hash table.
  71:    */
  72:   private static final int DEFAULT_CACHE_SIZE = 89;
  73: 
  74:   /**
  75:    * The default caching period in minutes.
  76:    */
  77:   private static final int DEFAULT_CACHE_PERIOD = 4 * 60;
  78: 
  79:   /**
  80:    * Percentage of cache entries to purge when the table gets full.
  81:    */
  82:   private static final int DEFAULT_CACHE_PURGE_PCT = 30;
  83: 
  84:   /**
  85:    * The special IP address INADDR_ANY.
  86:    */
  87:   private static InetAddress inaddr_any;
  88: 
  89:   /**
  90:    * Dummy InetAddress, used to bind socket to any (all) network interfaces.
  91:    */
  92:   static InetAddress ANY_IF;
  93: 
  94:   /**
  95:    * Stores static localhost address object.
  96:    */
  97:   static InetAddress LOCALHOST;
  98: 
  99:   /**
 100:    * The size of the cache.
 101:    */
 102:   private static int cache_size = 0;
 103: 
 104:   /**
 105:    * The length of time we will continue to read the address from cache
 106:    * before forcing another lookup.
 107:    */
 108:   private static int cache_period = 0;
 109: 
 110:   /**
 111:    * What percentage of the cache we will purge if it gets full.
 112:    */
 113:   private static int cache_purge_pct = 0;
 114: 
 115:   /**
 116:    * HashMap to use as DNS lookup cache.
 117:    * Use HashMap because all accesses to cache are already synchronized.
 118:    */
 119:   private static HashMap cache;
 120: 
 121:   static
 122:   {
 123:     // Look for properties that override default caching behavior
 124:     cache_size =
 125:       Integer.getInteger("gnu.java.net.dns_cache_size", DEFAULT_CACHE_SIZE)
 126:              .intValue();
 127:     cache_period =
 128:       Integer.getInteger("gnu.java.net.dns_cache_period",
 129:                          DEFAULT_CACHE_PERIOD * 60 * 1000).intValue();
 130: 
 131:     cache_purge_pct =
 132:       Integer.getInteger("gnu.java.net.dns_cache_purge_pct",
 133:                          DEFAULT_CACHE_PURGE_PCT).intValue();
 134: 
 135:     // Fallback to  defaults if necessary
 136:     if ((cache_purge_pct < 1) || (cache_purge_pct > 100))
 137:       cache_purge_pct = DEFAULT_CACHE_PURGE_PCT;
 138: 
 139:     // Create the cache
 140:     if (cache_size != 0)
 141:       cache = new HashMap(cache_size);
 142: 
 143:     // precompute the ANY_IF address
 144:     try
 145:       {
 146:         ANY_IF = getInaddrAny();
 147: 
 148:     byte[] ip_localhost = { 127, 0, 0, 1 };
 149:     LOCALHOST = new Inet4Address(ip_localhost, "localhost");
 150:       }
 151:     catch (UnknownHostException uhe)
 152:       {
 153:         // Hmmm, make one up and hope that it works.
 154:         byte[] zeros = { 0, 0, 0, 0 };
 155:         ANY_IF = new Inet4Address(zeros, "0.0.0.0");
 156:       }
 157:   }
 158: 
 159:   /**
 160:    * The Serialized Form specifies that an int 'address' is saved/restored.
 161:    * This class uses a byte array internally so we'll just do the conversion
 162:    * at serialization time and leave the rest of the algorithm as is.
 163:    */
 164:   private int address;
 165: 
 166:   /**
 167:    * An array of octets representing an IP address.
 168:    */
 169:   transient byte[] addr;
 170: 
 171:   /**
 172:    * The name of the host for this address.
 173:    */
 174:   String hostName;
 175: 
 176:   /**
 177:    * The time this address was looked up.
 178:    */
 179:   transient long lookup_time;
 180: 
 181:   /**
 182:    * The field 'family' seems to be the AF_ value.
 183:    * FIXME: Much of the code in the other java.net classes does not make
 184:    * use of this family field.  A better implementation would be to make
 185:    * use of getaddrinfo() and have other methods just check the family
 186:    * field rather than examining the length of the address each time.
 187:    */
 188:   int family;
 189: 
 190:   /**
 191:    * Initializes this object's addr instance variable from the passed in
 192:    * byte array.  Note that this constructor is protected and is called
 193:    * only by static methods in this class.
 194:    *
 195:    * @param ipaddr The IP number of this address as an array of bytes
 196:    * @param hostname The hostname of this IP address.
 197:    */
 198:   InetAddress(byte[] ipaddr, String hostname)
 199:   {
 200:     addr = (null == ipaddr) ? null : (byte[]) ipaddr.clone();
 201:     hostName = hostname;
 202:     
 203:     lookup_time = System.currentTimeMillis();
 204: 
 205:     family = 2; /* AF_INET */
 206:   }
 207: 
 208:   /**
 209:    * Returns true if this address is a multicast address, false otherwise.
 210:    * An address is multicast if the high four bits are "1110".  These are
 211:    * also known as "Class D" addresses.
 212:    *
 213:    * @return true if mulitcast, false if not
 214:    *
 215:    * @since 1.1
 216:    */
 217:   public boolean isMulticastAddress()
 218:   {
 219:     // Mask against high order bits of 1110
 220:     if (addr.length == 4)
 221:       return (addr[0] & 0xf0) == 0xe0;
 222: 
 223:     return false;
 224:   }
 225: 
 226:   /**
 227:    * Utility routine to check if the InetAddress in a wildcard address
 228:    *
 229:    * @since 1.4
 230:    */
 231:   public boolean isAnyLocalAddress()
 232:   {
 233:     // This is the IPv4 implementation.
 234:     // Any class derived from InetAddress should override this.
 235:     return equals(ANY_IF);
 236:   }
 237: 
 238:   /**
 239:    * Utility routine to check if the InetAddress is a loopback address
 240:    *
 241:    * @since 1.4
 242:    */
 243:   public boolean isLoopbackAddress()
 244:   {
 245:     // This is the IPv4 implementation.
 246:     // Any class derived from InetAddress should override this.
 247:     return (addr[0] & 0xff) == 0x7f;
 248:   }
 249: 
 250:   /**
 251:    * Utility routine to check if InetAddress is a link local address
 252:    *
 253:    * @since 1.4
 254:    */
 255:   public boolean isLinkLocalAddress()
 256:   {
 257:     // This is the IPv4 implementation.
 258:     // Any class derived from InetAddress should override this.
 259:     // XXX: This seems to not exist with IPv4 addresses
 260:     return false;
 261:   }
 262: 
 263:   /**
 264:    * Utility routine to check if InetAddress is a site local address
 265:    *
 266:    * @since 1.4
 267:    */
 268:   public boolean isSiteLocalAddress()
 269:   {
 270:     // This is the IPv4 implementation.
 271:     // Any class derived from InetAddress should override this.
 272: 
 273:     // 10.0.0.0/8
 274:     if ((addr[0] & 0xff) == 0x0a)
 275:       return true;
 276: 
 277:     // 172.16.0.0/12
 278:     if ((addr[0] & 0xff) == 0xac && (addr[1] & 0xf0) == 0x10)
 279:       return true;
 280: 
 281:     // 192.168.0.0/16
 282:     if ((addr[0] & 0xff) == 0xc0 && (addr[1] & 0xff) == 0xa8)
 283:       return true;
 284: 
 285:     // XXX: Do we need to check more addresses here ?
 286:     return false;
 287:   }
 288: 
 289:   /**
 290:    * Utility routine to check if InetAddress is a global multicast address
 291:    *
 292:    * @since 1.4
 293:    */
 294:   public boolean isMCGlobal()
 295:   {
 296:     // This is the IPv4 implementation.
 297:     // Any class derived from InetAddress should override this.
 298:     // XXX: This seems to not exist with IPv4 addresses
 299:     return false;
 300:   }
 301: 
 302:   /**
 303:    * Utility routine to check if InetAddress is a node local multicast address.
 304:    *
 305:    * @since 1.4
 306:    */
 307:   public boolean isMCNodeLocal()
 308:   {
 309:     // This is the IPv4 implementation.
 310:     // Any class derived from InetAddress should override this.
 311:     // XXX: This seems to not exist with IPv4 addresses
 312:     return false;
 313:   }
 314: 
 315:   /**
 316:    * Utility routine to check if InetAddress is a link local multicast address.
 317:    *
 318:    * @since 1.4
 319:    */
 320:   public boolean isMCLinkLocal()
 321:   {
 322:     // This is the IPv4 implementation.
 323:     // Any class derived from InetAddress should override this.
 324:     if (! isMulticastAddress())
 325:       return false;
 326: 
 327:     return ((addr[0] & 0xff) == 0xe0
 328:         && (addr[1] & 0xff)  == 0x00
 329:         && (addr[2] & 0xff)  == 0x00);
 330:   }
 331: 
 332:   /**
 333:    * Utility routine to check if InetAddress is a site local multicast address.
 334:    *
 335:    * @since 1.4
 336:    */
 337:   public boolean isMCSiteLocal()
 338:   {
 339:     // This is the IPv4 implementation.
 340:     // Any class derived from InetAddress should override this.
 341:     // XXX: This seems to not exist with IPv4 addresses
 342:     return false;
 343:   }
 344: 
 345:   /**
 346:    * Utility routine to check if InetAddress is a organization local
 347:    * multicast address.
 348:    *
 349:    * @since 1.4
 350:    */
 351:   public boolean isMCOrgLocal()
 352:   {
 353:     // This is the IPv4 implementation.
 354:     // Any class derived from InetAddress should override this.
 355:     // XXX: This seems to not exist with IPv4 addresses
 356:     return false;
 357:   }
 358: 
 359:   /**
 360:    * Returns the hostname for this address.  This will return the IP address
 361:    * as a String if there is no hostname available for this address
 362:    *
 363:    * @return The hostname for this address
 364:    */
 365:   public String getHostName()
 366:   {
 367:     if (hostName != null)
 368:       return hostName;
 369: 
 370:     try
 371:       {
 372:     hostName = VMInetAddress.getHostByAddr(addr);
 373:     return hostName;
 374:       }
 375:     catch (UnknownHostException e)
 376:       {
 377:     return getHostAddress();
 378:       }
 379:   }
 380: 
 381:   /**
 382:    * Returns the canonical hostname represented by this InetAddress
 383:    * 
 384:    * @since 1.4
 385:    */
 386:   public String getCanonicalHostName()
 387:   {
 388:     SecurityManager sm = System.getSecurityManager();
 389:     if (sm != null)
 390:       {
 391:         try
 392:       {
 393:             sm.checkConnect(hostName, -1);
 394:       }
 395:     catch (SecurityException e)
 396:       {
 397:         return getHostAddress();
 398:       }
 399:       }
 400: 
 401:     // Try to find the FDQN now
 402:     InetAddress address;
 403:     byte[] ipaddr = getAddress();
 404: 
 405:     if (ipaddr.length == 16)
 406:       address = new Inet6Address(getAddress(), null);
 407:     else
 408:       address = new Inet4Address(getAddress(), null);
 409: 
 410:     return address.getHostName();
 411:   }
 412: 
 413:   /**
 414:    * Returns the IP address of this object as a byte array.
 415:    *
 416:    * @return IP address
 417:    */
 418:   public byte[] getAddress()
 419:   {
 420:     // An experiment shows that JDK1.2 returns a different byte array each
 421:     // time.  This makes sense, in terms of security.
 422:     return (byte[]) addr.clone();
 423:   }
 424: 
 425:   /**
 426:    * Returns the IP address of this object as a String.  The address is in
 427:    * the dotted octet notation, for example, "127.0.0.1".
 428:    *
 429:    * @return The IP address of this object in String form
 430:    *
 431:    * @since 1.0.2
 432:    */
 433:   public String getHostAddress()
 434:   {
 435:     StringBuffer sb = new StringBuffer(40);
 436: 
 437:     int len = addr.length;
 438:     int i = 0;
 439:     
 440:     for ( ; ; )
 441:       {
 442:         sb.append(addr[i] & 0xff);
 443:         i++;
 444:     
 445:         if (i == len)
 446:           break;
 447:     
 448:         sb.append('.');
 449:       }
 450: 
 451:     return sb.toString();
 452:   }
 453: 
 454:   /**
 455:    * Returns a hash value for this address.  Useful for creating hash
 456:    * tables.  Overrides Object.hashCode()
 457:    *
 458:    * @return A hash value for this address.
 459:    */
 460:   public int hashCode()
 461:   {
 462:     // There hashing algorithm is not specified, but a simple experiment
 463:     // shows that it is equal to the address, as a 32-bit big-endian integer.
 464:     int hash = 0;
 465:     int len = addr.length;
 466:     int i = len > 4 ? len - 4 : 0;
 467: 
 468:     for (; i < len; i++)
 469:       hash = (hash << 8) | (addr[i] & 0xff);
 470: 
 471:     return hash;
 472:   }
 473: 
 474:   /**
 475:    * Tests this address for equality against another InetAddress.  The two
 476:    * addresses are considered equal if they contain the exact same octets.
 477:    * This implementation overrides Object.equals()
 478:    *
 479:    * @param obj The address to test for equality
 480:    *
 481:    * @return true if the passed in object's address is equal to this one's,
 482:    * false otherwise
 483:    */
 484:   public boolean equals(Object obj)
 485:   {
 486:     if (! (obj instanceof InetAddress))
 487:       return false;
 488: 
 489:     // "The Java Class Libraries" 2nd edition says "If a machine has
 490:     // multiple names instances of InetAddress for different name of
 491:     // that same machine are not equal.  This is because they have
 492:     // different host names."  This violates the description in the
 493:     // JDK 1.2 API documentation.  A little experimentation
 494:     // shows that the latter is correct.
 495:     byte[] addr2 = ((InetAddress) obj).addr;
 496: 
 497:     if (addr.length != addr2.length)
 498:       return false;
 499: 
 500:     for (int i = 0; i < addr.length; i++)
 501:       if (addr[i] != addr2[i])
 502:     return false;
 503: 
 504:     return true;
 505:   }
 506: 
 507:   /**
 508:    * Converts this address to a String.  This string contains the IP in
 509:    * dotted decimal form. For example: "127.0.0.1"  This method is equivalent
 510:    * to getHostAddress() and overrides Object.toString()
 511:    *
 512:    * @return This address in String form
 513:    */
 514:   public String toString()
 515:   {
 516:     String addr = getHostAddress();
 517:     String host = (hostName != null) ? hostName : "";
 518:     return host + "/" + addr;
 519:   }
 520: 
 521:   /**
 522:    * Returns an InetAddress object given the raw IP address.
 523:    *
 524:    * The argument is in network byte order: the highest order byte of the
 525:    * address is in getAddress()[0].
 526:    *
 527:    * @param addr The IP address to create the InetAddress object from
 528:    *
 529:    * @exception UnknownHostException If IP address has illegal length
 530:    *
 531:    * @since 1.4
 532:    */
 533:   public static InetAddress getByAddress(byte[] addr)
 534:     throws UnknownHostException
 535:   {
 536:     return getByAddress(null, addr);
 537:   }
 538: 
 539:   /**
 540:    * Creates an InetAddress based on the provided host name and IP address.
 541:    * No name service is checked for the validity of the address.
 542:    *
 543:    * @param host The hostname of the InetAddress object to create
 544:    * @param addr The IP address to create the InetAddress object from
 545:    *
 546:    * @exception UnknownHostException If IP address is of illegal length
 547:    *
 548:    * @since 1.4
 549:    */
 550:   public static InetAddress getByAddress(String host, byte[] addr)
 551:     throws UnknownHostException
 552:   {
 553:     if (addr.length == 4)
 554:       return new Inet4Address(addr, host);
 555: 
 556:     if (addr.length == 16)
 557:       return new Inet6Address(addr, host);
 558: 
 559:     throw new UnknownHostException("IP address has illegal length");
 560:   }
 561: 
 562:   /**
 563:    * If hostname is a valid numeric IP address, return the numeric address.
 564:    * Otherwise, return null.
 565:    *
 566:    * @param hostname the name of the host
 567:    */
 568:   private static byte[] aton(String hostname)
 569:   {
 570:     StringTokenizer st = new StringTokenizer(hostname, ".");
 571: 
 572:     if (st.countTokens() == 4)
 573:       {
 574:     int index;
 575:     byte[] address = new byte[4];
 576: 
 577:     for (index = 0; index < 4; index++)
 578:       {
 579:         try
 580:           {
 581:         short n = Short.parseShort(st.nextToken());
 582: 
 583:         if ((n < 0) || (n > 255))
 584:           break;
 585: 
 586:         address[index] = (byte) n;
 587:           }
 588:         catch (NumberFormatException e)
 589:           {
 590:         break;
 591:           }
 592:       }
 593: 
 594:     if (index == 4)
 595:       return address;
 596:       }
 597: 
 598:     return null;
 599:   }
 600: 
 601:   /**
 602:    * Returns an InetAddress object representing the IP address of the given
 603:    * hostname.  This name can be either a hostname such as "www.urbanophile.com"
 604:    * or an IP address in dotted decimal format such as "127.0.0.1".  If the
 605:    * hostname is null or "", the hostname of the local machine is supplied by
 606:    * default.  This method is equivalent to returning the first element in
 607:    * the InetAddress array returned from GetAllByName.
 608:    *
 609:    * @param hostname The name of the desired host, or null for the local 
 610:    * loopback address.
 611:    *
 612:    * @return The address of the host as an InetAddress object.
 613:    *
 614:    * @exception UnknownHostException If no IP address for the host could
 615:    * be found
 616:    * @exception SecurityException If a security manager exists and its
 617:    * checkConnect method doesn't allow the operation
 618:    */
 619:   public static InetAddress getByName(String hostname)
 620:     throws UnknownHostException
 621:   {
 622:     InetAddress[] addresses = getAllByName(hostname);
 623:     return addresses[0];
 624:   }
 625: 
 626:   /**
 627:    * Returns an array of InetAddress objects representing all the host/ip
 628:    * addresses of a given host, given the host's name.  This name can be
 629:    * either a hostname such as "www.urbanophile.com" or an IP address in
 630:    * dotted decimal format such as "127.0.0.1".  If the value is null, the
 631:    * hostname of the local machine is supplied by default.
 632:    *
 633:    * @param hostname The name of the desired host, or null for the
 634:    * local loopback address.
 635:    *
 636:    * @return All addresses of the host as an array of InetAddress objects.
 637:    *
 638:    * @exception UnknownHostException If no IP address for the host could
 639:    * be found
 640:    * @exception SecurityException If a security manager exists and its
 641:    * checkConnect method doesn't allow the operation
 642:    */
 643:   public static InetAddress[] getAllByName(String hostname)
 644:     throws UnknownHostException
 645:   {
 646:     SecurityManager s = System.getSecurityManager();
 647:     if (s != null)
 648:       s.checkConnect(hostname, -1);
 649: 
 650:     InetAddress[] addresses;
 651: 
 652:     // Default to current host if necessary
 653:     if (hostname == null)
 654:       {
 655:     addresses = new InetAddress[1];
 656:     addresses[0] = LOCALHOST;
 657:     return addresses;
 658:       }
 659: 
 660:     // Check the cache for this host before doing a lookup
 661:     addresses = checkCacheFor(hostname);
 662: 
 663:     if (addresses != null)
 664:       return addresses;
 665: 
 666:     // Not in cache, try the lookup
 667:     byte[][] iplist = VMInetAddress.getHostByName(hostname);
 668: 
 669:     if (iplist.length == 0)
 670:       throw new UnknownHostException(hostname);
 671: 
 672:     addresses = new InetAddress[iplist.length];
 673: 
 674:     for (int i = 0; i < iplist.length; i++)
 675:       {
 676:     if (iplist[i].length != 4)
 677:       throw new UnknownHostException(hostname);
 678: 
 679:     addresses[i] = new Inet4Address(iplist[i], hostname);
 680:       }
 681: 
 682:     addToCache(hostname, addresses);
 683:     return addresses;
 684:   }
 685: 
 686:   /**
 687:    * This method checks the DNS cache to see if we have looked this hostname
 688:    * up before. If so, we return the cached addresses unless it has been in the
 689:    * cache too long.
 690:    *
 691:    * @param hostname The hostname to check for
 692:    *
 693:    * @return The InetAddress for this hostname or null if not available
 694:    */
 695:   private static synchronized InetAddress[] checkCacheFor(String hostname)
 696:   {
 697:     InetAddress[] addresses = null;
 698: 
 699:     if (cache_size == 0)
 700:       return null;
 701: 
 702:     Object obj = cache.get(hostname);
 703:     if (obj == null)
 704:       return null;
 705: 
 706:     if (obj instanceof InetAddress[])
 707:       addresses = (InetAddress[]) obj;
 708: 
 709:     if (addresses == null)
 710:       return null;
 711: 
 712:     if (cache_period != -1)
 713:       if ((System.currentTimeMillis() - addresses[0].lookup_time) > cache_period)
 714:         {
 715:       cache.remove(hostname);
 716:       return null;
 717:         }
 718: 
 719:     return addresses;
 720:   }
 721: 
 722:   /**
 723:    * This method adds an InetAddress object to our DNS cache.  Note that
 724:    * if the cache is full, then we run a purge to get rid of old entries.
 725:    * This will cause a performance hit, thus applications using lots of
 726:    * lookups should set the cache size to be very large.
 727:    *
 728:    * @param hostname The hostname to cache this address under
 729:    * @param obj The InetAddress or InetAddress array to store
 730:    */
 731:   private static synchronized void addToCache(String hostname, Object obj)
 732:   {
 733:     if (cache_size == 0)
 734:       return;
 735: 
 736:     // Check to see if hash table is full
 737:     if (cache_size != -1)
 738:       if (cache.size() == cache_size)
 739:         {
 740:       // FIXME Add code to purge later.
 741:         }
 742: 
 743:     cache.put(hostname, obj);
 744:   }
 745: 
 746:   /**
 747:    * Returns the special address INADDR_ANY used for binding to a local
 748:    * port on all IP addresses hosted by a the local host.
 749:    *
 750:    * @return An InetAddress object representing INDADDR_ANY
 751:    *
 752:    * @exception UnknownHostException If an error occurs
 753:    */
 754:   static InetAddress getInaddrAny() throws UnknownHostException
 755:   {
 756:     if (inaddr_any == null)
 757:       {
 758:     byte[] tmp = VMInetAddress.lookupInaddrAny();
 759:     inaddr_any = new Inet4Address(tmp, null);
 760:       }
 761: 
 762:     return inaddr_any;
 763:   }
 764: 
 765:   /**
 766:    * Returns an InetAddress object representing the address of the current
 767:    * host.
 768:    *
 769:    * @return The local host's address
 770:    *
 771:    * @exception UnknownHostException If no IP address for the host could
 772:    * be found
 773:    */
 774:   public static InetAddress getLocalHost() throws UnknownHostException
 775:   {
 776:     String hostname = VMInetAddress.getLocalHostname();
 777:     return getByName(hostname);
 778:   }
 779: 
 780:   /*
 781:    * Needed for serialization
 782:    */
 783:   private void readResolve() throws ObjectStreamException
 784:   {
 785:     // FIXME: implement this
 786:   }
 787: 
 788:   private void readObject(ObjectInputStream ois)
 789:     throws IOException, ClassNotFoundException
 790:   {
 791:     ois.defaultReadObject();
 792:     addr = new byte[4];
 793:     addr[3] = (byte) address;
 794: 
 795:     for (int i = 2; i >= 0; --i)
 796:       addr[i] = (byte) (address >>= 8);
 797: 
 798:     family = 2; /* AF_INET  */
 799:   }
 800: 
 801:   private void writeObject(ObjectOutputStream oos) throws IOException
 802:   {
 803:     // Build a 32 bit address from the last 4 bytes of a 4 byte IPv4 address
 804:     // or a 16 byte IPv6 address.
 805:     int len = addr.length;
 806:     int i = len - 4;
 807: 
 808:     for (; i < len; i++)
 809:       address = address << 8 | (addr[i] & 0xff);
 810: 
 811:     oos.defaultWriteObject();
 812:   }
 813: }