/* * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package java.net; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Random; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.ArrayList; import java.security.AccessController; import java.io.ObjectStreamException; import java.io.ObjectStreamField; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectInputStream.GetField; import java.io.ObjectOutputStream; import java.io.ObjectOutputStream.PutField; import sun.security.action.*; import sun.net.InetAddressCachePolicy; import sun.net.util.IPAddressUtil; import sun.misc.Service; import sun.net.spi.nameservice.*; /** * This class represents an Internet Protocol (IP) address. * *
An IP address is either a 32-bit or 128-bit unsigned number * used by IP, a lower-level protocol on which protocols like UDP and * TCP are built. The IP address architecture is defined by RFC 790: * Assigned Numbers, RFC 1918: * Address Allocation for Private Internets, RFC 2365: * Administratively Scoped IP Multicast, and RFC 2373: IP * Version 6 Addressing Architecture. An instance of an * InetAddress consists of an IP address and possibly its * corresponding host name (depending on whether it is constructed * with a host name or whether it has already done reverse host name * resolution). * *
* **
* unicast *An identifier for a single interface. A packet sent to * a unicast address is delivered to the interface identified by * that address. * * The Unspecified Address -- Also called anylocal or wildcard * address. It must never be assigned to any node. It indicates the * absence of an address. One example of its use is as the target of * bind, which allows a server to accept a client connection on any * interface, in case the server host has multiple interfaces. * *
The unspecified address must not be used as * the destination address of an IP packet. * *
The Loopback Addresses -- This is the address * assigned to the loopback interface. Anything sent to this * IP address loops around and becomes IP input on the local * host. This address is often used when testing a * client.
* multicast *An identifier for a set of interfaces (typically belonging * to different nodes). A packet sent to a multicast address is * delivered to all interfaces identified by that address.
Link-local addresses are designed to be used for addressing * on a single link for purposes such as auto-address configuration, * neighbor discovery, or when no routers are present. * *
Site-local addresses are designed to be used for addressing * inside of a site without the need for a global prefix. * *
Global addresses are unique across the internet. * *
* * For IPv4 address format, please refer to Inet4Address#format; For IPv6 * address format, please refer to Inet6Address#format. * *
There is a couple of * System Properties affecting how IPv4 and IPv6 addresses are used.
* *Reverse name resolution means that for any IP address, * the host associated with the IP address is returned. * *
The InetAddress class provides methods to resolve host names to * their IP addresses and vice versa. * *
By default, when a security manager is installed, in order to * protect against DNS spoofing attacks, * the result of positive host name resolutions are * cached forever. When a security manager is not installed, the default * behavior is to cache entries for a finite (implementation dependent) * period of time. The result of unsuccessful host * name resolution is cached for a very short period of time (10 * seconds) to improve performance. * *
If the default behavior is not desired, then a Java security property * can be set to a different Time-to-live (TTL) value for positive * caching. Likewise, a system admin can configure a different * negative caching TTL value when needed. * *
Two Java security properties control the TTL values used for * positive and negative host name resolution caching: * *
** * @author Chris Warth * @see java.net.InetAddress#getByAddress(byte[]) * @see java.net.InetAddress#getByAddress(java.lang.String, byte[]) * @see java.net.InetAddress#getAllByName(java.lang.String) * @see java.net.InetAddress#getByName(java.lang.String) * @see java.net.InetAddress#getLocalHost() * @since JDK1.0 */ public class InetAddress implements java.io.Serializable { /** * Specify the address family: Internet Protocol, Version 4 * @since 1.4 */ static final int IPv4 = 1; /** * Specify the address family: Internet Protocol, Version 6 * @since 1.4 */ static final int IPv6 = 2; /* Specify address family preference */ static transient boolean preferIPv6Address = false; static class InetAddressHolder { InetAddressHolder() {} InetAddressHolder(String hostName, int address, int family) { this.hostName = hostName; this.address = address; this.family = family; } String hostName; String getHostName() { return hostName; } /** * Holds a 32-bit IPv4 address. */ int address; int getAddress() { return address; } /** * Specifies the address family type, for instance, '1' for IPv4 * addresses, and '2' for IPv6 addresses. */ int family; int getFamily() { return family; } } final transient InetAddressHolder holder; InetAddressHolder holder() { return holder; } /* Used to store the name service provider */ private static List*
*- networkaddress.cache.ttl
*- Indicates the caching policy for successful name lookups from * the name service. The value is specified as as integer to indicate * the number of seconds to cache the successful lookup. The default * setting is to cache for an implementation specific period of time. *
** A value of -1 indicates "cache forever". *
*
- networkaddress.cache.negative.ttl (default: 10)
*- Indicates the caching policy for un-successful name lookups * from the name service. The value is specified as as integer to * indicate the number of seconds to cache the failure for * un-successful lookups. *
** A value of 0 indicates "never cache". * A value of -1 indicates "cache forever". *
boolean
indicating if the InetAddress is
* an IP multicast address
* @since JDK1.1
*/
public boolean isMulticastAddress() {
return false;
}
/**
* Utility routine to check if the InetAddress in a wildcard address.
* @return a boolean
indicating if the Inetaddress is
* a wildcard address.
* @since 1.4
*/
public boolean isAnyLocalAddress() {
return false;
}
/**
* Utility routine to check if the InetAddress is a loopback address.
*
* @return a boolean
indicating if the InetAddress is
* a loopback address; or false otherwise.
* @since 1.4
*/
public boolean isLoopbackAddress() {
return false;
}
/**
* Utility routine to check if the InetAddress is an link local address.
*
* @return a boolean
indicating if the InetAddress is
* a link local address; or false if address is not a link local unicast address.
* @since 1.4
*/
public boolean isLinkLocalAddress() {
return false;
}
/**
* Utility routine to check if the InetAddress is a site local address.
*
* @return a boolean
indicating if the InetAddress is
* a site local address; or false if address is not a site local unicast address.
* @since 1.4
*/
public boolean isSiteLocalAddress() {
return false;
}
/**
* Utility routine to check if the multicast address has global scope.
*
* @return a boolean
indicating if the address has
* is a multicast address of global scope, false if it is not
* of global scope or it is not a multicast address
* @since 1.4
*/
public boolean isMCGlobal() {
return false;
}
/**
* Utility routine to check if the multicast address has node scope.
*
* @return a boolean
indicating if the address has
* is a multicast address of node-local scope, false if it is not
* of node-local scope or it is not a multicast address
* @since 1.4
*/
public boolean isMCNodeLocal() {
return false;
}
/**
* Utility routine to check if the multicast address has link scope.
*
* @return a boolean
indicating if the address has
* is a multicast address of link-local scope, false if it is not
* of link-local scope or it is not a multicast address
* @since 1.4
*/
public boolean isMCLinkLocal() {
return false;
}
/**
* Utility routine to check if the multicast address has site scope.
*
* @return a boolean
indicating if the address has
* is a multicast address of site-local scope, false if it is not
* of site-local scope or it is not a multicast address
* @since 1.4
*/
public boolean isMCSiteLocal() {
return false;
}
/**
* Utility routine to check if the multicast address has organization scope.
*
* @return a boolean
indicating if the address has
* is a multicast address of organization-local scope,
* false if it is not of organization-local scope
* or it is not a multicast address
* @since 1.4
*/
public boolean isMCOrgLocal() {
return false;
}
/**
* Test whether that address is reachable. Best effort is made by the
* implementation to try to reach the host, but firewalls and server
* configuration may block requests resulting in a unreachable status
* while some specific ports may be accessible.
* A typical implementation will use ICMP ECHO REQUESTs if the
* privilege can be obtained, otherwise it will try to establish
* a TCP connection on port 7 (Echo) of the destination host.
*
* The timeout value, in milliseconds, indicates the maximum amount of time
* the try should take. If the operation times out before getting an
* answer, the host is deemed unreachable. A negative value will result
* in an IllegalArgumentException being thrown.
*
* @param timeout the time, in milliseconds, before the call aborts
* @return a boolean
indicating if the address is reachable.
* @throws IOException if a network error occurs
* @throws IllegalArgumentException if timeout
is negative.
* @since 1.5
*/
public boolean isReachable(int timeout) throws IOException {
return isReachable(null, 0 , timeout);
}
/**
* Test whether that address is reachable. Best effort is made by the
* implementation to try to reach the host, but firewalls and server
* configuration may block requests resulting in a unreachable status
* while some specific ports may be accessible.
* A typical implementation will use ICMP ECHO REQUESTs if the
* privilege can be obtained, otherwise it will try to establish
* a TCP connection on port 7 (Echo) of the destination host.
*
* The network interface
and ttl
parameters
* let the caller specify which network interface the test will go through
* and the maximum number of hops the packets should go through.
* A negative value for the ttl
will result in an
* IllegalArgumentException being thrown.
*
* The timeout value, in milliseconds, indicates the maximum amount of time
* the try should take. If the operation times out before getting an
* answer, the host is deemed unreachable. A negative value will result
* in an IllegalArgumentException being thrown.
*
* @param netif the NetworkInterface through which the
* test will be done, or null for any interface
* @param ttl the maximum numbers of hops to try or 0 for the
* default
* @param timeout the time, in milliseconds, before the call aborts
* @throws IllegalArgumentException if either timeout
* or ttl
are negative.
* @return a boolean
indicating if the address is reachable.
* @throws IOException if a network error occurs
* @since 1.5
*/
public boolean isReachable(NetworkInterface netif, int ttl,
int timeout) throws IOException {
if (ttl < 0)
throw new IllegalArgumentException("ttl can't be negative");
if (timeout < 0)
throw new IllegalArgumentException("timeout can't be negative");
return impl.isReachable(this, timeout, netif, ttl);
}
/**
* Gets the host name for this IP address.
*
*
If this InetAddress was created with a host name, * this host name will be remembered and returned; * otherwise, a reverse name lookup will be performed * and the result will be returned based on the system * configured name lookup service. If a lookup of the name service * is required, call * {@link #getCanonicalHostName() getCanonicalHostName}. * *
If there is a security manager, its
* checkConnect
method is first called
* with the hostname and -1
* as its arguments to see if the operation is allowed.
* If the operation is not allowed, it will return
* the textual representation of the IP address.
*
* @return the host name for this IP address, or if the operation
* is not allowed by the security check, the textual
* representation of the IP address.
*
* @see InetAddress#getCanonicalHostName
* @see SecurityManager#checkConnect
*/
public String getHostName() {
return getHostName(true);
}
/**
* Returns the hostname for this address.
* If the host is equal to null, then this address refers to any
* of the local machine's available network addresses.
* this is package private so SocketPermission can make calls into
* here without a security check.
*
*
If there is a security manager, this method first
* calls its checkConnect
method
* with the hostname and -1
* as its arguments to see if the calling code is allowed to know
* the hostname for this IP address, i.e., to connect to the host.
* If the operation is not allowed, it will return
* the textual representation of the IP address.
*
* @return the host name for this IP address, or if the operation
* is not allowed by the security check, the textual
* representation of the IP address.
*
* @param check make security check if true
*
* @see SecurityManager#checkConnect
*/
String getHostName(boolean check) {
if (holder().getHostName() == null) {
holder().hostName = InetAddress.getHostFromNameService(this, check);
}
return holder().getHostName();
}
/**
* Gets the fully qualified domain name for this IP address.
* Best effort method, meaning we may not be able to return
* the FQDN depending on the underlying system configuration.
*
*
If there is a security manager, this method first
* calls its checkConnect
method
* with the hostname and -1
* as its arguments to see if the calling code is allowed to know
* the hostname for this IP address, i.e., to connect to the host.
* If the operation is not allowed, it will return
* the textual representation of the IP address.
*
* @return the fully qualified domain name for this IP address,
* or if the operation is not allowed by the security check,
* the textual representation of the IP address.
*
* @see SecurityManager#checkConnect
*
* @since 1.4
*/
public String getCanonicalHostName() {
if (canonicalHostName == null) {
canonicalHostName =
InetAddress.getHostFromNameService(this, true);
}
return canonicalHostName;
}
/**
* Returns the hostname for this address.
*
*
If there is a security manager, this method first
* calls its checkConnect
method
* with the hostname and -1
* as its arguments to see if the calling code is allowed to know
* the hostname for this IP address, i.e., to connect to the host.
* If the operation is not allowed, it will return
* the textual representation of the IP address.
*
* @return the host name for this IP address, or if the operation
* is not allowed by the security check, the textual
* representation of the IP address.
*
* @param check make security check if true
*
* @see SecurityManager#checkConnect
*/
private static String getHostFromNameService(InetAddress addr, boolean check) {
String host = null;
for (NameService nameService : nameServices) {
try {
// first lookup the hostname
host = nameService.getHostByAddr(addr.getAddress());
/* check to see if calling code is allowed to know
* the hostname for this IP address, ie, connect to the host
*/
if (check) {
SecurityManager sec = System.getSecurityManager();
if (sec != null) {
sec.checkConnect(host, -1);
}
}
/* now get all the IP addresses for this hostname,
* and make sure one of them matches the original IP
* address. We do this to try and prevent spoofing.
*/
InetAddress[] arr = InetAddress.getAllByName0(host, check);
boolean ok = false;
if(arr != null) {
for(int i = 0; !ok && i < arr.length; i++) {
ok = addr.equals(arr[i]);
}
}
//XXX: if it looks a spoof just return the address?
if (!ok) {
host = addr.getHostAddress();
return host;
}
break;
} catch (SecurityException e) {
host = addr.getHostAddress();
break;
} catch (UnknownHostException e) {
host = addr.getHostAddress();
// let next provider resolve the hostname
}
}
return host;
}
/**
* Returns the raw IP address of this InetAddress
* object. The result is in network byte order: the highest order
* byte of the address is in getAddress()[0]
.
*
* @return the raw IP address of this object.
*/
public byte[] getAddress() {
return null;
}
/**
* Returns the IP address string in textual presentation.
*
* @return the raw IP address in a string format.
* @since JDK1.0.2
*/
public String getHostAddress() {
return null;
}
/**
* Returns a hashcode for this IP address.
*
* @return a hash code value for this IP address.
*/
public int hashCode() {
return -1;
}
/**
* Compares this object against the specified object.
* The result is true
if and only if the argument is
* not null
and it represents the same IP address as
* this object.
*
* Two instances of The host name can either be a machine name, such as
* " No validity checking is done on the host name either.
*
* If addr specifies an IPv4 address an instance of Inet4Address
* will be returned; otherwise, an instance of Inet6Address
* will be returned.
*
* IPv4 address byte array must be 4 bytes long and IPv6 byte array
* must be 16 bytes long
*
* @param host the specified host
* @param addr the raw IP address in network byte order
* @return an InetAddress object created from the raw IP address.
* @exception UnknownHostException if IP address is of illegal length
* @since 1.4
*/
public static InetAddress getByAddress(String host, byte[] addr)
throws UnknownHostException {
if (host != null && host.length() > 0 && host.charAt(0) == '[') {
if (host.charAt(host.length()-1) == ']') {
host = host.substring(1, host.length() -1);
}
}
if (addr != null) {
if (addr.length == Inet4Address.INADDRSZ) {
return new Inet4Address(host, addr);
} else if (addr.length == Inet6Address.INADDRSZ) {
byte[] newAddr
= IPAddressUtil.convertFromIPv4MappedAddress(addr);
if (newAddr != null) {
return new Inet4Address(host, newAddr);
} else {
return new Inet6Address(host, addr);
}
}
}
throw new UnknownHostException("addr is of illegal length");
}
/**
* Determines the IP address of a host, given the host's name.
*
* The host name can either be a machine name, such as
* " For If the host is null then an InetAddress
* representing an address of the loopback interface is returned.
* See RFC 3330
* section 2 and RFC 2373
* section 2.5.3. The host name can either be a machine name, such as
* " For If the host is null then an InetAddress
* representing an address of the loopback interface is returned.
* See RFC 3330
* section 2 and RFC 2373
* section 2.5.3. If there is a security manager and
* The InetAddress returned will represent the IPv4
* loopback address, 127.0.0.1, or the IPv6 loopback
* address, ::1. The IPv4 loopback address returned
* is only one of many in the form 127.*.*.*
*
* @return the InetAddress loopback instance.
* @since 1.7
*/
public static InetAddress getLoopbackAddress() {
return impl.loopbackAddress();
}
/**
* check if the literal address string has %nn appended
* returns -1 if not, or the numeric value otherwise.
*
* %nn may also be a string that represents the displayName of
* a currently available NetworkInterface.
*/
private static int checkNumericZone (String s) throws UnknownHostException {
int percent = s.indexOf ('%');
int slen = s.length();
int digit, zone=0;
if (percent == -1) {
return -1;
}
for (int i=percent+1; i This method doesn't block, i.e. no reverse name service lookup
* is performed.
*
* IPv4 address byte array must be 4 bytes long and IPv6 byte array
* must be 16 bytes long
*
* @param addr the raw IP address in network byte order
* @return an InetAddress object created from the raw IP address.
* @exception UnknownHostException if IP address is of illegal length
* @since 1.4
*/
public static InetAddress getByAddress(byte[] addr)
throws UnknownHostException {
return getByAddress(null, addr);
}
private static InetAddress cachedLocalHost = null;
private static long cacheTime = 0;
private static final long maxCacheTime = 5000L;
private static final Object cacheLock = new Object();
/**
* Returns the address of the local host. This is achieved by retrieving
* the name of the host from the system, then resolving that name into
* an Note: The resolved address may be cached for a short period of time.
* If there is a security manager, its
* InetAddress
represent the same IP
* address if the length of the byte arrays returned by
* getAddress
is the same for both, and each of the
* array components is the same for the byte arrays.
*
* @param obj the object to compare against.
* @return true
if the objects are the same;
* false
otherwise.
* @see java.net.InetAddress#getAddress()
*/
public boolean equals(Object obj) {
return false;
}
/**
* Converts this IP address to a String
. The
* string returned is of the form: hostname / literal IP
* address.
*
* If the host name is unresolved, no reverse name service lookup
* is performed. The hostname part will be represented by an empty string.
*
* @return a string representation of this IP address.
*/
public String toString() {
String hostName = holder().getHostName();
return ((hostName != null) ? hostName : "")
+ "/" + getHostAddress();
}
/*
* Cached addresses - our own litle nis, not!
*/
private static Cache addressCache = new Cache(Cache.Type.Positive);
private static Cache negativeCache = new Cache(Cache.Type.Negative);
private static boolean addressCacheInit = false;
static InetAddress[] unknown_array; // put THIS in cache
static InetAddressImpl impl;
private static final HashMapjava.sun.com
", or a textual representation of its IP
* address.
* java.sun.com
", or a textual representation of its
* IP address. If a literal IP address is supplied, only the
* validity of the address format is checked.
*
* host
specified in literal IPv6 address,
* either the form defined in RFC 2732 or the literal IPv6 address
* format defined in RFC 2373 is accepted. IPv6 scoped addresses are also
* supported. See here for a description of IPv6
* scoped addresses.
*
* null
.
* @return an IP address for the given host name.
* @exception UnknownHostException if no IP address for the
* host
could be found, or if a scope_id was specified
* for a global IPv6 address.
* @exception SecurityException if a security manager exists
* and its checkConnect method doesn't allow the operation
*/
public static InetAddress getByName(String host)
throws UnknownHostException {
return InetAddress.getAllByName(host)[0];
}
// called from deployment cache manager
private static InetAddress getByName(String host, InetAddress reqAddr)
throws UnknownHostException {
return InetAddress.getAllByName(host, reqAddr)[0];
}
/**
* Given the name of a host, returns an array of its IP addresses,
* based on the configured name service on the system.
*
* java.sun.com
", or a textual representation of its IP
* address. If a literal IP address is supplied, only the
* validity of the address format is checked.
*
* host
specified in literal IPv6 address,
* either the form defined in RFC 2732 or the literal IPv6 address
* format defined in RFC 2373 is accepted. A literal IPv6 address may
* also be qualified by appending a scoped zone identifier or scope_id.
* The syntax and usage of scope_ids is described
* here.
* host
is not
* null and host.length()
is not equal to zero, the
* security manager's
* checkConnect
method is called
* with the hostname and -1
* as its arguments to see if the operation is allowed.
*
* @param host the name of the host, or null
.
* @return an array of all the IP addresses for a given host name.
*
* @exception UnknownHostException if no IP address for the
* host
could be found, or if a scope_id was specified
* for a global IPv6 address.
* @exception SecurityException if a security manager exists and its
* checkConnect
method doesn't allow the operation.
*
* @see SecurityManager#checkConnect
*/
public static InetAddress[] getAllByName(String host)
throws UnknownHostException {
return getAllByName(host, null);
}
private static InetAddress[] getAllByName(String host, InetAddress reqAddr)
throws UnknownHostException {
if (host == null || host.length() == 0) {
InetAddress[] ret = new InetAddress[1];
ret[0] = impl.loopbackAddress();
return ret;
}
boolean ipv6Expected = false;
if (host.charAt(0) == '[') {
// This is supposed to be an IPv6 literal
if (host.length() > 2 && host.charAt(host.length()-1) == ']') {
host = host.substring(1, host.length() -1);
ipv6Expected = true;
} else {
// This was supposed to be a IPv6 address, but it's not!
throw new UnknownHostException(host + ": invalid IPv6 address");
}
}
// if host is an IP address, we won't do further lookup
if (Character.digit(host.charAt(0), 16) != -1
|| (host.charAt(0) == ':')) {
byte[] addr = null;
int numericZone = -1;
String ifname = null;
// see if it is IPv4 address
addr = IPAddressUtil.textToNumericFormatV4(host);
if (addr == null) {
// see if it is IPv6 address
// Check if a numeric or string zone id is present
int pos;
if ((pos=host.indexOf ("%")) != -1) {
numericZone = checkNumericZone (host);
if (numericZone == -1) { /* remainder of string must be an ifname */
ifname = host.substring (pos+1);
}
}
addr = IPAddressUtil.textToNumericFormatV6(host);
} else if (ipv6Expected) {
// Means an IPv4 litteral between brackets!
throw new UnknownHostException("["+host+"]");
}
InetAddress[] ret = new InetAddress[1];
if(addr != null) {
if (addr.length == Inet4Address.INADDRSZ) {
ret[0] = new Inet4Address(null, addr);
} else {
if (ifname != null) {
ret[0] = new Inet6Address(null, addr, ifname);
} else {
ret[0] = new Inet6Address(null, addr, numericZone);
}
}
return ret;
}
} else if (ipv6Expected) {
// We were expecting an IPv6 Litteral, but got something else
throw new UnknownHostException("["+host+"]");
}
return getAllByName0(host, reqAddr, true);
}
/**
* Returns the loopback address.
* 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]
.
*
* InetAddress
.
*
* checkConnect
method is called
* with the local host name and -1
* as its arguments to see if the operation is allowed.
* If the operation is not allowed, an InetAddress representing
* the loopback address is returned.
*
* @return the address of the local host.
*
* @exception UnknownHostException if the local host name could not
* be resolved into an address.
*
* @see SecurityManager#checkConnect
* @see java.net.InetAddress#getByName(java.lang.String)
*/
public static InetAddress getLocalHost() throws UnknownHostException {
SecurityManager security = System.getSecurityManager();
try {
String local = impl.getLocalHostName();
if (security != null) {
security.checkConnect(local, -1);
}
if (local.equals("localhost")) {
return impl.loopbackAddress();
}
InetAddress ret = null;
synchronized (cacheLock) {
long now = System.currentTimeMillis();
if (cachedLocalHost != null) {
if ((now - cacheTime) < maxCacheTime) // Less than 5s old?
ret = cachedLocalHost;
else
cachedLocalHost = null;
}
// we are calling getAddressesFromNameService directly
// to avoid getting localHost from cache
if (ret == null) {
InetAddress[] localAddrs;
try {
localAddrs =
InetAddress.getAddressesFromNameService(local, null);
} catch (UnknownHostException uhe) {
// Rethrow with a more informative error message.
UnknownHostException uhe2 =
new UnknownHostException(local + ": " +
uhe.getMessage());
uhe2.initCause(uhe);
throw uhe2;
}
cachedLocalHost = localAddrs[0];
cacheTime = now;
ret = localAddrs[0];
}
}
return ret;
} catch (java.lang.SecurityException e) {
return impl.loopbackAddress();
}
}
/**
* Perform class load-time initializations.
*/
private static native void init();
/*
* Returns the InetAddress representing anyLocalAddress
* (typically 0.0.0.0 or ::0)
*/
static InetAddress anyLocalAddress() {
return impl.anyLocalAddress();
}
/*
* Load and instantiate an underlying impl class
*/
static InetAddressImpl loadImpl(String implName) {
Object impl = null;
/*
* Property "impl.prefix" will be prepended to the classname
* of the implementation object we instantiate, to which we
* delegate the real work (like native methods). This
* property can vary across implementations of the java.
* classes. The default is an empty String "".
*/
String prefix = AccessController.doPrivileged(
new GetPropertyAction("impl.prefix", ""));
try {
impl = Class.forName("java.net." + prefix + implName).newInstance();
} catch (ClassNotFoundException e) {
System.err.println("Class not found: java.net." + prefix +
implName + ":\ncheck impl.prefix property " +
"in your properties file.");
} catch (InstantiationException e) {
System.err.println("Could not instantiate: java.net." + prefix +
implName + ":\ncheck impl.prefix property " +
"in your properties file.");
} catch (IllegalAccessException e) {
System.err.println("Cannot access class: java.net." + prefix +
implName + ":\ncheck impl.prefix property " +
"in your properties file.");
}
if (impl == null) {
try {
impl = Class.forName(implName).newInstance();
} catch (Exception e) {
throw new Error("System property impl.prefix incorrect");
}
}
return (InetAddressImpl) impl;
}
private void readObjectNoData (ObjectInputStream s) throws
IOException, ClassNotFoundException {
if (getClass().getClassLoader() != null) {
throw new SecurityException ("invalid address type");
}
}
private static final long FIELDS_OFFSET;
private static final sun.misc.Unsafe UNSAFE;
static {
try {
sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
FIELDS_OFFSET = unsafe.objectFieldOffset(
InetAddress.class.getDeclaredField("holder")
);
UNSAFE = unsafe;
} catch (ReflectiveOperationException e) {
throw new Error(e);
}
}
private void readObject (ObjectInputStream s) throws
IOException, ClassNotFoundException {
if (getClass().getClassLoader() != null) {
throw new SecurityException ("invalid address type");
}
GetField gf = s.readFields();
String host = (String)gf.get("hostName", null);
int address= gf.get("address", 0);
int family= gf.get("family", 0);
InetAddressHolder h = new InetAddressHolder(host, address, family);
UNSAFE.putObject(this, FIELDS_OFFSET, h);
}
/* needed because the serializable fields no longer exist */
/**
* @serialField hostName String
* @serialField address int
* @serialField family int
*/
private static final ObjectStreamField[] serialPersistentFields = {
new ObjectStreamField("hostName", String.class),
new ObjectStreamField("address", int.class),
new ObjectStreamField("family", int.class),
};
private void writeObject (ObjectOutputStream s) throws
IOException {
if (getClass().getClassLoader() != null) {
throw new SecurityException ("invalid address type");
}
PutField pf = s.putFields();
pf.put("hostName", holder().hostName);
pf.put("address", holder().address);
pf.put("family", holder().family);
s.writeFields();
s.flush();
}
}
/*
* Simple factory to create the impl
*/
class InetAddressImplFactory {
static InetAddressImpl create() {
return InetAddress.loadImpl(isIPv6Supported() ?
"Inet6AddressImpl" : "Inet4AddressImpl");
}
static native boolean isIPv6Supported();
}