/* InetAddress.java -- Class to model an Internet address
   Copyright (C) 1998, 1999, 2002, 2004, 2005, 2006
   Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.net;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;

/**
 * This class models an Internet address.  It does not have a public
 * constructor.  Instead, new instances of this objects are created
 * using the static methods getLocalHost(), getByName(), and
 * getAllByName().
 *
 * <p>This class fulfills the function of the C style functions gethostname(),
 * gethostbyname(), and gethostbyaddr().  It resolves Internet DNS names
 * into their corresponding numeric addresses and vice versa.</p>
 *
 * @author Aaron M. Renn (arenn@urbanophile.com)
 * @author Per Bothner
 * @author Gary Benson (gbenson@redhat.com)
 *
 * @specnote This class is not final since JK 1.4
 */
public class InetAddress implements Serializable
{
  private static final long serialVersionUID = 3286316764910316507L;

  /**
   * Dummy InetAddress, used to bind socket to any (all) network interfaces.
   */
  static InetAddress ANY_IF;
  static
  {
    byte[] addr;
    try
      {
	addr = VMInetAddress.lookupInaddrAny();
      }
    catch (UnknownHostException e)
      {
	// Make one up and hope it works.
	addr = new byte[] {0, 0, 0, 0};
      }
    try
      {
	ANY_IF = getByAddress(addr);
      }
    catch (UnknownHostException e)
      {
	throw new RuntimeException("should never happen", e);
      }
    ANY_IF.hostName = ANY_IF.getHostName();
  }
  
  /**
   * Stores static localhost address object.
   */
  static InetAddress LOCALHOST;
  static
  {
    try
      {
	LOCALHOST = getByAddress("localhost", new byte[] {127, 0, 0, 1});
      }
    catch (UnknownHostException e)
      {
	throw new RuntimeException("should never happen", e);
      }
  }    

  /**
   * The Serialized Form specifies that an int 'address' is saved/restored.
   * This class uses a byte array internally so we'll just do the conversion
   * at serialization time and leave the rest of the algorithm as is.
   */
  private int address;

  /**
   * An array of octets representing an IP address.
   */
  transient byte[] addr;

  /**
   * The name of the host for this address.
   */
  String hostName;

  /**
   * Needed for serialization.
   */
  private int family;

  /**
   * Constructor.  Prior to the introduction of IPv6 support in 1.4,
   * methods such as InetAddress.getByName() would return InetAddress
   * objects.  From 1.4 such methods returned either Inet4Address or
   * Inet6Address objects, but for compatibility Inet4Address objects
   * are serialized as InetAddresses.  As such, there are only two
   * places where it is appropriate to invoke this constructor: within
   * subclasses constructors and within Inet4Address.writeReplace().
   *
   * @param ipaddr The IP number of this address as an array of bytes
   * @param hostname The hostname of this IP address.
   * @param family The address family of this IP address.
   */
  InetAddress(byte[] ipaddr, String hostname, int family)
  {
    addr = (null == ipaddr) ? null : (byte[]) ipaddr.clone();
    hostName = hostname;
    this.family = family;
  }

  /**
   * Returns true if this address is a multicast address, false otherwise.
   * An address is multicast if the high four bits are "1110".  These are
   * also known as "Class D" addresses.
   *
   * <p>This method cannot be abstract for backward compatibility reasons. By
   * default it always throws {@link UnsupportedOperationException} unless
   * overridden.</p>
   * 
   * @return true if mulitcast, false if not
   *
   * @since 1.1
   */
  public boolean isMulticastAddress()
  {
    throw new UnsupportedOperationException();
  }

  /**
   * Utility routine to check if the InetAddress in a wildcard address
   *
   * <p>This method cannot be abstract for backward compatibility reasons. By
   * default it always throws {@link UnsupportedOperationException} unless
   * overridden.</p>
   * 
   * @since 1.4
   */
  public boolean isAnyLocalAddress()
  {
    throw new UnsupportedOperationException();
  }

