001/* InetAddress.java -- Class to model an Internet address
002   Copyright (C) 1998, 1999, 2002, 2004, 2005, 2006
003   Free Software Foundation, Inc.
004
005This file is part of GNU Classpath.
006
007GNU Classpath is free software; you can redistribute it and/or modify
008it under the terms of the GNU General Public License as published by
009the Free Software Foundation; either version 2, or (at your option)
010any later version.
011
012GNU Classpath is distributed in the hope that it will be useful, but
013WITHOUT ANY WARRANTY; without even the implied warranty of
014MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015General Public License for more details.
016
017You should have received a copy of the GNU General Public License
018along with GNU Classpath; see the file COPYING.  If not, write to the
019Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02002110-1301 USA.
021
022Linking this library statically or dynamically with other modules is
023making a combined work based on this library.  Thus, the terms and
024conditions of the GNU General Public License cover the whole
025combination.
026
027As a special exception, the copyright holders of this library give you
028permission to link this library with independent modules to produce an
029executable, regardless of the license terms of these independent
030modules, and to copy and distribute the resulting executable under
031terms of your choice, provided that you also meet, for each linked
032independent module, the terms and conditions of the license of that
033module.  An independent module is a module which is not derived from
034or based on this library.  If you modify this library, you may extend
035this exception to your version of the library, but you are not
036obligated to do so.  If you do not wish to do so, delete this
037exception statement from your version. */
038
039
040package java.net;
041
042import java.io.IOException;
043import java.io.ObjectInputStream;
044import java.io.ObjectOutputStream;
045import java.io.ObjectStreamException;
046import java.io.Serializable;
047
048/**
049 * This class models an Internet address.  It does not have a public
050 * constructor.  Instead, new instances of this objects are created
051 * using the static methods getLocalHost(), getByName(), and
052 * getAllByName().
053 *
054 * <p>This class fulfills the function of the C style functions gethostname(),
055 * gethostbyname(), and gethostbyaddr().  It resolves Internet DNS names
056 * into their corresponding numeric addresses and vice versa.</p>
057 *
058 * @author Aaron M. Renn (arenn@urbanophile.com)
059 * @author Per Bothner
060 * @author Gary Benson (gbenson@redhat.com)
061 *
062 * @specnote This class is not final since JDK 1.4
063 */
064public class InetAddress implements Serializable
065{
066  private static final long serialVersionUID = 3286316764910316507L;
067
068  /**
069   * Dummy InetAddress, used to bind socket to any (all) network interfaces.
070   */
071  static InetAddress ANY_IF;
072  static
073  {
074    byte[] addr;
075    try
076      {
077        addr = VMInetAddress.lookupInaddrAny();
078      }
079    catch (UnknownHostException e)
080      {
081        // Make one up and hope it works.
082        addr = new byte[] {0, 0, 0, 0};
083      }
084    try
085      {
086        ANY_IF = getByAddress(addr);
087      }
088    catch (UnknownHostException e)
089      {
090        throw (InternalError) new InternalError().initCause(e);
091      }
092    ANY_IF.hostName = ANY_IF.getHostName();
093  }
094  
095  /**
096   * Stores static localhost address object.
097   */
098  static InetAddress LOCALHOST;
099  static
100  {
101    try
102      {
103        LOCALHOST = getByAddress("localhost", new byte[] {127, 0, 0, 1});
104      }
105    catch (UnknownHostException e)
106      {
107        throw (InternalError) new InternalError().initCause(e);
108      }
109  }    
110
111  /**
112   * The Serialized Form specifies that an int 'address' is saved/restored.
113   * This class uses a byte array internally so we'll just do the conversion
114   * at serialization time and leave the rest of the algorithm as is.
115   */
116  private int address;
117
118  /**
119   * An array of octets representing an IP address.
120   */
121  transient byte[] addr;
122
123  /**
124   * The name of the host for this address.
125   */
126  String hostName;
127
128  /**
129   * Needed for serialization.
130   */
131  private int family;
132
133  /**
134   * Constructor.  Prior to the introduction of IPv6 support in 1.4,
135   * methods such as InetAddress.getByName() would return InetAddress
136   * objects.  From 1.4 such methods returned either Inet4Address or
137   * Inet6Address objects, but for compatibility Inet4Address objects
138   * are serialized as InetAddresses.  As such, there are only two
139   * places where it is appropriate to invoke this constructor: within
140   * subclasses constructors and within Inet4Address.writeReplace().
141   *
142   * @param ipaddr The IP number of this address as an array of bytes
143   * @param hostname The hostname of this IP address.
144   * @param family The address family of this IP address.
145   */
146  InetAddress(byte[] ipaddr, String hostname, int family)
147  {
148    addr = (null == ipaddr) ? null : (byte[]) ipaddr.clone();
149    hostName = hostname;
150    this.family = family;
151  }
152
153  /**
154   * Returns true if this address is a multicast address, false otherwise.
155   * An address is multicast if the high four bits are "1110".  These are
156   * also known as "Class D" addresses.
157   *
158   * <p>This method cannot be abstract for backward compatibility reasons. By
159   * default it always throws {@link UnsupportedOperationException} unless
160   * overridden.</p>
161   * 
162   * @return true if mulitcast, false if not
163   *
164   * @since 1.1
165   */
166  public boolean isMulticastAddress()
167  {
168    throw new UnsupportedOperationException();
169  }
170
171  /**
172   * Utility routine to check if the InetAddress in a wildcard address
173   *
174   * <p>This method cannot be abstract for backward compatibility reasons. By
175   * default it always throws {@link UnsupportedOperationException} unless
176   * overridden.</p>
177   * 
178   * @since 1.4
179   */
180  public boolean isAnyLocalAddress()
181  {
182    throw new UnsupportedOperationException();
183  }
184
185  /**
186   * Utility routine to check if the InetAddress is a loopback address
187   *
188   * <p>This method cannot be abstract for backward compatibility reasons. By
189   * default it always throws {@link UnsupportedOperationException} unless
190   * overridden.</p>
191   * 
192   * @since 1.4
193   */
194  public boolean isLoopbackAddress()
195  {
196    throw new UnsupportedOperationException();
197  }
198
199  /**
200   * Utility routine to check if InetAddress is a link local address
201   *
202   * <p>This method cannot be abstract for backward compatibility reasons. By
203   * default it always throws {@link UnsupportedOperationException} unless
204   * overridden.</p>
205   * 
206   * @since 1.4
207   */
208  public boolean isLinkLocalAddress()
209  {
210    throw new UnsupportedOperationException();
211  }
212
213  /**
214   * Utility routine to check if InetAddress is a site local address
215   *
216   * <p>This method cannot be abstract for backward compatibility reasons. By
217   * default it always throws {@link UnsupportedOperationException} unless
218   * overridden.</p>
219   * 
220   * @since 1.4
221   */
222  public boolean isSiteLocalAddress()
223  {
224    throw new UnsupportedOperationException();
225  }
226
227  /**
228   * Utility routine to check if InetAddress is a global multicast address
229   *
230   * <p>This method cannot be abstract for backward compatibility reasons. By
231   * default it always throws {@link UnsupportedOperationException} unless
232   * overridden.</p>
233   * 
234   * @since 1.4
235   */
236  public boolean isMCGlobal()
237  {
238    throw new UnsupportedOperationException();
239  }
240
241  /**
242   * Utility routine to check if InetAddress is a node local multicast address.
243   *
244   * <p>This method cannot be abstract for backward compatibility reasons. By
245   * default it always throws {@link UnsupportedOperationException} unless
246   * overridden.</p>
247   * 
248   * @since 1.4
249   */
250  public boolean isMCNodeLocal()
251  {
252    throw new UnsupportedOperationException();
253  }
254
255  /**
256   * Utility routine to check if InetAddress is a link local multicast address.
257   *
258   * <p>This method cannot be abstract for backward compatibility reasons. By
259   * default it always throws {@link UnsupportedOperationException} unless
260   * overridden.</p>
261   * 
262   * @since 1.4
263   */
264  public boolean isMCLinkLocal()
265  {
266    throw new UnsupportedOperationException();
267  }
268
269  /**
270   * Utility routine to check if InetAddress is a site local multicast address.
271   *
272   * <p>This method cannot be abstract for backward compatibility reasons. By
273   * default it always throws {@link UnsupportedOperationException} unless
274   * overridden.</p>
275   * 
276   * @since 1.4
277   */
278  public boolean isMCSiteLocal()
279  {
280    throw new UnsupportedOperationException();
281  }
282
283  /**
284   * Utility routine to check if InetAddress is a organization local
285   * multicast address.
286   *
287   * <p>This method cannot be abstract for backward compatibility reasons. By
288   * default it always throws {@link UnsupportedOperationException} unless
289   * overridden.</p>
290   * 
291   * @since 1.4
292   */
293  public boolean isMCOrgLocal()
294  {
295    throw new UnsupportedOperationException();
296  }
297
298  /**
299   * Returns the hostname for this address.  This will return the IP address
300   * as a String if there is no hostname available for this address
301   *
302   * @return The hostname for this address
303   */
304  public String getHostName()
305  {
306    if (hostName == null)
307      hostName = getCanonicalHostName();
308
309    return hostName;
310  }
311
312  /**
313   * Returns the canonical hostname represented by this InetAddress
314   */
315  String internalGetCanonicalHostName()
316  {
317    try
318      {
319        return ResolverCache.getHostByAddr(addr);
320      }
321    catch (UnknownHostException e)
322      {
323        return getHostAddress();
324      }
325  }
326
327  /**
328   * Returns the canonical hostname represented by this InetAddress
329   * 
330   * @since 1.4
331   */
332  public String getCanonicalHostName()
333  {
334    String hostname = internalGetCanonicalHostName();
335
336    SecurityManager sm = System.getSecurityManager();
337    if (sm != null)
338      {
339        try
340          {
341            sm.checkConnect(hostname, -1);
342          }
343        catch (SecurityException e)
344          {
345            return getHostAddress();
346          }
347      }
348
349    return hostname;
350  }
351
352  /**
353   * Returns the IP address of this object as a byte array.
354   *
355   * @return IP address
356   */
357  public byte[] getAddress()
358  {
359    // An experiment shows that JDK1.2 returns a different byte array each
360    // time.  This makes sense, in terms of security.
361    return (byte[]) addr.clone();
362  }
363
364  /**
365   * Returns the IP address of this object as a String.
366   *
367   * <p>This method cannot be abstract for backward compatibility reasons. By
368   * default it always throws {@link UnsupportedOperationException} unless
369   * overridden.</p>
370   * 
371   * @return The IP address of this object in String form
372   *
373   * @since 1.0.2
374   */
375  public String getHostAddress()
376  {
377    throw new UnsupportedOperationException();
378  }
379
380  /**
381   * Returns a hash value for this address.  Useful for creating hash
382   * tables.  Overrides Object.hashCode()
383   *
384   * @return A hash value for this address.
385   */
386  public int hashCode()
387  {
388    // There hashing algorithm is not specified, but a simple experiment
389    // shows that it is equal to the address, as a 32-bit big-endian integer.
390    int hash = 0;
391    int len = addr.length;
392    int i = len > 4 ? len - 4 : 0;
393
394    for (; i < len; i++)
395      hash = (hash << 8) | (addr[i] & 0xff);
396
397    return hash;
398  }
399
400  /**
401   * Tests this address for equality against another InetAddress.  The two
402   * addresses are considered equal if they contain the exact same octets.
403   * This implementation overrides Object.equals()
404   *
405   * @param obj The address to test for equality
406   *
407   * @return true if the passed in object's address is equal to this one's,
408   * false otherwise
409   */
410  public boolean equals(Object obj)
411  {
412    if (! (obj instanceof InetAddress))
413      return false;
414
415    // "The Java Class Libraries" 2nd edition says "If a machine has
416    // multiple names instances of InetAddress for different name of
417    // that same machine are not equal.  This is because they have
418    // different host names."  This violates the description in the
419    // JDK 1.2 API documentation.  A little experimentation
420    // shows that the latter is correct.
421    byte[] addr2 = ((InetAddress) obj).addr;
422
423    if (addr.length != addr2.length)
424      return false;
425
426    for (int i = 0; i < addr.length; i++)
427      if (addr[i] != addr2[i])
428        return false;
429
430    return true;
431  }
432
433  /**
434   * Converts this address to a String.  This string contains the IP in
435   * dotted decimal form. For example: "127.0.0.1"  This method is equivalent
436   * to getHostAddress() and overrides Object.toString()
437   *
438   * @return This address in String form
439   */
440  public String toString()
441  {
442    String addr = getHostAddress();
443    String host = (hostName != null) ? hostName : "";
444    return host + "/" + addr;
445  }
446
447  /**
448   * Returns an InetAddress object given the raw IP address.
449   *
450   * The argument is in network byte order: the highest order byte of the
451   * address is in getAddress()[0].
452   *
453   * @param addr The IP address to create the InetAddress object from
454   *
455   * @exception UnknownHostException If IP address has illegal length
456   *
457   * @since 1.4
458   */
459  public static InetAddress getByAddress(byte[] addr)
460    throws UnknownHostException
461  {
462    return getByAddress(null, addr);
463  }
464
465  /**
466   * Creates an InetAddress based on the provided host name and IP address.
467   * No name service is checked for the validity of the address.
468   *
469   * @param host The hostname of the InetAddress object to create
470   * @param addr The IP address to create the InetAddress object from
471   *
472   * @exception UnknownHostException If IP address is of illegal length
473   *
474   * @since 1.4
475   */
476  public static InetAddress getByAddress(String host, byte[] addr)
477    throws UnknownHostException
478  {
479    if (addr.length == 4)
480      return new Inet4Address(addr, host);
481
482    if (addr.length == 16)
483      {
484        for (int i = 0; i < 12; i++)
485          {
486            if (addr[i] != (i < 10 ? 0 : (byte) 0xFF))
487              return new Inet6Address(addr, host);
488          }
489          
490        byte[] ip4addr = new byte[4];
491        ip4addr[0] = addr[12];
492        ip4addr[1] = addr[13];
493        ip4addr[2] = addr[14];
494        ip4addr[3] = addr[15];
495        return new Inet4Address(ip4addr, host);
496      }
497
498    throw new UnknownHostException("IP address has illegal length");
499  }
500
501  /**
502   * Returns an InetAddress object representing the IP address of
503   * the given literal IP address in dotted decimal format such as
504   * "127.0.0.1".  This is used by SocketPermission.setHostPort()
505   * to parse literal IP addresses without performing a DNS lookup.
506   *
507   * @param literal The literal IP address to create the InetAddress
508   * object from
509   *
510   * @return The address of the host as an InetAddress object, or
511   * null if the IP address is invalid.
512   */
513  static InetAddress getByLiteral(String literal)
514  {
515    byte[] address = VMInetAddress.aton(literal);
516    if (address == null)
517      return null;
518    
519    try
520      {
521        return getByAddress(address);
522      }
523    catch (UnknownHostException e)
524      {
525        throw (InternalError) new InternalError().initCause(e);
526      }
527  }
528
529  /**
530   * Returns an InetAddress object representing the IP address of the given
531   * hostname.  This name can be either a hostname such as "www.urbanophile.com"
532   * or an IP address in dotted decimal format such as "127.0.0.1".  If the
533   * hostname is null or "", the hostname of the local machine is supplied by
534   * default.  This method is equivalent to returning the first element in
535   * the InetAddress array returned from GetAllByName.
536   *
537   * @param hostname The name of the desired host, or null for the local 
538   * loopback address.
539   *
540   * @return The address of the host as an InetAddress object.
541   *
542   * @exception UnknownHostException If no IP address for the host could
543   * be found
544   * @exception SecurityException If a security manager exists and its
545   * checkConnect method doesn't allow the operation
546   */
547  public static InetAddress getByName(String hostname)
548    throws UnknownHostException
549  {
550    InetAddress[] addresses = getAllByName(hostname);
551    return addresses[0];
552  }
553
554  /**
555   * Returns an array of InetAddress objects representing all the host/ip
556   * addresses of a given host, given the host's name.  This name can be
557   * either a hostname such as "www.urbanophile.com" or an IP address in
558   * dotted decimal format such as "127.0.0.1".  If the value is null, the
559   * hostname of the local machine is supplied by default.
560   *
561   * @param hostname The name of the desired host, or null for the
562   * local loopback address.
563   *
564   * @return All addresses of the host as an array of InetAddress objects.
565   *
566   * @exception UnknownHostException If no IP address for the host could
567   * be found
568   * @exception SecurityException If a security manager exists and its
569   * checkConnect method doesn't allow the operation
570   */
571  public static InetAddress[] getAllByName(String hostname)
572    throws UnknownHostException
573  {
574    // If null or the empty string is supplied, the loopback address
575    // is returned.
576    if (hostname == null || hostname.length() == 0)
577      return new InetAddress[] {LOCALHOST};
578
579    // Check if hostname is an IP address
580    InetAddress address = getByLiteral(hostname);
581    if (address != null)
582      return new InetAddress[] {address};
583
584    // Perform security check before resolving
585    SecurityManager sm = System.getSecurityManager();
586    if (sm != null)
587      sm.checkConnect(hostname, -1);
588
589    // Resolve the hostname
590    byte[][] iplist = ResolverCache.getHostByName(hostname);
591    if (iplist.length == 0)
592      throw new UnknownHostException(hostname);
593
594    InetAddress[] addresses = new InetAddress[iplist.length];
595    for (int i = 0; i < iplist.length; i++)
596      addresses[i] = getByAddress(hostname, iplist[i]);
597
598    return addresses;
599  }
600
601  /**
602   * Returns an InetAddress object representing the address of the current
603   * host.
604   *
605   * @return The local host's address
606   *
607   * @exception UnknownHostException If no IP address for the host could
608   * be found
609   */
610  public static InetAddress getLocalHost() throws UnknownHostException
611  {
612    String hostname = VMInetAddress.getLocalHostname();
613    try
614      {
615        return getByName(hostname);
616      }
617    catch (SecurityException e)
618      {
619        return LOCALHOST;
620      }
621  }
622
623  /**
624   * Inet4Address objects are serialized as InetAddress objects.
625   * This deserializes them back into Inet4Address objects.
626   */
627  private Object readResolve() throws ObjectStreamException
628  {
629    return new Inet4Address(addr, hostName);
630  }
631
632  private void readObject(ObjectInputStream ois)
633    throws IOException, ClassNotFoundException
634  {
635    ois.defaultReadObject();
636    addr = new byte[4];
637    addr[3] = (byte) address;
638
639    for (int i = 2; i >= 0; --i)
640      addr[i] = (byte) (address >>= 8);
641  }
642
643  private void writeObject(ObjectOutputStream oos) throws IOException
644  {
645    // Build a 32 bit address from the last 4 bytes of a 4 byte IPv4 address
646    // or a 16 byte IPv6 address.
647    int len = addr.length;
648    int i = len - 4;
649
650    for (; i < len; i++)
651      address = address << 8 | (addr[i] & 0xff);
652
653    oos.defaultWriteObject();
654  }
655}