diff options
Diffstat (limited to 'java/net/InetAddress.java')
-rw-r--r-- | java/net/InetAddress.java | 379 |
1 files changed, 175 insertions, 204 deletions
diff --git a/java/net/InetAddress.java b/java/net/InetAddress.java index ce65bc773..1f2667980 100644 --- a/java/net/InetAddress.java +++ b/java/net/InetAddress.java @@ -1,5 +1,6 @@ /* InetAddress.java -- Class to model an Internet address - Copyright (C) 1998, 1999, 2002, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2002, 2004, 2005, 2006 + Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -43,7 +44,6 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamException; import java.io.Serializable; -import java.util.StringTokenizer; /** * This class models an Internet address. It does not have a public @@ -57,45 +57,56 @@ import java.util.StringTokenizer; * * @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 + * @specnote This class is not final since JDK 1.4 */ public class InetAddress implements Serializable { private static final long serialVersionUID = 3286316764910316507L; /** - * The special IP address INADDR_ANY. - */ - private static InetAddress inaddr_any; - - /** * 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 (InternalError) new InternalError().initCause(e); + } + ANY_IF.hostName = ANY_IF.getHostName(); + } + /** * Stores static localhost address object. */ static InetAddress LOCALHOST; - static { - // precompute the ANY_IF address try { - ANY_IF = getInaddrAny(); - - byte[] ip_localhost = { 127, 0, 0, 1 }; - LOCALHOST = new Inet4Address(ip_localhost, "localhost"); + LOCALHOST = getByAddress("localhost", new byte[] {127, 0, 0, 1}); } - catch (UnknownHostException uhe) + catch (UnknownHostException e) { - // Hmmm, make one up and hope that it works. - byte[] zeros = { 0, 0, 0, 0 }; - ANY_IF = new Inet4Address(zeros, "0.0.0.0"); + throw (InternalError) new InternalError().initCause(e); } - } + } /** * The Serialized Form specifies that an int 'address' is saved/restored. @@ -115,28 +126,28 @@ public class InetAddress implements Serializable String hostName; /** - * The field 'family' seems to be the AF_ value. - * FIXME: Much of the code in the other java.net classes does not make - * use of this family field. A better implementation would be to make - * use of getaddrinfo() and have other methods just check the family - * field rather than examining the length of the address each time. + * Needed for serialization. */ - int family; + private int family; /** - * Initializes this object's addr instance variable from the passed in - * byte array. Note that this constructor is protected and is called - * only by static methods in this class. + * 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) + InetAddress(byte[] ipaddr, String hostname, int family) { addr = (null == ipaddr) ? null : (byte[]) ipaddr.clone(); hostName = hostname; - - family = 2; /* AF_INET */ + this.family = family; } /** @@ -144,150 +155,144 @@ public class InetAddress implements Serializable * 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() { - // Mask against high order bits of 1110 - if (addr.length == 4) - return (addr[0] & 0xf0) == 0xe0; - - return false; + 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() { - // This is the IPv4 implementation. - // Any class derived from InetAddress should override this. - return equals(ANY_IF); + 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() { - // This is the IPv4 implementation. - // Any class derived from InetAddress should override this. - return (addr[0] & 0xff) == 0x7f; + 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() { - // This is the IPv4 implementation. - // Any class derived from InetAddress should override this. - // XXX: This seems to not exist with IPv4 addresses - return false; + 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() { - // This is the IPv4 implementation. - // Any class derived from InetAddress should override this. - - // 10.0.0.0/8 - if ((addr[0] & 0xff) == 0x0a) - return true; - - // 172.16.0.0/12 - if ((addr[0] & 0xff) == 0xac && (addr[1] & 0xf0) == 0x10) - return true; - - // 192.168.0.0/16 - if ((addr[0] & 0xff) == 0xc0 && (addr[1] & 0xff) == 0xa8) - return true; - - // XXX: Do we need to check more addresses here ? - return false; + 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() { - // This is the IPv4 implementation. - // Any class derived from InetAddress should override this. - // XXX: This seems to not exist with IPv4 addresses - return false; + 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() { - // This is the IPv4 implementation. - // Any class derived from InetAddress should override this. - // XXX: This seems to not exist with IPv4 addresses - return false; + 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() { - // This is the IPv4 implementation. - // Any class derived from InetAddress should override this. - if (! isMulticastAddress()) - return false; - - return ((addr[0] & 0xff) == 0xe0 - && (addr[1] & 0xff) == 0x00 - && (addr[2] & 0xff) == 0x00); + 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() { - // This is the IPv4 implementation. - // Any class derived from InetAddress should override this. - // XXX: This seems to not exist with IPv4 addresses - return false; + 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() { - // This is the IPv4 implementation. - // Any class derived from InetAddress should override this. - // XXX: This seems to not exist with IPv4 addresses - return false; + throw new UnsupportedOperationException(); } /** @@ -298,13 +303,20 @@ public class InetAddress implements Serializable */ public String getHostName() { - if (hostName != null) - return hostName; + if (hostName == null) + hostName = getCanonicalHostName(); + return hostName; + } + + /** + * Returns the canonical hostname represented by this InetAddress + */ + String internalGetCanonicalHostName() + { try { - hostName = VMInetAddress.getHostByAddr(addr); - return hostName; + return ResolverCache.getHostByAddr(addr); } catch (UnknownHostException e) { @@ -319,12 +331,14 @@ public class InetAddress implements Serializable */ public String getCanonicalHostName() { + String hostname = internalGetCanonicalHostName(); + SecurityManager sm = System.getSecurityManager(); if (sm != null) { try { - sm.checkConnect(hostName, -1); + sm.checkConnect(hostname, -1); } catch (SecurityException e) { @@ -332,16 +346,7 @@ public class InetAddress implements Serializable } } - // Try to find the FDQN now - InetAddress address; - byte[] ipaddr = getAddress(); - - if (ipaddr.length == 16) - address = new Inet6Address(getAddress(), null); - else - address = new Inet4Address(getAddress(), null); - - return address.getHostName(); + return hostname; } /** @@ -357,32 +362,19 @@ public class InetAddress implements Serializable } /** - * Returns the IP address of this object as a String. The address is in - * the dotted octet notation, for example, "127.0.0.1". + * 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() { - StringBuffer sb = new StringBuffer(40); - - int len = addr.length; - int i = 0; - - for ( ; ; ) - { - sb.append(addr[i] & 0xff); - i++; - - if (i == len) - break; - - sb.append('.'); - } - - return sb.toString(); + throw new UnsupportedOperationException(); } /** @@ -488,48 +480,50 @@ public class InetAddress implements Serializable return new Inet4Address(addr, host); if (addr.length == 16) - return new Inet6Address(addr, host); + { + 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"); } /** - * If hostname is a valid numeric IP address, return the numeric address. - * Otherwise, return null. + * 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 * - * @param hostname the name of the host + * @return The address of the host as an InetAddress object, or + * null if the IP address is invalid. */ - private static byte[] aton(String hostname) + static InetAddress getByLiteral(String literal) { - StringTokenizer st = new StringTokenizer(hostname, "."); - - if (st.countTokens() == 4) + byte[] address = VMInetAddress.aton(literal); + if (address == null) + return null; + + try { - int index; - byte[] address = new byte[4]; - - for (index = 0; index < 4; index++) - { - try - { - short n = Short.parseShort(st.nextToken()); - - if ((n < 0) || (n > 255)) - break; - - address[index] = (byte) n; - } - catch (NumberFormatException e) - { - break; - } - } - - if (index == 4) - return address; + return getByAddress(address); + } + catch (UnknownHostException e) + { + throw (InternalError) new InternalError().initCause(e); } - - return null; } /** @@ -577,63 +571,34 @@ public class InetAddress implements Serializable public static InetAddress[] getAllByName(String hostname) throws UnknownHostException { - SecurityManager s = System.getSecurityManager(); - if (s != null) - s.checkConnect(hostname, -1); - - InetAddress[] addresses; - - if (hostname != null) - hostname = hostname.trim(); + // If null or the empty string is supplied, the loopback address + // is returned. + if (hostname == null || hostname.length() == 0) + return new InetAddress[] {LOCALHOST}; - // Default to current host if necessary - if (hostname == null || hostname.equals("")) - { - addresses = new InetAddress[1]; - addresses[0] = LOCALHOST; - return addresses; - } + // Check if hostname is an IP address + InetAddress address = getByLiteral(hostname); + if (address != null) + return new InetAddress[] {address}; - // Not in cache, try the lookup - byte[][] iplist = VMInetAddress.getHostByName(hostname); + // 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); - addresses = new InetAddress[iplist.length]; - + InetAddress[] addresses = new InetAddress[iplist.length]; for (int i = 0; i < iplist.length; i++) - { - if (iplist[i].length != 4) - throw new UnknownHostException(hostname); - - addresses[i] = new Inet4Address(iplist[i], hostname); - } + addresses[i] = getByAddress(hostname, iplist[i]); return addresses; } /** - * Returns the special address INADDR_ANY used for binding to a local - * port on all IP addresses hosted by a the local host. - * - * @return An InetAddress object representing INDADDR_ANY - * - * @exception UnknownHostException If an error occurs - */ - static InetAddress getInaddrAny() throws UnknownHostException - { - if (inaddr_any == null) - { - byte[] tmp = VMInetAddress.lookupInaddrAny(); - inaddr_any = new Inet4Address(tmp, null); - inaddr_any.hostName = inaddr_any.getHostName(); - } - - return inaddr_any; - } - - /** * Returns an InetAddress object representing the address of the current * host. * @@ -645,11 +610,19 @@ public class InetAddress implements Serializable public static InetAddress getLocalHost() throws UnknownHostException { String hostname = VMInetAddress.getLocalHostname(); - return getByName(hostname); + try + { + return getByName(hostname); + } + catch (SecurityException e) + { + return LOCALHOST; + } } - /* - * Needed for serialization + /** + * Inet4Address objects are serialized as InetAddress objects. + * This deserializes them back into Inet4Address objects. */ private Object readResolve() throws ObjectStreamException { @@ -665,8 +638,6 @@ public class InetAddress implements Serializable for (int i = 2; i >= 0; --i) addr[i] = (byte) (address >>= 8); - - family = 2; /* AF_INET */ } private void writeObject(ObjectOutputStream oos) throws IOException |