  /**
   * Utility routine to check if the InetAddress is a loopback address
   *
   * <p>This method cannot be abstract for backward compatibility reasons. By
   * default it always throws {@link UnsupportedOperationException} unless
   * overridden.</p>
   * 
   * @since 1.4
   */
  public boolean isLoopbackAddress()
  {
    throw new UnsupportedOperationException();
  }

  /**
   * Utility routine to check if InetAddress is a link local address
   *
   * <p>This method cannot be abstract for backward compatibility reasons. By
   * default it always throws {@link UnsupportedOperationException} unless
   * overridden.</p>
   * 
   * @since 1.4
   */
  public boolean isLinkLocalAddress()
  {
    throw new UnsupportedOperationException();
  }

  /**
   * Utility routine to check if InetAddress is a site local address
   *
   * <p>This method cannot be abstract for backward compatibility reasons. By
   * default it always throws {@link UnsupportedOperationException} unless
   * overridden.</p>
   * 
   * @since 1.4
   */
  public boolean isSiteLocalAddress()
  {
    throw new UnsupportedOperationException();
  }

  /**
   * Utility routine to check if InetAddress is a global multicast address
   *
   * <p>This method cannot be abstract for backward compatibility reasons. By
   * default it always throws {@link UnsupportedOperationException} unless
   * overridden.</p>
   * 
   * @since 1.4
   */
  public boolean isMCGlobal()
  {
    throw new UnsupportedOperationException();
  }

  /**
   * Utility routine to check if InetAddress is a node local multicast address.
   *
   * <p>This method cannot be abstract for backward compatibility reasons. By
   * default it always throws {@link UnsupportedOperationException} unless
   * overridden.</p>
   * 
   * @since 1.4
   */
  public boolean isMCNodeLocal()
  {
    throw new UnsupportedOperationException();
  }

  /**
   * Utility routine to check if InetAddress is a link local multicast address.
   *
   * <p>This method cannot be abstract for backward compatibility reasons. By
   * default it always throws {@link UnsupportedOperationException} unless
   * overridden.</p>
   * 
   * @since 1.4
   */
  public boolean isMCLinkLocal()
  {
    throw new UnsupportedOperationException();
  }

  /**
   * Utility routine to check if InetAddress is a site local multicast address.
   *
   * <p>This method cannot be abstract for backward compatibility reasons. By
   * default it always throws {@link UnsupportedOperationException} unless
   * overridden.</p>
   * 
   * @since 1.4
   */
  public boolean isMCSiteLocal()
  {
    throw new UnsupportedOperationException();
  }

  /**
   * Utility routine to check if InetAddress is a organization local
   * multicast address.
   *
   * <p>This method cannot be abstract for backward compatibility reasons. By
   * default it always throws {@link UnsupportedOperationException} unless
   * overridden.</p>
   * 
   * @since 1.4
   */
  public boolean isMCOrgLocal()
  {
    throw new UnsupportedOperationException();
  }

  /**
   * Returns the hostname for this address.  This will return the IP address
   * as a String if there is no hostname available for this address
   *
   * @return The hostname for this address
   */
  public String getHostName()
  {
    if (hostName == null)
      hostName = getCanonicalHostName();

    return hostName;
  }

  /**
   * Returns the canonical hostname represented by this InetAddress
   */
  String internalGetCanonicalHostName()
  {
    try
      {
	return ResolverCache.getHostByAddr(addr);
      }
    catch (UnknownHostException e)
      {
	return getHostAddress();
      }
  }

  /**
   * Returns the canonical hostname represented by this InetAddress
   * 
   * @since 1.4
   */
  public String getCanonicalHostName()
  {
    String hostname = internalGetCanonicalHostName();

    SecurityManager sm = System.getSecurityManager();
    if (sm != null)
      {
        try
	  {
            sm.checkConnect(hostname, -1);
	  }
	catch (SecurityException e)
	  {
	    return getHostAddress();
	  }
      }

    return hostname;
  }

  /**
   * Returns the IP address of this object as a byte array.
   *
   * @return IP address
   */
  public byte[] getAddress()
  {
    // An experiment shows that JDK1.2 returns a different byte array each
    // time.  This makes sense, in terms of security.
    return (byte[]) addr.clone();
  }

