| /* | |
| * Copyright (C) 2014 The Android Open Source Project | |
| * Copyright (c) 1995, 2015, 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.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 libcore.net.InetAddressUtils; | |
| import sun.net.util.IPAddressUtil; | |
| import sun.net.spi.nameservice.*; | |
| import libcore.io.Libcore; | |
| /** | |
| * This class represents an Internet Protocol (IP) address. | |
| * | |
| * <p> 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 <a | |
| * href="http://www.ietf.org/rfc/rfc790.txt"><i>RFC 790: | |
| * Assigned Numbers</i></a>, <a | |
| * href="http://www.ietf.org/rfc/rfc1918.txt"> <i>RFC 1918: | |
| * Address Allocation for Private Internets</i></a>, <a | |
| * href="http://www.ietf.org/rfc/rfc2365.txt"><i>RFC 2365: | |
| * Administratively Scoped IP Multicast</i></a>, and <a | |
| * href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC 2373: IP | |
| * Version 6 Addressing Architecture</i></a>. 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). | |
| * | |
| * <h3> Address types </h3> | |
| * | |
| * <blockquote><table cellspacing=2 summary="Description of unicast and multicast address types"> | |
| * <tr><th valign=top><i>unicast</i></th> | |
| * <td>An identifier for a single interface. A packet sent to | |
| * a unicast address is delivered to the interface identified by | |
| * that address. | |
| * | |
| * <p> 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. | |
| * | |
| * <p> The <i>unspecified</i> address must not be used as | |
| * the destination address of an IP packet. | |
| * | |
| * <p> The <i>Loopback</i> 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.</td></tr> | |
| * <tr><th valign=top><i>multicast</i></th> | |
| * <td>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.</td></tr> | |
| * </table></blockquote> | |
| * | |
| * <h4> IP address scope </h4> | |
| * | |
| * <p> <i>Link-local</i> 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. | |
| * | |
| * <p> <i>Site-local</i> addresses are designed to be used for addressing | |
| * inside of a site without the need for a global prefix. | |
| * | |
| * <p> <i>Global</i> addresses are unique across the internet. | |
| * | |
| * <h4> Textual representation of IP addresses </h4> | |
| * | |
| * The textual representation of an IP address is address family specific. | |
| * | |
| * <p> | |
| * | |
| * For IPv4 address format, please refer to <A | |
| * HREF="Inet4Address.html#format">Inet4Address#format</A>; For IPv6 | |
| * address format, please refer to <A | |
| * HREF="Inet6Address.html#format">Inet6Address#format</A>. | |
| * | |
| * <P>There is a <a href="doc-files/net-properties.html#Ipv4IPv6">couple of | |
| * System Properties</a> affecting how IPv4 and IPv6 addresses are used.</P> | |
| * | |
| * <h4> Host Name Resolution </h4> | |
| * | |
| * Host name-to-IP address <i>resolution</i> is accomplished through | |
| * the use of a combination of local machine configuration information | |
| * and network naming services such as the Domain Name System (DNS) | |
| * and Network Information Service(NIS). The particular naming | |
| * services(s) being used is by default the local machine configured | |
| * one. For any host name, its corresponding IP address is returned. | |
| * | |
| * <p> <i>Reverse name resolution</i> means that for any IP address, | |
| * the host associated with the IP address is returned. | |
| * | |
| * <p> The InetAddress class provides methods to resolve host names to | |
| * their IP addresses and vice versa. | |
| * | |
| * <h4> InetAddress Caching </h4> | |
| * | |
| * The InetAddress class has a cache to store successful as well as | |
| * unsuccessful host name resolutions. | |
| * | |
| * <p> 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. | |
| * | |
| * <p> 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. | |
| * | |
| * <p> Two Java security properties control the TTL values used for | |
| * positive and negative host name resolution caching: | |
| * | |
| * <blockquote> | |
| * <dl> | |
| * <dt><b>networkaddress.cache.ttl</b></dt> | |
| * <dd>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. | |
| * <p> | |
| * A value of -1 indicates "cache forever". | |
| * </dd> | |
| * <dt><b>networkaddress.cache.negative.ttl</b> (default: 10)</dt> | |
| * <dd>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. | |
| * <p> | |
| * A value of 0 indicates "never cache". | |
| * A value of -1 indicates "cache forever". | |
| * </dd> | |
| * </dl> | |
| * </blockquote> | |
| * | |
| * @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 { | |
| // BEGIN Android-removed: Android uses linux-based OsConstants. | |
| /* | |
| * 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; | |
| */ | |
| // END Android-removed: Android uses linux-based OsConstants. | |
| // Android-removed: Android doesn't support the preference. | |
| // /* Specify address family preference */ | |
| //static transient boolean preferIPv6Address = false; | |
| static class InetAddressHolder { | |
| /** | |
| * Reserve the original application specified hostname. | |
| * | |
| * The original hostname is useful for domain-based endpoint | |
| * identification (see RFC 2818 and RFC 6125). If an address | |
| * was created with a raw IP address, a reverse name lookup | |
| * may introduce endpoint identification security issue via | |
| * DNS forging. | |
| * | |
| * Oracle JSSE provider is using this original hostname, via | |
| * sun.misc.JavaNetAccess, for SSL/TLS endpoint identification. | |
| * | |
| * Note: May define a new public method in the future if necessary. | |
| */ | |
| String originalHostName; | |
| InetAddressHolder() {} | |
| InetAddressHolder(String hostName, int address, int family) { | |
| this.originalHostName = hostName; | |
| this.hostName = hostName; | |
| this.address = address; | |
| this.family = family; | |
| } | |
| void init(String hostName, int family) { | |
| this.originalHostName = hostName; | |
| this.hostName = hostName; | |
| if (family != -1) { | |
| this.family = family; | |
| } | |
| } | |
| String hostName; | |
| String getHostName() { | |
| return hostName; | |
| } | |
| String getOriginalHostName() { | |
| return originalHostName; | |
| } | |
| /** | |
| * Holds a 32-bit IPv4 address. | |
| */ | |
| int address; | |
| int getAddress() { | |
| return address; | |
| } | |
| // Android-changed: Documentation: use Linux-based OsConstants. | |
| /** | |
| * Specifies the address family type, for instance, AF_INET for IPv4 | |
| * addresses, and AF_INET6 for IPv6 addresses. | |
| */ | |
| int family; | |
| int getFamily() { | |
| return family; | |
| } | |
| } | |
| transient InetAddressHolder holder; | |
| InetAddressHolder holder() { | |
| return holder; | |
| } | |
| /* The implementation is always dual stack IPv6/IPv4 on android */ | |
| static final InetAddressImpl impl = new Inet6AddressImpl(); | |
| /* Used to store the name service provider */ | |
| // Android-changed: Android has only one name service. | |
| // Android doesn't allow user to provide custom name services. | |
| // private static List<NameService> nameServices = null; | |
| private static final NameService nameService = new NameService() { | |
| public InetAddress[] lookupAllHostAddr(String host, int netId) | |
| throws UnknownHostException { | |
| return impl.lookupAllHostAddr(host, netId); | |
| } | |
| public String getHostByAddr(byte[] addr) | |
| throws UnknownHostException { | |
| return impl.getHostByAddr(addr); | |
| } | |
| }; | |
| /* Used to store the best available hostname */ | |
| private transient String canonicalHostName = null; | |
| /** use serialVersionUID from JDK 1.0.2 for interoperability */ | |
| private static final long serialVersionUID = 3286316764910316507L; | |
| // BEGIN Android-removed: Android doesn't need to load native library. | |
| /* | |
| * Load net library into runtime, and perform initializations. | |
| * | |
| static { | |
| preferIPv6Address = java.security.AccessController.doPrivileged( | |
| new GetBooleanAction("java.net.preferIPv6Addresses")).booleanValue(); | |
| AccessController.doPrivileged( | |
| new java.security.PrivilegedAction<Void>() { | |
| public Void run() { | |
| System.loadLibrary("net"); | |
| return null; | |
| } | |
| }); | |
| init(); | |
| } | |
| */ | |
| // END Android-removed: Android doesn't need to load native library. | |
| /** | |
| * Constructor for the Socket.accept() method. | |
| * This creates an empty InetAddress, which is filled in by | |
| * the accept() method. This InetAddress, however, is not | |
| * put in the address cache, since it is not created by name. | |
| */ | |
| InetAddress() { | |
| holder = new InetAddressHolder(); | |
| } | |
| /** | |
| * Replaces the de-serialized object with an Inet4Address object. | |
| * | |
| * @return the alternate object to the de-serialized object. | |
| * | |
| * @throws ObjectStreamException if a new object replacing this | |
| * object could not be created | |
| */ | |
| private Object readResolve() throws ObjectStreamException { | |
| // will replace the deserialized 'this' object | |
| return new Inet4Address(holder().getHostName(), holder().getAddress()); | |
| } | |
| /** | |
| * Utility routine to check if the InetAddress is an | |
| * IP multicast address. | |
| * @return a {@code 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 {@code 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 {@code 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 {@code 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 {@code 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 {@code 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 {@code 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 {@code 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 {@code 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 {@code 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; | |
| } | |
| // Android-changed: Document that impl tries ICMP ECHO REQUESTs first. | |
| // The sole implementation, Inet6AddressImpl.isReachable(), tries ICMP ECHO REQUESTs before | |
| // TCP ECHO REQUESTs on Android. On Android, these are both possible without root access. | |
| /** | |
| * 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. | |
| * <p> | |
| * Android implementation attempts ICMP ECHO REQUESTs first, on failure it | |
| * will fall back to TCP ECHO REQUESTs. Success on either protocol will | |
| * return true. | |
| * <p> | |
| * 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 {@code boolean} indicating if the address is reachable. | |
| * @throws IOException if a network error occurs | |
| * @throws IllegalArgumentException if {@code timeout} is negative. | |
| * @since 1.5 | |
| */ | |
| public boolean isReachable(int timeout) throws IOException { | |
| return isReachable(null, 0 , timeout); | |
| } | |
| // Android-changed: Document that impl tries ICMP ECHO REQUESTs first. | |
| // The sole implementation, Inet6AddressImpl.isReachable(), tries ICMP ECHO REQUESTs before | |
| // TCP ECHO REQUESTs on Android. On Android, these are both possible without root access. | |
| /** | |
| * 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. | |
| * <p> | |
| * Android implementation attempts ICMP ECHO REQUESTs first, on failure it | |
| * will fall back to TCP ECHO REQUESTs. Success on either protocol will | |
| * return true. | |
| * <p> | |
| * The {@code network interface} and {@code 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 {@code ttl} will result in an | |
| * IllegalArgumentException being thrown. | |
| * <p> | |
| * 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 {@code timeout} | |
| * or {@code ttl} are negative. | |
| * @return a {@code 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); | |
| } | |
| // BEGIN Android-added: isReachableByICMP(timeout). | |
| /** | |
| * @hide For testing only | |
| */ | |
| public boolean isReachableByICMP(int timeout) throws IOException { | |
| return ((Inet6AddressImpl) impl).icmpEcho(this, timeout, null, 0); | |
| } | |
| // END Android-added: isReachableByICMP(timeout). | |
| /** | |
| * Gets the host name for this IP address. | |
| * | |
| * <p>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}. | |
| * | |
| * <p>If there is a security manager, its | |
| * {@code checkConnect} method is first called | |
| * with the hostname and {@code -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() { | |
| // Android-changed: Remove SecurityManager check. | |
| if (holder().getHostName() == null) { | |
| holder().hostName = InetAddress.getHostFromNameService(this); | |
| } | |
| return holder().getHostName(); | |
| } | |
| // BEGIN Android-removed: Android doesn't support SecurityManager. | |
| /* | |
| * 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. | |
| * | |
| * <p>If there is a security manager, this method first | |
| * calls its {@code checkConnect} method | |
| * with the hostname and {@code -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(); | |
| } | |
| */ | |
| // END Android-removed: Android doesn't support SecurityManager. | |
| /** | |
| * 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. | |
| * | |
| * <p>If there is a security manager, this method first | |
| * calls its {@code checkConnect} method | |
| * with the hostname and {@code -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() { | |
| // Android-changed: Remove SecurityManager check. | |
| if (canonicalHostName == null) { | |
| canonicalHostName = InetAddress.getHostFromNameService(this); | |
| } | |
| return canonicalHostName; | |
| } | |
| // Android-changed: Remove SecurityManager check. | |
| // * @param check make security check if true | |
| /** | |
| * Returns the hostname for this address. | |
| * | |
| * <p>If there is a security manager, this method first | |
| * calls its {@code checkConnect} method | |
| * with the hostname and {@code -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. | |
| * | |
| * @see SecurityManager#checkConnect | |
| */ | |
| private static String getHostFromNameService(InetAddress addr) { | |
| String host = null; | |
| try { | |
| // first lookup the hostname | |
| // Android-changed: Android has only one name service. | |
| host = nameService.getHostByAddr(addr.getAddress()); | |
| /* 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 = nameService.lookupAllHostAddr(host, NETID_UNSET); | |
| 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; | |
| } | |
| } catch (UnknownHostException e) { | |
| host = addr.getHostAddress(); | |
| } | |
| return host; | |
| } | |
| /** | |
| * Returns the raw IP address of this {@code InetAddress} | |
| * object. The result is in network byte order: the highest order | |
| * byte of the address is in {@code 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 {@code true} if and only if the argument is | |
| * not {@code null} and it represents the same IP address as | |
| * this object. | |
| * <p> | |
| * Two instances of {@code InetAddress} represent the same IP | |
| * address if the length of the byte arrays returned by | |
| * {@code 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 {@code true} if the objects are the same; | |
| * {@code false} otherwise. | |
| * @see java.net.InetAddress#getAddress() | |
| */ | |
| public boolean equals(Object obj) { | |
| return false; | |
| } | |
| /** | |
| * Converts this IP address to a {@code 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(); | |
| } | |
| // BEGIN Android-removed: Resolves a hostname using Libcore.os. | |
| /* | |
| * 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 HashMap<String, Void> lookupTable = new HashMap<>(); | |
| /** | |
| * Represents a cache entry | |
| * | |
| static final class CacheEntry { | |
| CacheEntry(InetAddress[] addresses, long expiration) { | |
| this.addresses = addresses; | |
| this.expiration = expiration; | |
| } | |
| InetAddress[] addresses; | |
| long expiration; | |
| } | |
| /** | |
| * A cache that manages entries based on a policy specified | |
| * at creation time. | |
| * | |
| static final class Cache { | |
| private LinkedHashMap<String, CacheEntry> cache; | |
| private Type type; | |
| enum Type {Positive, Negative}; | |
| /** | |
| * Create cache | |
| * | |
| public Cache(Type type) { | |
| this.type = type; | |
| cache = new LinkedHashMap<String, CacheEntry>(); | |
| } | |
| private int getPolicy() { | |
| if (type == Type.Positive) { | |
| return InetAddressCachePolicy.get(); | |
| } else { | |
| return InetAddressCachePolicy.getNegative(); | |
| } | |
| } | |
| /** | |
| * Add an entry to the cache. If there's already an | |
| * entry then for this host then the entry will be | |
| * replaced. | |
| * | |
| public Cache put(String host, InetAddress[] addresses) { | |
| int policy = getPolicy(); | |
| if (policy == InetAddressCachePolicy.NEVER) { | |
| return this; | |
| } | |
| // purge any expired entries | |
| if (policy != InetAddressCachePolicy.FOREVER) { | |
| // As we iterate in insertion order we can | |
| // terminate when a non-expired entry is found. | |
| LinkedList<String> expired = new LinkedList<>(); | |
| long now = System.currentTimeMillis(); | |
| for (String key : cache.keySet()) { | |
| CacheEntry entry = cache.get(key); | |
| if (entry.expiration >= 0 && entry.expiration < now) { | |
| expired.add(key); | |
| } else { | |
| break; | |
| } | |
| } | |
| for (String key : expired) { | |
| cache.remove(key); | |
| } | |
| } | |
| // create new entry and add it to the cache | |
| // -- as a HashMap replaces existing entries we | |
| // don't need to explicitly check if there is | |
| // already an entry for this host. | |
| long expiration; | |
| if (policy == InetAddressCachePolicy.FOREVER) { | |
| expiration = -1; | |
| } else { | |
| expiration = System.currentTimeMillis() + (policy * 1000); | |
| } | |
| CacheEntry entry = new CacheEntry(addresses, expiration); | |
| cache.put(host, entry); | |
| return this; | |
| } | |
| /** | |
| * Query the cache for the specific host. If found then | |
| * return its CacheEntry, or null if not found. | |
| * | |
| public CacheEntry get(String host) { | |
| int policy = getPolicy(); | |
| if (policy == InetAddressCachePolicy.NEVER) { | |
| return null; | |
| } | |
| CacheEntry entry = cache.get(host); | |
| // check if entry has expired | |
| if (entry != null && policy != InetAddressCachePolicy.FOREVER) { | |
| if (entry.expiration >= 0 && | |
| entry.expiration < System.currentTimeMillis()) { | |
| cache.remove(host); | |
| entry = null; | |
| } | |
| } | |
| return entry; | |
| } | |
| } | |
| /* | |
| * Initialize cache and insert anyLocalAddress into the | |
| * unknown array with no expiry. | |
| * | |
| private static void cacheInitIfNeeded() { | |
| assert Thread.holdsLock(addressCache); | |
| if (addressCacheInit) { | |
| return; | |
| } | |
| unknown_array = new InetAddress[1]; | |
| unknown_array[0] = impl.anyLocalAddress(); | |
| addressCache.put(impl.anyLocalAddress().getHostName(), | |
| unknown_array); | |
| addressCacheInit = true; | |
| } | |
| /* | |
| * Cache the given hostname and addresses. | |
| * | |
| private static void cacheAddresses(String hostname, | |
| InetAddress[] addresses, | |
| boolean success) { | |
| hostname = hostname.toLowerCase(); | |
| synchronized (addressCache) { | |
| cacheInitIfNeeded(); | |
| if (success) { | |
| addressCache.put(hostname, addresses); | |
| } else { | |
| negativeCache.put(hostname, addresses); | |
| } | |
| } | |
| } | |
| /* | |
| * Lookup hostname in cache (positive & negative cache). If | |
| * found return addresses, null if not found. | |
| * | |
| private static InetAddress[] getCachedAddresses(String hostname) { | |
| hostname = hostname.toLowerCase(); | |
| // search both positive & negative caches | |
| synchronized (addressCache) { | |
| cacheInitIfNeeded(); | |
| CacheEntry entry = addressCache.get(hostname); | |
| if (entry == null) { | |
| entry = negativeCache.get(hostname); | |
| } | |
| if (entry != null) { | |
| return entry.addresses; | |
| } | |
| } | |
| // not found | |
| return null; | |
| } | |
| private static NameService createNSProvider(String provider) { | |
| if (provider == null) | |
| return null; | |
| NameService nameService = null; | |
| if (provider.equals("default")) { | |
| // initialize the default name service | |
| nameService = new NameService() { | |
| public InetAddress[] lookupAllHostAddr(String host) | |
| throws UnknownHostException { | |
| return impl.lookupAllHostAddr(host); | |
| } | |
| public String getHostByAddr(byte[] addr) | |
| throws UnknownHostException { | |
| return impl.getHostByAddr(addr); | |
| } | |
| }; | |
| } else { | |
| final String providerName = provider; | |
| try { | |
| nameService = java.security.AccessController.doPrivileged( | |
| new java.security.PrivilegedExceptionAction<NameService>() { | |
| public NameService run() { | |
| Iterator<NameServiceDescriptor> itr = | |
| ServiceLoader.load(NameServiceDescriptor.class) | |
| .iterator(); | |
| while (itr.hasNext()) { | |
| NameServiceDescriptor nsd = itr.next(); | |
| if (providerName. | |
| equalsIgnoreCase(nsd.getType()+"," | |
| +nsd.getProviderName())) { | |
| try { | |
| return nsd.createNameService(); | |
| } catch (Exception e) { | |
| e.printStackTrace(); | |
| System.err.println( | |
| "Cannot create name service:" | |
| +providerName+": " + e); | |
| } | |
| } | |
| } | |
| return null; | |
| } | |
| } | |
| ); | |
| } catch (java.security.PrivilegedActionException e) { | |
| } | |
| } | |
| return nameService; | |
| } | |
| static { | |
| // create the impl | |
| impl = InetAddressImplFactory.create(); | |
| // get name service if provided and requested | |
| String provider = null;; | |
| String propPrefix = "sun.net.spi.nameservice.provider."; | |
| int n = 1; | |
| nameServices = new ArrayList<NameService>(); | |
| provider = AccessController.doPrivileged( | |
| new GetPropertyAction(propPrefix + n)); | |
| while (provider != null) { | |
| NameService ns = createNSProvider(provider); | |
| if (ns != null) | |
| nameServices.add(ns); | |
| n++; | |
| provider = AccessController.doPrivileged( | |
| new GetPropertyAction(propPrefix + n)); | |
| } | |
| // if not designate any name services provider, | |
| // create a default one | |
| if (nameServices.size() == 0) { | |
| NameService ns = createNSProvider("default"); | |
| nameServices.add(ns); | |
| } | |
| } | |
| */ | |
| // END Android-removed: Resolves a hostname using Libcore.os. | |
| /** | |
| * Creates an InetAddress based on the provided host name and IP address. | |
| * No name service is checked for the validity of the address. | |
| * | |
| * <p> The host name can either be a machine name, such as | |
| * "{@code java.sun.com}", or a textual representation of its IP | |
| * address. | |
| * <p> No validity checking is done on the host name either. | |
| * | |
| * <p> If addr specifies an IPv4 address an instance of Inet4Address | |
| * will be returned; otherwise, an instance of Inet6Address | |
| * will be returned. | |
| * | |
| * <p> 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 { | |
| return getByAddress(host, addr, -1 /* scopeId */); | |
| } | |
| // Android-added: Called by native code in Libcore.io. | |
| // Do not delete. Called from native code. | |
| private static InetAddress getByAddress(String host, byte[] addr, int scopeId) | |
| 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, scopeId); | |
| } | |
| } | |
| } | |
| throw new UnknownHostException("addr is of illegal length"); | |
| } | |
| /** | |
| * Determines the IP address of a host, given the host's name. | |
| * | |
| * <p> The host name can either be a machine name, such as | |
| * "{@code 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. | |
| * | |
| * <p> For {@code 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 <a href="Inet6Address.html#scoped">here</a> for a description of IPv6 | |
| * scoped addresses. | |
| * | |
| * <p> If the host is {@code null} then an {@code InetAddress} | |
| * representing an address of the loopback interface is returned. | |
| * See <a href="http://www.ietf.org/rfc/rfc3330.txt">RFC 3330</a> | |
| * section 2 and <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC 2373</a> | |
| * section 2.5.3. </p> | |
| * | |
| * @param host the specified host, or {@code null}. | |
| * @return an IP address for the given host name. | |
| * @exception UnknownHostException if no IP address for the | |
| * {@code 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 { | |
| // Android-changed: Rewritten on the top of Libcore.os. | |
| return impl.lookupAllHostAddr(host, NETID_UNSET)[0]; | |
| } | |
| /** | |
| * Given the name of a host, returns an array of its IP addresses, | |
| * based on the configured name service on the system. | |
| * | |
| * <p> The host name can either be a machine name, such as | |
| * "{@code 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. | |
| * | |
| * <p> For {@code host} specified in <i>literal IPv6 address</i>, | |
| * 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 | |
| * <a href="Inet6Address.html#scoped">here</a>. | |
| * <p> If the host is {@code null} then an {@code InetAddress} | |
| * representing an address of the loopback interface is returned. | |
| * See <a href="http://www.ietf.org/rfc/rfc3330.txt">RFC 3330</a> | |
| * section 2 and <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC 2373</a> | |
| * section 2.5.3. </p> | |
| * | |
| * <p> If there is a security manager and {@code host} is not | |
| * null and {@code host.length() } is not equal to zero, the | |
| * security manager's | |
| * {@code checkConnect} method is called | |
| * with the hostname and {@code -1} | |
| * as its arguments to see if the operation is allowed. | |
| * | |
| * @param host the name of the host, or {@code null}. | |
| * @return an array of all the IP addresses for a given host name. | |
| * | |
| * @exception UnknownHostException if no IP address for the | |
| * {@code 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 | |
| * {@code checkConnect} method doesn't allow the operation. | |
| * | |
| * @see SecurityManager#checkConnect | |
| */ | |
| public static InetAddress[] getAllByName(String host) | |
| throws UnknownHostException { | |
| // Android-changed: Resolves a hostname using Libcore.os. | |
| // Also, returns both the Inet4 and Inet6 loopback for null/empty host | |
| return impl.lookupAllHostAddr(host, NETID_UNSET).clone(); | |
| } | |
| /** | |
| * Returns the loopback address. | |
| * <p> | |
| * 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() { | |
| // Android-changed: Always returns IPv6 loopback address in Android. | |
| return impl.loopbackAddresses()[0]; | |
| } | |
| // BEGIN Android-removed: Resolves a hostname using Libcore.os. | |
| /* | |
| * 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<slen; i++) { | |
| char c = s.charAt(i); | |
| if (c == ']') { | |
| if (i == percent+1) { | |
| /* empty per-cent field * | |
| return -1; | |
| } | |
| break; | |
| } | |
| if ((digit = Character.digit (c, 10)) < 0) { | |
| return -1; | |
| } | |
| zone = (zone * 10) + digit; | |
| } | |
| return zone; | |
| } | |
| private static InetAddress[] getAllByName0 (String host) | |
| throws UnknownHostException | |
| { | |
| return getAllByName0(host, true); | |
| } | |
| /** | |
| * package private so SocketPermission can call it | |
| * | |
| static InetAddress[] getAllByName0 (String host, boolean check) | |
| throws UnknownHostException { | |
| return getAllByName0 (host, null, check); | |
| } | |
| private static InetAddress[] getAllByName0 (String host, InetAddress reqAddr, boolean check) | |
| throws UnknownHostException { | |
| /* If it gets here it is presumed to be a hostname */ | |
| /* Cache.get can return: null, unknownAddress, or InetAddress[] */ | |
| /* make sure the connection to the host is allowed, before we | |
| * give out a hostname | |
| * | |
| if (check) { | |
| SecurityManager security = System.getSecurityManager(); | |
| if (security != null) { | |
| security.checkConnect(host, -1); | |
| } | |
| } | |
| InetAddress[] addresses = getCachedAddresses(host); | |
| /* If no entry in cache, then do the host lookup * | |
| if (addresses == null) { | |
| addresses = getAddressesFromNameService(host, reqAddr); | |
| } | |
| if (addresses == unknown_array) | |
| throw new UnknownHostException(host); | |
| return addresses.clone(); | |
| } | |
| private static InetAddress[] getAddressesFromNameService(String host, InetAddress reqAddr) | |
| throws UnknownHostException | |
| { | |
| InetAddress[] addresses = null; | |
| boolean success = false; | |
| UnknownHostException ex = null; | |
| // Check whether the host is in the lookupTable. | |
| // 1) If the host isn't in the lookupTable when | |
| // checkLookupTable() is called, checkLookupTable() | |
| // would add the host in the lookupTable and | |
| // return null. So we will do the lookup. | |
| // 2) If the host is in the lookupTable when | |
| // checkLookupTable() is called, the current thread | |
| // would be blocked until the host is removed | |
| // from the lookupTable. Then this thread | |
| // should try to look up the addressCache. | |
| // i) if it found the addresses in the | |
| // addressCache, checkLookupTable() would | |
| // return the addresses. | |
| // ii) if it didn't find the addresses in the | |
| // addressCache for any reason, | |
| // it should add the host in the | |
| // lookupTable and return null so the | |
| // following code would do a lookup itself. | |
| if ((addresses = checkLookupTable(host)) == null) { | |
| try { | |
| // This is the first thread which looks up the addresses | |
| // this host or the cache entry for this host has been | |
| // expired so this thread should do the lookup. | |
| for (NameService nameService : nameServices) { | |
| try { | |
| /* | |
| * Do not put the call to lookup() inside the | |
| * constructor. if you do you will still be | |
| * allocating space when the lookup fails. | |
| * | |
| addresses = nameService.lookupAllHostAddr(host); | |
| success = true; | |
| break; | |
| } catch (UnknownHostException uhe) { | |
| if (host.equalsIgnoreCase("localhost")) { | |
| InetAddress[] local = new InetAddress[] { impl.loopbackAddress() }; | |
| addresses = local; | |
| success = true; | |
| break; | |
| } | |
| else { | |
| addresses = unknown_array; | |
| success = false; | |
| ex = uhe; | |
| } | |
| } | |
| } | |
| // More to do? | |
| if (reqAddr != null && addresses.length > 1 && !addresses[0].equals(reqAddr)) { | |
| // Find it? | |
| int i = 1; | |
| for (; i < addresses.length; i++) { | |
| if (addresses[i].equals(reqAddr)) { | |
| break; | |
| } | |
| } | |
| // Rotate | |
| if (i < addresses.length) { | |
| InetAddress tmp, tmp2 = reqAddr; | |
| for (int j = 0; j < i; j++) { | |
| tmp = addresses[j]; | |
| addresses[j] = tmp2; | |
| tmp2 = tmp; | |
| } | |
| addresses[i] = tmp2; | |
| } | |
| } | |
| // Cache the address. | |
| cacheAddresses(host, addresses, success); | |
| if (!success && ex != null) | |
| throw ex; | |
| } finally { | |
| // Delete host from the lookupTable and notify | |
| // all threads waiting on the lookupTable monitor. | |
| updateLookupTable(host); | |
| } | |
| } | |
| return addresses; | |
| } | |
| private static InetAddress[] checkLookupTable(String host) { | |
| synchronized (lookupTable) { | |
| // If the host isn't in the lookupTable, add it in the | |
| // lookuptable and return null. The caller should do | |
| // the lookup. | |
| if (lookupTable.containsKey(host) == false) { | |
| lookupTable.put(host, null); | |
| return null; | |
| } | |
| // If the host is in the lookupTable, it means that another | |
| // thread is trying to look up the addresses of this host. | |
| // This thread should wait. | |
| while (lookupTable.containsKey(host)) { | |
| try { | |
| lookupTable.wait(); | |
| } catch (InterruptedException e) { | |
| } | |
| } | |
| } | |
| // The other thread has finished looking up the addresses of | |
| // the host. This thread should retry to get the addresses | |
| // from the addressCache. If it doesn't get the addresses from | |
| // the cache, it will try to look up the addresses itself. | |
| InetAddress[] addresses = getCachedAddresses(host); | |
| if (addresses == null) { | |
| synchronized (lookupTable) { | |
| lookupTable.put(host, null); | |
| return null; | |
| } | |
| } | |
| return addresses; | |
| } | |
| private static void updateLookupTable(String host) { | |
| synchronized (lookupTable) { | |
| lookupTable.remove(host); | |
| lookupTable.notifyAll(); | |
| } | |
| } | |
| */ | |
| // END Android-removed: Resolves a hostname using Libcore.os. | |
| /** | |
| * Returns an {@code InetAddress} object given the raw IP address . | |
| * The argument is in network byte order: the highest order | |
| * byte of the address is in {@code getAddress()[0]}. | |
| * | |
| * <p> This method doesn't block, i.e. no reverse name service lookup | |
| * is performed. | |
| * | |
| * <p> 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); | |
| } | |
| // BEGIN Android-removed: Resolves a hostname using Libcore.os. | |
| /* | |
| private static InetAddress cachedLocalHost = null; | |
| private static long cacheTime = 0; | |
| private static final long maxCacheTime = 5000L; | |
| private static final Object cacheLock = new Object(); | |
| */ | |
| // END Android-removed: Resolves a hostname using Libcore.os. | |
| /** | |
| * 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 {@code InetAddress}. | |
| * | |
| * <P>Note: The resolved address may be cached for a short period of time. | |
| * </P> | |
| * | |
| * <p>If there is a security manager, its | |
| * {@code checkConnect} method is called | |
| * with the local host name and {@code -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 { | |
| // BEGIN Android-changed: Resolves a hostname using Libcore.os. | |
| /* | |
| 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(); | |
| } | |
| */ | |
| String local = Libcore.os.uname().nodename; | |
| return impl.lookupAllHostAddr(local, NETID_UNSET)[0]; | |
| // END Android-changed: Resolves a hostname using Libcore.os. | |
| } | |
| // BEGIN Android-removed: Android doesn't need to call native init. | |
| /** | |
| * Perform class load-time initializations. | |
| * | |
| private static native void init(); | |
| */ | |
| // END Android-removed: Android doesn't need to call native init. | |
| /* | |
| * Returns the InetAddress representing anyLocalAddress | |
| * (typically 0.0.0.0 or ::0) | |
| */ | |
| static InetAddress anyLocalAddress() { | |
| return impl.anyLocalAddress(); | |
| } | |
| // BEGIN Android-removed: Android doesn't load user-provided implementation. | |
| /* | |
| * 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; | |
| } | |
| */ | |
| // END Android-removed: Android doesn't load user-provided implementation. | |
| private void readObjectNoData (ObjectInputStream s) throws | |
| IOException, ClassNotFoundException { | |
| // Android-changed: Don't use null to mean the boot classloader. | |
| if (getClass().getClassLoader() != BOOT_CLASSLOADER) { | |
| throw new SecurityException ("invalid address type"); | |
| } | |
| } | |
| // Android-changed: Don't use null to mean the boot classloader. | |
| private static final ClassLoader BOOT_CLASSLOADER = Object.class.getClassLoader(); | |
| private void readObject (ObjectInputStream s) throws | |
| IOException, ClassNotFoundException { | |
| // Android-changed: Don't use null to mean the boot classloader. | |
| if (getClass().getClassLoader() != BOOT_CLASSLOADER) { | |
| 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); | |
| holder = new InetAddressHolder(host, address, family); | |
| } | |
| /* 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 { | |
| // Android-changed: Don't use null to mean the boot classloader. | |
| if (getClass().getClassLoader() != BOOT_CLASSLOADER) { | |
| 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(); | |
| } | |
| static final int NETID_UNSET = 0; | |
| // BEGIN Android-added: Add methods required by frameworks/base. | |
| // Particularly those required to deal with scope ids. | |
| /** | |
| * Returns true if the string is a valid numeric IPv4 or IPv6 address (such as "192.168.0.1"). | |
| * | |
| * <p>This copes with all forms of address that Java supports, detailed in the | |
| * {@link InetAddress} class documentation. An empty string is not treated as numeric. | |
| * | |
| * @hide used by frameworks/base to ensure that a getAllByName won't cause a DNS lookup. | |
| * @deprecated Use {@link InetAddressUtils#isNumericAddress(String)} instead, if possible. | |
| * @throws NullPointerException if the {@code address} is {@code null}. | |
| */ | |
| @Deprecated | |
| public static boolean isNumeric(String address) { | |
| return InetAddressUtils.parseNumericAddressNoThrowStripOptionalBrackets(address) != null; | |
| } | |
| /** | |
| * Returns an InetAddress corresponding to the given numeric address (such | |
| * as {@code "192.168.0.1"} or {@code "2001:4860:800d::68"}). | |
| * | |
| * <p>This method will never do a DNS lookup. Non-numeric addresses are errors. Passing either | |
| * an empty string or a {@code null} as the {@code numericAddress} will return the | |
| * {@link Inet6Address#LOOPBACK} address. | |
| * | |
| * @hide used by frameworks/base's NetworkUtils.numericToInetAddress | |
| * @throws IllegalArgumentException if {@code numericAddress} is not a numeric address | |
| * @deprecated Use {@link InetAddressUtils#parseNumericAddress(String)} instead, if possible. | |
| */ | |
| @Deprecated | |
| public static InetAddress parseNumericAddress(String numericAddress) { | |
| if (numericAddress == null || numericAddress.isEmpty()) { | |
| return Inet6Address.LOOPBACK; | |
| } | |
| InetAddress result = InetAddressUtils | |
| .parseNumericAddressNoThrowStripOptionalBrackets(numericAddress); | |
| if (result == null) { | |
| throw new IllegalArgumentException("Not a numeric address: " + numericAddress); | |
| } | |
| return result; | |
| } | |
| /** | |
| * Removes all entries from the VM's DNS cache. This does not affect the C library's DNS | |
| * cache, nor any caching DNS servers between you and the canonical server. | |
| * @hide | |
| */ | |
| public static void clearDnsCache() { | |
| impl.clearAddressCache(); | |
| } | |
| // END Android-added: Add methods required by frameworks/base. | |
| // BEGIN Android-added: Support for network (netId)-specific DNS resolution. | |
| /** | |
| * Operates identically to {@code getByName} except host resolution is | |
| * performed on the network designated by {@code netId}. | |
| * | |
| * @param host | |
| * the hostName to be resolved to an address or {@code null}. | |
| * @param netId the network to use for host resolution. | |
| * @return the {@code InetAddress} instance representing the host. | |
| * @throws UnknownHostException if the address lookup fails. | |
| * @hide | |
| */ | |
| public static InetAddress getByNameOnNet(String host, int netId) throws UnknownHostException { | |
| return impl.lookupAllHostAddr(host, netId)[0]; | |
| } | |
| /** | |
| * Operates identically to {@code getAllByName} except host resolution is | |
| * performed on the network designated by {@code netId}. | |
| * | |
| * @param host the hostname or literal IP string to be resolved. | |
| * @param netId the network to use for host resolution. | |
| * @return the array of addresses associated with the specified host. | |
| * @throws UnknownHostException if the address lookup fails. | |
| * @hide | |
| */ | |
| public static InetAddress[] getAllByNameOnNet(String host, int netId) throws UnknownHostException { | |
| return impl.lookupAllHostAddr(host, netId).clone(); | |
| } | |
| // END Android-added: Support for network (netId)-specific DNS resolution. | |
| } | |
| // BEGIN Android-removed: Android doesn't load user-provided implementation. | |
| /* | |
| * Simple factory to create the impl | |
| * | |
| class InetAddressImplFactory { | |
| static InetAddressImpl create() { | |
| return InetAddress.loadImpl(isIPv6Supported() ? | |
| "Inet6AddressImpl" : "Inet4AddressImpl"); | |
| } | |
| static native boolean isIPv6Supported(); | |
| } | |
| */ | |
| // END Android-removed: Android doesn't load user-provided implementation. |