  /**
   * Returns the IP address of this object as a String.
   *
   * <p>This method cannot be abstract for backward compatibility reasons. By
   * default it always throws {@link UnsupportedOperationException} unless
   * overridden.</p>
   * 
   * @return The IP address of this object in String form
   *
   * @since 1.0.2
   */
  public String getHostAddress()
  {
    throw new UnsupportedOperationException();
  }

  /**
   * Returns a hash value for this address.  Useful for creating hash
   * tables.  Overrides Object.hashCode()
   *
   * @return A hash value for this address.
   */
  public int hashCode()
  {
    // There hashing algorithm is not specified, but a simple experiment
    // shows that it is equal to the address, as a 32-bit big-endian integer.
    int hash = 0;
    int len = addr.length;
    int i = len > 4 ? len - 4 : 0;

    for (; i < len; i++)
      hash = (hash << 8) | (addr[i] & 0xff);

    return hash;
  }

  /**
   * Tests this address for equality against another InetAddress.  The two
   * addresses are considered equal if they contain the exact same octets.
   * This implementation overrides Object.equals()
   *
   * @param obj The address to test for equality
   *
   * @return true if the passed in object's address is equal to this one's,
   * false otherwise
   */
  public boolean equals(Object obj)
  {
    if (! (obj instanceof InetAddress))
      return false;

    // "The Java Class Libraries" 2nd edition says "If a machine has
    // multiple names instances of InetAddress for different name of
    // that same machine are not equal.  This is because they have
    // different host names."  This violates the description in the
    // JDK 1.2 API documentation.  A little experimentation
    // shows that the latter is correct.
    byte[] addr2 = ((InetAddress) obj).addr;

    if (addr.length != addr2.length)
      return false;

    for (int i = 0; i < addr.length; i++)
      if (addr[i] != addr2[i])
	return false;

    return true;
  }

  /**
   * Converts this address to a String.  This string contains the IP in
   * dotted decimal form. For example: "127.0.0.1"  This method is equivalent
   * to getHostAddress() and overrides Object.toString()
   *
   * @return This address in String form
   */
  public String toString()
  {
    String addr = getHostAddress();
    String host = (hostName != null) ? hostName : "";
    return host + "/" + addr;
  }

  /**
   * Returns an InetAddress object given the raw IP address.
   *
   * The argument is in network byte order: the highest order byte of the
   * address is in getAddress()[0].
   *
   * @param addr The IP address to create the InetAddress object from
   *
   * @exception UnknownHostException If IP address has illegal length
   *
   * @since 1.4
   */
  public static InetAddress getByAddress(byte[] addr)
    throws UnknownHostException
  {
    return getByAddress(null, addr);
  }

  /**
   * Creates an InetAddress based on the provided host name and IP address.
   * No name service is checked for the validity of the address.
   *
   * @param host The hostname of the InetAddress object to create
   * @param addr The IP address to create the InetAddress object from
   *
   * @exception UnknownHostException If IP address is of illegal length
   *
   * @since 1.4
   */
  public static InetAddress getByAddress(String host, byte[] addr)
    throws UnknownHostException
  {
    if (addr.length == 4)
      return new Inet4Address(addr, host);

    if (addr.length == 16)
      {
	for (int i = 0; i < 12; i++)
	  {
	    if (addr[i] != (i < 10 ? 0 : (byte) 0xFF))
	      return new Inet6Address(addr, host);
	  }
	  
	byte[] ip4addr = new byte[4];
	ip4addr[0] = addr[12];
	ip4addr[1] = addr[13];
	ip4addr[2] = addr[14];
	ip4addr[3] = addr[15];
	return new Inet4Address(ip4addr, host);
      }

    throw new UnknownHostException("IP address has illegal length");
  }

  /**
   * Returns an InetAddress object representing the IP address of
   * the given literal IP address in dotted decimal format such as
   * "127.0.0.1".  This is used by SocketPermission.setHostPort()
   * to parse literal IP addresses without performing a DNS lookup.
   *
   * @param literal The literal IP address to create the InetAddress
   * object from
   *
   * @return The address of the host as an InetAddress object, or
   * null if the IP address is invalid.
   */
  static InetAddress getByLiteral(String literal)
  {
    byte[] address = VMInetAddress.aton(literal);
    if (address == null)
      return null;
    
    try
      {
	return getByAddress(address);
      }
    catch (UnknownHostException e)
      {
	throw new RuntimeException("should never happen", e);
      }
  }

  /**
   * Returns an InetAddress object representing the IP address of the given
   * hostname.  This name can be either a hostname such as "www.urbanophile.com"
   * or an IP address in dotted decimal format such as "127.0.0.1".  If the
   * hostname is null or "", the hostname of the local machine is supplied by
   * default.  This method is equivalent to returning the first element in
   * the InetAddress array returned from GetAllByName.
   *
   * @param hostname The name of the desired host, or null for the local 
   * loopback address.
   *
   * @return The address of the host as an InetAddress object.
   *
   * @exception UnknownHostException If no IP address for the host could
   * be found
   * @exception SecurityException If a security manager exists and its
   * checkConnect method doesn't allow the operation
   */
  public static InetAddress getByName(String hostname)
    throws UnknownHostException
  {
    InetAddress[] addresses = getAllByName(hostname);
    return addresses[0];
  }

  /**
   * Returns an array of InetAddress objects representing all the host/ip
   * addresses of a given host, given the host's name.  This name can be
   * either a hostname such as "www.urbanophile.com" or an IP address in
   * dotted decimal format such as "127.0.0.1".  If the value is null, the
   * hostname of the local machine is supplied by default.
   *
   * @param hostname The name of the desired host, or null for the
   * local loopback address.
   *
   * @return All addresses of the host as an array of InetAddress objects.
   *
   * @exception UnknownHostException If no IP address for the host could
   * be found
   * @exception SecurityException If a security manager exists and its
   * checkConnect method doesn't allow the operation
   */
  public static InetAddress[] getAllByName(String hostname)
    throws UnknownHostException
  {
    // If null or the empty string is supplied, the loopback address
    // is returned.
    if (hostname == null || hostname.length() == 0)
      return new InetAddress[] {LOCALHOST};

    // Check if hostname is an IP address
    InetAddress address = getByLiteral(hostname);
    if (address != null)
      return new InetAddress[] {address};

    // Perform security check before resolving
    SecurityManager sm = System.getSecurityManager();
    if (sm != null)
      sm.checkConnect(hostname, -1);

    // Resolve the hostname
    byte[][] iplist = ResolverCache.getHostByName(hostname);
    if (iplist.length == 0)
      throw new UnknownHostException(hostname);

    InetAddress[] addresses = new InetAddress[iplist.length];
    for (int i = 0; i < iplist.length; i++)
      addresses[i] = getByAddress(hostname, iplist[i]);

    return addresses;
  }

  /**
   * Returns an InetAddress object representing the address of the current
   * host.
   *
   * @return The local host's address
   *
   * @exception UnknownHostException If no IP address for the host could
   * be found
   */
  public static InetAddress getLocalHost() throws UnknownHostException
  {
    String hostname = VMInetAddress.getLocalHostname();
    try
      {
	return getByName(hostname);
      }
    catch (SecurityException e)
      {
	return LOCALHOST;
      }
  }

  /**
   * Inet4Address objects are serialized as InetAddress objects.
   * This deserializes them back into Inet4Address objects.
   */
  private Object readResolve() throws ObjectStreamException
  {
    return new Inet4Address(addr, hostName);
  }

  private void readObject(ObjectInputStream ois)
    throws IOException, ClassNotFoundException
  {
    ois.defaultReadObject();
    addr = new byte[4];
    addr[3] = (byte) address;

    for (int i = 2; i >= 0; --i)
      addr[i] = (byte) (address >>= 8);
  }

  private void writeObject(ObjectOutputStream oos) throws IOException
  {
    // Build a 32 bit address from the last 4 bytes of a 4 byte IPv4 address
    // or a 16 byte IPv6 address.
    int len = addr.length;
    int i = len - 4;

    for (; i < len; i++)
      address = address << 8 | (addr[i] & 0xff);

    oos.defaultWriteObject();
  }
}
