InetAddress.java revision 93c98aac54848043518d85216782a0801e79ffe2
1/*
2 * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.net;
27
28import java.util.HashMap;
29import java.util.LinkedHashMap;
30import java.util.Random;
31import java.util.Iterator;
32import java.util.LinkedList;
33import java.util.List;
34import java.util.ArrayList;
35import java.security.AccessController;
36import java.io.ObjectStreamException;
37import java.io.ObjectStreamField;
38import java.io.IOException;
39import java.io.ObjectInputStream;
40import java.io.ObjectInputStream.GetField;
41import java.io.ObjectOutputStream;
42import java.io.ObjectOutputStream.PutField;
43import sun.security.action.*;
44import sun.net.InetAddressCachePolicy;
45import sun.net.util.IPAddressUtil;
46import sun.misc.Service;
47import sun.net.spi.nameservice.*;
48import android.system.ErrnoException;
49import android.system.GaiException;
50import android.system.StructAddrinfo;
51import dalvik.system.BlockGuard;
52import libcore.io.Libcore;
53import static android.system.OsConstants.*;
54
55/**
56 * This class represents an Internet Protocol (IP) address.
57 *
58 * <p> An IP address is either a 32-bit or 128-bit unsigned number
59 * used by IP, a lower-level protocol on which protocols like UDP and
60 * TCP are built. The IP address architecture is defined by <a
61 * href="http://www.ietf.org/rfc/rfc790.txt"><i>RFC&nbsp;790:
62 * Assigned Numbers</i></a>, <a
63 * href="http://www.ietf.org/rfc/rfc1918.txt"> <i>RFC&nbsp;1918:
64 * Address Allocation for Private Internets</i></a>, <a
65 * href="http://www.ietf.org/rfc/rfc2365.txt"><i>RFC&nbsp;2365:
66 * Administratively Scoped IP Multicast</i></a>, and <a
67 * href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC&nbsp;2373: IP
68 * Version 6 Addressing Architecture</i></a>. An instance of an
69 * InetAddress consists of an IP address and possibly its
70 * corresponding host name (depending on whether it is constructed
71 * with a host name or whether it has already done reverse host name
72 * resolution).
73 *
74 * <h4> Address types </h4>
75 *
76 * <blockquote><table cellspacing=2 summary="Description of unicast and multicast address types">
77 *   <tr><th valign=top><i>unicast</i></th>
78 *       <td>An identifier for a single interface. A packet sent to
79 *         a unicast address is delivered to the interface identified by
80 *         that address.
81 *
82 *         <p> The Unspecified Address -- Also called anylocal or wildcard
83 *         address. It must never be assigned to any node. It indicates the
84 *         absence of an address. One example of its use is as the target of
85 *         bind, which allows a server to accept a client connection on any
86 *         interface, in case the server host has multiple interfaces.
87 *
88 *         <p> The <i>unspecified</i> address must not be used as
89 *         the destination address of an IP packet.
90 *
91 *         <p> The <i>Loopback</i> Addresses -- This is the address
92 *         assigned to the loopback interface. Anything sent to this
93 *         IP address loops around and becomes IP input on the local
94 *         host. This address is often used when testing a
95 *         client.</td></tr>
96 *   <tr><th valign=top><i>multicast</i></th>
97 *       <td>An identifier for a set of interfaces (typically belonging
98 *         to different nodes). A packet sent to a multicast address is
99 *         delivered to all interfaces identified by that address.</td></tr>
100 * </table></blockquote>
101 *
102 * <h4> IP address scope </h4>
103 *
104 * <p> <i>Link-local</i> addresses are designed to be used for addressing
105 * on a single link for purposes such as auto-address configuration,
106 * neighbor discovery, or when no routers are present.
107 *
108 * <p> <i>Site-local</i> addresses are designed to be used for addressing
109 * inside of a site without the need for a global prefix.
110 *
111 * <p> <i>Global</i> addresses are unique across the internet.
112 *
113 * <h4> Textual representation of IP addresses </h4>
114 *
115 * The textual representation of an IP address is address family specific.
116 *
117 * <p>
118 *
119 * For IPv4 address format, please refer to <A
120 * HREF="Inet4Address.html#format">Inet4Address#format</A>; For IPv6
121 * address format, please refer to <A
122 * HREF="Inet6Address.html#format">Inet6Address#format</A>.
123 *
124 * <P>There is a <a href="doc-files/net-properties.html#Ipv4IPv6">couple of
125 * System Properties</a> affecting how IPv4 and IPv6 addresses are used.</P>
126 *
127 * <h4> Host Name Resolution </h4>
128 *
129 * Host name-to-IP address <i>resolution</i> is accomplished through
130 * the use of a combination of local machine configuration information
131 * and network naming services such as the Domain Name System (DNS)
132 * and Network Information Service(NIS). The particular naming
133 * services(s) being used is by default the local machine configured
134 * one. For any host name, its corresponding IP address is returned.
135 *
136 * <p> <i>Reverse name resolution</i> means that for any IP address,
137 * the host associated with the IP address is returned.
138 *
139 * <p> The InetAddress class provides methods to resolve host names to
140 * their IP addresses and vice versa.
141 *
142 * <h4> InetAddress Caching </h4>
143 *
144 * The InetAddress class has a cache to store successful as well as
145 * unsuccessful host name resolutions.
146 *
147 * <p> By default, when a security manager is installed, in order to
148 * protect against DNS spoofing attacks,
149 * the result of positive host name resolutions are
150 * cached forever. When a security manager is not installed, the default
151 * behavior is to cache entries for a finite (implementation dependent)
152 * period of time. The result of unsuccessful host
153 * name resolution is cached for a very short period of time (10
154 * seconds) to improve performance.
155 *
156 * <p> If the default behavior is not desired, then a Java security property
157 * can be set to a different Time-to-live (TTL) value for positive
158 * caching. Likewise, a system admin can configure a different
159 * negative caching TTL value when needed.
160 *
161 * <p> Two Java security properties control the TTL values used for
162 *  positive and negative host name resolution caching:
163 *
164 * <blockquote>
165 * <dl>
166 * <dt><b>networkaddress.cache.ttl</b></dt>
167 * <dd>Indicates the caching policy for successful name lookups from
168 * the name service. The value is specified as as integer to indicate
169 * the number of seconds to cache the successful lookup. The default
170 * setting is to cache for an implementation specific period of time.
171 * <p>
172 * A value of -1 indicates "cache forever".
173 * </dd>
174 * <p>
175 * <dt><b>networkaddress.cache.negative.ttl</b> (default: 10)</dt>
176 * <dd>Indicates the caching policy for un-successful name lookups
177 * from the name service. The value is specified as as integer to
178 * indicate the number of seconds to cache the failure for
179 * un-successful lookups.
180 * <p>
181 * A value of 0 indicates "never cache".
182 * A value of -1 indicates "cache forever".
183 * </dd>
184 * </dl>
185 * </blockquote>
186 *
187 * @author  Chris Warth
188 * @see     java.net.InetAddress#getByAddress(byte[])
189 * @see     java.net.InetAddress#getByAddress(java.lang.String, byte[])
190 * @see     java.net.InetAddress#getAllByName(java.lang.String)
191 * @see     java.net.InetAddress#getByName(java.lang.String)
192 * @see     java.net.InetAddress#getLocalHost()
193 * @since JDK1.0
194 */
195public
196class InetAddress implements java.io.Serializable {
197    /* ----- BEGIN android -----
198    Use AF_INET for IPv4 and AF_INET6 for IPv6 (and AF_UNIX for unix sockets)
199    //
200    // Specify the address family: Internet Protocol, Version 4
201    // @since 1.4
202    //
203    static final int IPv4 = 1;
204
205    //
206    // Specify the address family: Internet Protocol, Version 6
207    // @since 1.4
208    //
209    static final int IPv6 = 2;
210    ----- END android ----- */
211
212    /* Specify address family preference */
213    static transient boolean preferIPv6Address = false;
214
215    static class InetAddressHolder {
216
217        InetAddressHolder() {}
218
219        InetAddressHolder(String hostName, int address, int family) {
220            this.hostName = hostName;
221            this.address = address;
222            this.family = family;
223        }
224
225        String hostName;
226
227        String getHostName() {
228            return hostName;
229        }
230
231        /**
232         * Holds a 32-bit IPv4 address.
233         */
234        int address;
235
236        int getAddress() {
237            return address;
238        }
239
240        /**
241         * Specifies the address family type, for instance, AF_INET for IPv4
242         * addresses, and AF_INET6 for IPv6 addresses.
243         */
244        int family;
245
246        int getFamily() {
247            return family;
248        }
249    }
250
251    final transient InetAddressHolder holder;
252
253    InetAddressHolder holder() {
254        return holder;
255    }
256
257    /* Used to store the name service provider */
258    private static List<NameService> nameServices = null;
259
260    /* Used to store the best available hostname */
261    private transient String canonicalHostName = null;
262
263    /** use serialVersionUID from JDK 1.0.2 for interoperability */
264    private static final long serialVersionUID = 3286316764910316507L;
265
266    /*
267     * Load net library into runtime, and perform initializations.
268     */
269    static {
270        preferIPv6Address = java.security.AccessController.doPrivileged(
271            new GetBooleanAction("java.net.preferIPv6Addresses")).booleanValue();
272        init();
273    }
274
275    /**
276     * Constructor for the Socket.accept() method.
277     * This creates an empty InetAddress, which is filled in by
278     * the accept() method.  This InetAddress, however, is not
279     * put in the address cache, since it is not created by name.
280     */
281    InetAddress() {
282        holder = new InetAddressHolder();
283    }
284
285    /**
286     * Replaces the de-serialized object with an Inet4Address object.
287     *
288     * @return the alternate object to the de-serialized object.
289     *
290     * @throws ObjectStreamException if a new object replacing this
291     * object could not be created
292     */
293    private Object readResolve() throws ObjectStreamException {
294        // will replace the deserialized 'this' object
295        return new Inet4Address(holder().getHostName(), holder().getAddress());
296    }
297
298    /**
299     * Utility routine to check if the InetAddress is an
300     * IP multicast address.
301     * @return a <code>boolean</code> indicating if the InetAddress is
302     * an IP multicast address
303     * @since   JDK1.1
304     */
305    public boolean isMulticastAddress() {
306        return false;
307    }
308
309    /**
310     * Utility routine to check if the InetAddress in a wildcard address.
311     * @return a <code>boolean</code> indicating if the Inetaddress is
312     *         a wildcard address.
313     * @since 1.4
314     */
315    public boolean isAnyLocalAddress() {
316        return false;
317    }
318
319    /**
320     * Utility routine to check if the InetAddress is a loopback address.
321     *
322     * @return a <code>boolean</code> indicating if the InetAddress is
323     * a loopback address; or false otherwise.
324     * @since 1.4
325     */
326    public boolean isLoopbackAddress() {
327        return false;
328    }
329
330    /**
331     * Utility routine to check if the InetAddress is an link local address.
332     *
333     * @return a <code>boolean</code> indicating if the InetAddress is
334     * a link local address; or false if address is not a link local unicast address.
335     * @since 1.4
336     */
337    public boolean isLinkLocalAddress() {
338        return false;
339    }
340
341    /**
342     * Utility routine to check if the InetAddress is a site local address.
343     *
344     * @return a <code>boolean</code> indicating if the InetAddress is
345     * a site local address; or false if address is not a site local unicast address.
346     * @since 1.4
347     */
348    public boolean isSiteLocalAddress() {
349        return false;
350    }
351
352    /**
353     * Utility routine to check if the multicast address has global scope.
354     *
355     * @return a <code>boolean</code> indicating if the address has
356     *         is a multicast address of global scope, false if it is not
357     *         of global scope or it is not a multicast address
358     * @since 1.4
359     */
360    public boolean isMCGlobal() {
361        return false;
362    }
363
364    /**
365     * Utility routine to check if the multicast address has node scope.
366     *
367     * @return a <code>boolean</code> indicating if the address has
368     *         is a multicast address of node-local scope, false if it is not
369     *         of node-local scope or it is not a multicast address
370     * @since 1.4
371     */
372    public boolean isMCNodeLocal() {
373        return false;
374    }
375
376    /**
377     * Utility routine to check if the multicast address has link scope.
378     *
379     * @return a <code>boolean</code> indicating if the address has
380     *         is a multicast address of link-local scope, false if it is not
381     *         of link-local scope or it is not a multicast address
382     * @since 1.4
383     */
384    public boolean isMCLinkLocal() {
385        return false;
386    }
387
388    /**
389     * Utility routine to check if the multicast address has site scope.
390     *
391     * @return a <code>boolean</code> indicating if the address has
392     *         is a multicast address of site-local scope, false if it is not
393     *         of site-local scope or it is not a multicast address
394     * @since 1.4
395     */
396    public boolean isMCSiteLocal() {
397        return false;
398    }
399
400    /**
401     * Utility routine to check if the multicast address has organization scope.
402     *
403     * @return a <code>boolean</code> indicating if the address has
404     *         is a multicast address of organization-local scope,
405     *         false if it is not of organization-local scope
406     *         or it is not a multicast address
407     * @since 1.4
408     */
409    public boolean isMCOrgLocal() {
410        return false;
411    }
412
413
414    /**
415     * Test whether that address is reachable. Best effort is made by the
416     * implementation to try to reach the host, but firewalls and server
417     * configuration may block requests resulting in a unreachable status
418     * while some specific ports may be accessible.
419     * A typical implementation will use ICMP ECHO REQUESTs if the
420     * privilege can be obtained, otherwise it will try to establish
421     * a TCP connection on port 7 (Echo) of the destination host.
422     * <p>
423     * The timeout value, in milliseconds, indicates the maximum amount of time
424     * the try should take. If the operation times out before getting an
425     * answer, the host is deemed unreachable. A negative value will result
426     * in an IllegalArgumentException being thrown.
427     *
428     * @param   timeout the time, in milliseconds, before the call aborts
429     * @return a <code>boolean</code> indicating if the address is reachable.
430     * @throws IOException if a network error occurs
431     * @throws  IllegalArgumentException if <code>timeout</code> is negative.
432     * @since 1.5
433     */
434    public boolean isReachable(int timeout) throws IOException {
435        return isReachable(null, 0 , timeout);
436    }
437
438    /**
439     * Test whether that address is reachable. Best effort is made by the
440     * implementation to try to reach the host, but firewalls and server
441     * configuration may block requests resulting in a unreachable status
442     * while some specific ports may be accessible.
443     * A typical implementation will use ICMP ECHO REQUESTs if the
444     * privilege can be obtained, otherwise it will try to establish
445     * a TCP connection on port 7 (Echo) of the destination host.
446     * <p>
447     * The <code>network interface</code> and <code>ttl</code> parameters
448     * let the caller specify which network interface the test will go through
449     * and the maximum number of hops the packets should go through.
450     * A negative value for the <code>ttl</code> will result in an
451     * IllegalArgumentException being thrown.
452     * <p>
453     * The timeout value, in milliseconds, indicates the maximum amount of time
454     * the try should take. If the operation times out before getting an
455     * answer, the host is deemed unreachable. A negative value will result
456     * in an IllegalArgumentException being thrown.
457     *
458     * @param   netif   the NetworkInterface through which the
459     *                    test will be done, or null for any interface
460     * @param   ttl     the maximum numbers of hops to try or 0 for the
461     *                  default
462     * @param   timeout the time, in milliseconds, before the call aborts
463     * @throws  IllegalArgumentException if either <code>timeout</code>
464     *                          or <code>ttl</code> are negative.
465     * @return a <code>boolean</code>indicating if the address is reachable.
466     * @throws IOException if a network error occurs
467     * @since 1.5
468     */
469    public boolean isReachable(NetworkInterface netif, int ttl,
470                               int timeout) throws IOException {
471        if (ttl < 0)
472            throw new IllegalArgumentException("ttl can't be negative");
473        if (timeout < 0)
474            throw new IllegalArgumentException("timeout can't be negative");
475
476        return impl.isReachable(this, timeout, netif, ttl);
477    }
478
479    /**
480     * Gets the host name for this IP address.
481     *
482     * <p>If this InetAddress was created with a host name,
483     * this host name will be remembered and returned;
484     * otherwise, a reverse name lookup will be performed
485     * and the result will be returned based on the system
486     * configured name lookup service. If a lookup of the name service
487     * is required, call
488     * {@link #getCanonicalHostName() getCanonicalHostName}.
489     *
490     * <p>If there is a security manager, its
491     * <code>checkConnect</code> method is first called
492     * with the hostname and <code>-1</code>
493     * as its arguments to see if the operation is allowed.
494     * If the operation is not allowed, it will return
495     * the textual representation of the IP address.
496     *
497     * @return  the host name for this IP address, or if the operation
498     *    is not allowed by the security check, the textual
499     *    representation of the IP address.
500     *
501     * @see InetAddress#getCanonicalHostName
502     * @see SecurityManager#checkConnect
503     */
504    public String getHostName() {
505        return getHostName(true);
506    }
507
508    /**
509     * Returns the hostname for this address.
510     * If the host is equal to null, then this address refers to any
511     * of the local machine's available network addresses.
512     * this is package private so SocketPermission can make calls into
513     * here without a security check.
514     *
515     * <p>If there is a security manager, this method first
516     * calls its <code>checkConnect</code> method
517     * with the hostname and <code>-1</code>
518     * as its arguments to see if the calling code is allowed to know
519     * the hostname for this IP address, i.e., to connect to the host.
520     * If the operation is not allowed, it will return
521     * the textual representation of the IP address.
522     *
523     * @return  the host name for this IP address, or if the operation
524     *    is not allowed by the security check, the textual
525     *    representation of the IP address.
526     *
527     * @param check make security check if true
528     *
529     * @see SecurityManager#checkConnect
530     */
531    String getHostName(boolean check) {
532        if (holder().getHostName() == null) {
533            holder().hostName = InetAddress.getHostFromNameService(this, check);
534        }
535        return holder().getHostName();
536    }
537
538    /**
539     * Gets the fully qualified domain name for this IP address.
540     * Best effort method, meaning we may not be able to return
541     * the FQDN depending on the underlying system configuration.
542     *
543     * <p>If there is a security manager, this method first
544     * calls its <code>checkConnect</code> method
545     * with the hostname and <code>-1</code>
546     * as its arguments to see if the calling code is allowed to know
547     * the hostname for this IP address, i.e., to connect to the host.
548     * If the operation is not allowed, it will return
549     * the textual representation of the IP address.
550     *
551     * @return  the fully qualified domain name for this IP address,
552     *    or if the operation is not allowed by the security check,
553     *    the textual representation of the IP address.
554     *
555     * @see SecurityManager#checkConnect
556     *
557     * @since 1.4
558     */
559    public String getCanonicalHostName() {
560        if (canonicalHostName == null) {
561            canonicalHostName =
562                InetAddress.getHostFromNameService(this, true);
563        }
564        return canonicalHostName;
565    }
566
567    /**
568     * Returns the hostname for this address.
569     *
570     * <p>If there is a security manager, this method first
571     * calls its <code>checkConnect</code> method
572     * with the hostname and <code>-1</code>
573     * as its arguments to see if the calling code is allowed to know
574     * the hostname for this IP address, i.e., to connect to the host.
575     * If the operation is not allowed, it will return
576     * the textual representation of the IP address.
577     *
578     * @return  the host name for this IP address, or if the operation
579     *    is not allowed by the security check, the textual
580     *    representation of the IP address.
581     *
582     * @param check make security check if true
583     *
584     * @see SecurityManager#checkConnect
585     */
586    private static String getHostFromNameService(InetAddress addr, boolean check) {
587        String host = null;
588        for (NameService nameService : nameServices) {
589            try {
590                // first lookup the hostname
591                host = nameService.getHostByAddr(addr.getAddress());
592
593                /* check to see if calling code is allowed to know
594                 * the hostname for this IP address, ie, connect to the host
595                 */
596                if (check) {
597                    SecurityManager sec = System.getSecurityManager();
598                    if (sec != null) {
599                        sec.checkConnect(host, -1);
600                    }
601                }
602
603                /* now get all the IP addresses for this hostname,
604                 * and make sure one of them matches the original IP
605                 * address. We do this to try and prevent spoofing.
606                 */
607
608                InetAddress[] arr = InetAddress.getAllByName0(host, check);
609                boolean ok = false;
610
611                if(arr != null) {
612                    for(int i = 0; !ok && i < arr.length; i++) {
613                        ok = addr.equals(arr[i]);
614                    }
615                }
616
617                //XXX: if it looks a spoof just return the address?
618                if (!ok) {
619                    host = addr.getHostAddress();
620                    return host;
621                }
622
623                break;
624
625            } catch (SecurityException e) {
626                host = addr.getHostAddress();
627                break;
628            } catch (UnknownHostException e) {
629                host = addr.getHostAddress();
630                // let next provider resolve the hostname
631            }
632        }
633
634        return host;
635    }
636
637    /**
638     * Returns the raw IP address of this <code>InetAddress</code>
639     * object. The result is in network byte order: the highest order
640     * byte of the address is in <code>getAddress()[0]</code>.
641     *
642     * @return  the raw IP address of this object.
643     */
644    public byte[] getAddress() {
645        return null;
646    }
647
648    /* @hide */
649    public byte[] getAddressInternal() {
650        return null;
651    }
652
653    /**
654     * Returns the IP address string in textual presentation.
655     *
656     * @return  the raw IP address in a string format.
657     * @since   JDK1.0.2
658     */
659    public String getHostAddress() {
660        return null;
661     }
662
663    /**
664     * Returns a hashcode for this IP address.
665     *
666     * @return  a hash code value for this IP address.
667     */
668    public int hashCode() {
669        return -1;
670    }
671
672    /**
673     * Compares this object against the specified object.
674     * The result is <code>true</code> if and only if the argument is
675     * not <code>null</code> and it represents the same IP address as
676     * this object.
677     * <p>
678     * Two instances of <code>InetAddress</code> represent the same IP
679     * address if the length of the byte arrays returned by
680     * <code>getAddress</code> is the same for both, and each of the
681     * array components is the same for the byte arrays.
682     *
683     * @param   obj   the object to compare against.
684     * @return  <code>true</code> if the objects are the same;
685     *          <code>false</code> otherwise.
686     * @see     java.net.InetAddress#getAddress()
687     */
688    public boolean equals(Object obj) {
689        return false;
690    }
691
692    /**
693     * Converts this IP address to a <code>String</code>. The
694     * string returned is of the form: hostname / literal IP
695     * address.
696     *
697     * If the host name is unresolved, no reverse name service lookup
698     * is performed. The hostname part will be represented by an empty string.
699     *
700     * @return  a string representation of this IP address.
701     */
702    public String toString() {
703        String hostName = holder().getHostName();
704        return ((hostName != null) ? hostName : "")
705            + "/" + getHostAddress();
706    }
707
708    /*
709     * Cached addresses - our own litle nis, not!
710     */
711    private static Cache addressCache = new Cache(Cache.Type.Positive);
712
713    private static Cache negativeCache = new Cache(Cache.Type.Negative);
714
715    private static boolean addressCacheInit = false;
716
717    static InetAddress[]    unknown_array; // put THIS in cache
718
719    static InetAddressImpl  impl;
720
721    private static final HashMap<String, Void> lookupTable = new HashMap<>();
722
723    /**
724     * Represents a cache entry
725     */
726    static final class CacheEntry {
727
728        CacheEntry(InetAddress[] addresses, long expiration) {
729            this.addresses = addresses;
730            this.expiration = expiration;
731        }
732
733        InetAddress[] addresses;
734        long expiration;
735    }
736
737    /**
738     * A cache that manages entries based on a policy specified
739     * at creation time.
740     */
741    static final class Cache {
742        private LinkedHashMap<String, CacheEntry> cache;
743        private Type type;
744
745        enum Type {Positive, Negative};
746
747        /**
748         * Create cache
749         */
750        public Cache(Type type) {
751            this.type = type;
752            cache = new LinkedHashMap<String, CacheEntry>();
753        }
754
755        private int getPolicy() {
756            if (type == Type.Positive) {
757                return InetAddressCachePolicy.get();
758            } else {
759                return InetAddressCachePolicy.getNegative();
760            }
761        }
762
763        /**
764         * Add an entry to the cache. If there's already an
765         * entry then for this host then the entry will be
766         * replaced.
767         */
768        public Cache put(String host, InetAddress[] addresses) {
769            int policy = getPolicy();
770            if (policy == InetAddressCachePolicy.NEVER) {
771                return this;
772            }
773
774            // purge any expired entries
775
776            if (policy != InetAddressCachePolicy.FOREVER) {
777
778                // As we iterate in insertion order we can
779                // terminate when a non-expired entry is found.
780                LinkedList<String> expired = new LinkedList<>();
781                long now = System.currentTimeMillis();
782                for (String key : cache.keySet()) {
783                    CacheEntry entry = cache.get(key);
784
785                    if (entry.expiration >= 0 && entry.expiration < now) {
786                        expired.add(key);
787                    } else {
788                        break;
789                    }
790                }
791
792                for (String key : expired) {
793                    cache.remove(key);
794                }
795            }
796
797            // create new entry and add it to the cache
798            // -- as a HashMap replaces existing entries we
799            //    don't need to explicitly check if there is
800            //    already an entry for this host.
801            long expiration;
802            if (policy == InetAddressCachePolicy.FOREVER) {
803                expiration = -1;
804            } else {
805                expiration = System.currentTimeMillis() + (policy * 1000);
806            }
807            CacheEntry entry = new CacheEntry(addresses, expiration);
808            cache.put(host, entry);
809            return this;
810        }
811
812        /**
813         * Query the cache for the specific host. If found then
814         * return its CacheEntry, or null if not found.
815         */
816        public CacheEntry get(String host) {
817            int policy = getPolicy();
818            if (policy == InetAddressCachePolicy.NEVER) {
819                return null;
820            }
821            CacheEntry entry = cache.get(host);
822
823            // check if entry has expired
824            if (entry != null && policy != InetAddressCachePolicy.FOREVER) {
825                if (entry.expiration >= 0 &&
826                    entry.expiration < System.currentTimeMillis()) {
827                    cache.remove(host);
828                    entry = null;
829                }
830            }
831
832            return entry;
833        }
834    }
835
836    /*
837     * Initialize cache and insert anyLocalAddress into the
838     * unknown array with no expiry.
839     */
840    private static void cacheInitIfNeeded() {
841        assert Thread.holdsLock(addressCache);
842        if (addressCacheInit) {
843            return;
844        }
845        unknown_array = new InetAddress[1];
846        unknown_array[0] = impl.anyLocalAddress();
847
848        addressCache.put(impl.anyLocalAddress().getHostName(),
849                         unknown_array);
850
851        addressCacheInit = true;
852    }
853
854    /*
855     * Cache the given hostname and addresses.
856     */
857    private static void cacheAddresses(String hostname,
858                                       InetAddress[] addresses,
859                                       boolean success) {
860        hostname = hostname.toLowerCase();
861        synchronized (addressCache) {
862            cacheInitIfNeeded();
863            if (success) {
864                addressCache.put(hostname, addresses);
865            } else {
866                negativeCache.put(hostname, addresses);
867            }
868        }
869    }
870
871    /*
872     * Lookup hostname in cache (positive & negative cache). If
873     * found return addresses, null if not found.
874     */
875    private static InetAddress[] getCachedAddresses(String hostname) {
876        hostname = hostname.toLowerCase();
877
878        // search both positive & negative caches
879
880        synchronized (addressCache) {
881            cacheInitIfNeeded();
882
883            CacheEntry entry = addressCache.get(hostname);
884            if (entry == null) {
885                entry = negativeCache.get(hostname);
886            }
887
888            if (entry != null) {
889                return entry.addresses;
890            }
891        }
892
893        // not found
894        return null;
895    }
896
897    private static NameService createNSProvider(String provider) {
898        if (provider == null)
899            return null;
900
901        NameService nameService = null;
902        if (provider.equals("default")) {
903            // initialize the default name service
904            nameService = new NameService() {
905                public InetAddress[] lookupAllHostAddr(String host)
906                    throws UnknownHostException {
907                    return impl.lookupAllHostAddr(host);
908                }
909                public String getHostByAddr(byte[] addr)
910                    throws UnknownHostException {
911                    return impl.getHostByAddr(addr);
912                }
913            };
914        } else {
915            final String providerName = provider;
916            try {
917                nameService = java.security.AccessController.doPrivileged(
918                    new java.security.PrivilegedExceptionAction<NameService>() {
919                        public NameService run() {
920                            Iterator itr = Service.providers(NameServiceDescriptor.class);
921                            while (itr.hasNext()) {
922                                NameServiceDescriptor nsd
923                                    = (NameServiceDescriptor)itr.next();
924                                if (providerName.
925                                    equalsIgnoreCase(nsd.getType()+","
926                                        +nsd.getProviderName())) {
927                                    try {
928                                        return nsd.createNameService();
929                                    } catch (Exception e) {
930                                        e.printStackTrace();
931                                        System.err.println(
932                                            "Cannot create name service:"
933                                             +providerName+": " + e);
934                                    }
935                                }
936                            }
937
938                            return null;
939                        }
940                    }
941                );
942            } catch (java.security.PrivilegedActionException e) {
943            }
944        }
945
946        return nameService;
947    }
948
949    static {
950        // create the impl
951        impl = InetAddressImplFactory.create();
952
953        // get name service if provided and requested
954        String provider = null;;
955        String propPrefix = "sun.net.spi.nameservice.provider.";
956        int n = 1;
957        nameServices = new ArrayList<NameService>();
958        provider = AccessController.doPrivileged(
959                new GetPropertyAction(propPrefix + n));
960        while (provider != null) {
961            NameService ns = createNSProvider(provider);
962            if (ns != null)
963                nameServices.add(ns);
964
965            n++;
966            provider = AccessController.doPrivileged(
967                    new GetPropertyAction(propPrefix + n));
968        }
969
970        // if not designate any name services provider,
971        // create a default one
972        if (nameServices.size() == 0) {
973            NameService ns = createNSProvider("default");
974            nameServices.add(ns);
975        }
976    }
977
978    /**
979     * Creates an InetAddress based on the provided host name and IP address.
980     * No name service is checked for the validity of the address.
981     *
982     * <p> The host name can either be a machine name, such as
983     * "<code>java.sun.com</code>", or a textual representation of its IP
984     * address.
985     * <p> No validity checking is done on the host name either.
986     *
987     * <p> If addr specifies an IPv4 address an instance of Inet4Address
988     * will be returned; otherwise, an instance of Inet6Address
989     * will be returned.
990     *
991     * <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
992     * must be 16 bytes long
993     *
994     * @param host the specified host
995     * @param addr the raw IP address in network byte order
996     * @return  an InetAddress object created from the raw IP address.
997     * @exception  UnknownHostException  if IP address is of illegal length
998     * @since 1.4
999     */
1000    public static InetAddress getByAddress(String host, byte[] addr)
1001        throws UnknownHostException {
1002        if (host != null && host.length() > 0 && host.charAt(0) == '[') {
1003            if (host.charAt(host.length()-1) == ']') {
1004                host = host.substring(1, host.length() -1);
1005            }
1006        }
1007        if (addr != null) {
1008            if (addr.length == Inet4Address.INADDRSZ) {
1009                return new Inet4Address(host, addr);
1010            } else if (addr.length == Inet6Address.INADDRSZ) {
1011                byte[] newAddr
1012                    = IPAddressUtil.convertFromIPv4MappedAddress(addr);
1013                if (newAddr != null) {
1014                    return new Inet4Address(host, newAddr);
1015                } else {
1016                    return new Inet6Address(host, addr);
1017                }
1018            }
1019        }
1020        throw new UnknownHostException("addr is of illegal length");
1021    }
1022
1023    private static InetAddress getByAddress(String host, byte[] addr, int scopeId)
1024        throws UnknownHostException {
1025        if (host != null && host.length() > 0 && host.charAt(0) == '[') {
1026            if (host.charAt(host.length()-1) == ']') {
1027                host = host.substring(1, host.length() -1);
1028            }
1029        }
1030        if (addr != null) {
1031            if (addr.length == Inet4Address.INADDRSZ) {
1032                return new Inet4Address(host, addr);
1033            } else if (addr.length == Inet6Address.INADDRSZ) {
1034                byte[] newAddr
1035                    = IPAddressUtil.convertFromIPv4MappedAddress(addr);
1036                if (newAddr != null) {
1037                    return new Inet4Address(host, newAddr);
1038                } else {
1039                    return new Inet6Address(host, addr, scopeId);
1040                }
1041            }
1042        }
1043        throw new UnknownHostException("addr is of illegal length");
1044    }
1045
1046
1047    /**
1048     * Determines the IP address of a host, given the host's name.
1049     *
1050     * <p> The host name can either be a machine name, such as
1051     * "<code>java.sun.com</code>", or a textual representation of its
1052     * IP address. If a literal IP address is supplied, only the
1053     * validity of the address format is checked.
1054     *
1055     * <p> For <code>host</code> specified in literal IPv6 address,
1056     * either the form defined in RFC 2732 or the literal IPv6 address
1057     * format defined in RFC 2373 is accepted. IPv6 scoped addresses are also
1058     * supported. See <a href="Inet6Address.html#scoped">here</a> for a description of IPv6
1059     * scoped addresses.
1060     *
1061     * <p> If the host is <tt>null</tt> then an <tt>InetAddress</tt>
1062     * representing an address of the loopback interface is returned.
1063     * See <a href="http://www.ietf.org/rfc/rfc3330.txt">RFC&nbsp;3330</a>
1064     * section&nbsp;2 and <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC&nbsp;2373</a>
1065     * section&nbsp;2.5.3. </p>
1066     *
1067     * @param      host   the specified host, or <code>null</code>.
1068     * @return     an IP address for the given host name.
1069     * @exception  UnknownHostException  if no IP address for the
1070     *               <code>host</code> could be found, or if a scope_id was specified
1071     *               for a global IPv6 address.
1072     * @exception  SecurityException if a security manager exists
1073     *             and its checkConnect method doesn't allow the operation
1074     */
1075    public static InetAddress getByName(String host)
1076        throws UnknownHostException {
1077        return InetAddress.getAllByName(host)[0];
1078    }
1079
1080    // called from deployment cache manager
1081    private static InetAddress getByName(String host, InetAddress reqAddr)
1082        throws UnknownHostException {
1083        return InetAddress.getAllByName(host, reqAddr)[0];
1084    }
1085
1086    /**
1087     * Given the name of a host, returns an array of its IP addresses,
1088     * based on the configured name service on the system.
1089     *
1090     * <p> The host name can either be a machine name, such as
1091     * "<code>java.sun.com</code>", or a textual representation of its IP
1092     * address. If a literal IP address is supplied, only the
1093     * validity of the address format is checked.
1094     *
1095     * <p> For <code>host</code> specified in <i>literal IPv6 address</i>,
1096     * either the form defined in RFC 2732 or the literal IPv6 address
1097     * format defined in RFC 2373 is accepted. A literal IPv6 address may
1098     * also be qualified by appending a scoped zone identifier or scope_id.
1099     * The syntax and usage of scope_ids is described
1100     * <a href="Inet6Address.html#scoped">here</a>.
1101     * <p> If the host is <tt>null</tt> then an <tt>InetAddress</tt>
1102     * representing an address of the loopback interface is returned.
1103     * See <a href="http://www.ietf.org/rfc/rfc3330.txt">RFC&nbsp;3330</a>
1104     * section&nbsp;2 and <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC&nbsp;2373</a>
1105     * section&nbsp;2.5.3. </p>
1106     *
1107     * <p> If there is a security manager and <code>host</code> is not
1108     * null and <code>host.length() </code> is not equal to zero, the
1109     * security manager's
1110     * <code>checkConnect</code> method is called
1111     * with the hostname and <code>-1</code>
1112     * as its arguments to see if the operation is allowed.
1113     *
1114     * @param      host   the name of the host, or <code>null</code>.
1115     * @return     an array of all the IP addresses for a given host name.
1116     *
1117     * @exception  UnknownHostException  if no IP address for the
1118     *               <code>host</code> could be found, or if a scope_id was specified
1119     *               for a global IPv6 address.
1120     * @exception  SecurityException  if a security manager exists and its
1121     *               <code>checkConnect</code> method doesn't allow the operation.
1122     *
1123     * @see SecurityManager#checkConnect
1124     */
1125    public static InetAddress[] getAllByName(String host)
1126        throws UnknownHostException {
1127        return getAllByName(host, null);
1128    }
1129
1130    private static InetAddress[] getAllByName(String host, InetAddress reqAddr)
1131        throws UnknownHostException {
1132
1133        if (host == null || host.length() == 0) {
1134            InetAddress[] ret = new InetAddress[1];
1135            ret[0] = impl.loopbackAddress();
1136            return ret;
1137        }
1138
1139        boolean ipv6Expected = false;
1140        if (host.charAt(0) == '[') {
1141            // This is supposed to be an IPv6 literal
1142            if (host.length() > 2 && host.charAt(host.length()-1) == ']') {
1143                host = host.substring(1, host.length() -1);
1144                ipv6Expected = true;
1145            } else {
1146                // This was supposed to be a IPv6 address, but it's not!
1147                throw new UnknownHostException(host + ": invalid IPv6 address");
1148            }
1149        }
1150
1151        // if host is an IP address, we won't do further lookup
1152        if (Character.digit(host.charAt(0), 16) != -1
1153            || (host.charAt(0) == ':')) {
1154            byte[] addr = null;
1155            int numericZone = -1;
1156            String ifname = null;
1157            // see if it is IPv4 address
1158            addr = IPAddressUtil.textToNumericFormatV4(host);
1159            if (addr == null) {
1160                // see if it is IPv6 address
1161                // Check if a numeric or string zone id is present
1162                int pos;
1163                if ((pos=host.indexOf ("%")) != -1) {
1164                    numericZone = checkNumericZone (host);
1165                    if (numericZone == -1) { /* remainder of string must be an ifname */
1166                        ifname = host.substring (pos+1);
1167                    }
1168                }
1169                addr = IPAddressUtil.textToNumericFormatV6(host);
1170            } else if (ipv6Expected) {
1171                // Means an IPv4 litteral between brackets!
1172                throw new UnknownHostException("["+host+"]");
1173            }
1174            InetAddress[] ret = new InetAddress[1];
1175            if(addr != null) {
1176                if (addr.length == Inet4Address.INADDRSZ) {
1177                    ret[0] = new Inet4Address(null, addr);
1178                } else {
1179                    if (ifname != null) {
1180                        ret[0] = new Inet6Address(null, addr, ifname);
1181                    } else {
1182                        ret[0] = new Inet6Address(null, addr, numericZone);
1183                    }
1184                }
1185                return ret;
1186            }
1187            } else if (ipv6Expected) {
1188                // We were expecting an IPv6 Litteral, but got something else
1189                throw new UnknownHostException("["+host+"]");
1190            }
1191        return getAllByName0(host, reqAddr, true);
1192    }
1193
1194    /**
1195     * Returns the loopback address.
1196     * <p>
1197     * The InetAddress returned will represent the IPv4
1198     * loopback address, 127.0.0.1, or the IPv6 loopback
1199     * address, ::1. The IPv4 loopback address returned
1200     * is only one of many in the form 127.*.*.*
1201     *
1202     * @return  the InetAddress loopback instance.
1203     * @since 1.7
1204     */
1205    public static InetAddress getLoopbackAddress() {
1206        return impl.loopbackAddress();
1207    }
1208
1209
1210    /**
1211     * check if the literal address string has %nn appended
1212     * returns -1 if not, or the numeric value otherwise.
1213     *
1214     * %nn may also be a string that represents the displayName of
1215     * a currently available NetworkInterface.
1216     */
1217    private static int checkNumericZone (String s) throws UnknownHostException {
1218        int percent = s.indexOf ('%');
1219        int slen = s.length();
1220        int digit, zone=0;
1221        if (percent == -1) {
1222            return -1;
1223        }
1224        for (int i=percent+1; i<slen; i++) {
1225            char c = s.charAt(i);
1226            if (c == ']') {
1227                if (i == percent+1) {
1228                    /* empty per-cent field */
1229                    return -1;
1230                }
1231                break;
1232            }
1233            if ((digit = Character.digit (c, 10)) < 0) {
1234                return -1;
1235            }
1236            zone = (zone * 10) + digit;
1237        }
1238        return zone;
1239    }
1240
1241    private static InetAddress[] getAllByName0 (String host)
1242        throws UnknownHostException
1243    {
1244        return getAllByName0(host, true);
1245    }
1246
1247    /**
1248     * package private so SocketPermission can call it
1249     */
1250    static InetAddress[] getAllByName0 (String host, boolean check)
1251        throws UnknownHostException  {
1252        return getAllByName0 (host, null, check);
1253    }
1254
1255    private static InetAddress[] getAllByName0 (String host, InetAddress reqAddr, boolean check)
1256        throws UnknownHostException  {
1257
1258        /* If it gets here it is presumed to be a hostname */
1259        /* Cache.get can return: null, unknownAddress, or InetAddress[] */
1260
1261        /* make sure the connection to the host is allowed, before we
1262         * give out a hostname
1263         */
1264        if (check) {
1265            SecurityManager security = System.getSecurityManager();
1266            if (security != null) {
1267                security.checkConnect(host, -1);
1268            }
1269        }
1270
1271        InetAddress[] addresses = getCachedAddresses(host);
1272
1273        /* If no entry in cache, then do the host lookup */
1274        if (addresses == null) {
1275            addresses = getAddressesFromNameService(host, reqAddr);
1276        }
1277
1278        if (addresses == unknown_array)
1279            throw new UnknownHostException(host);
1280
1281        return addresses.clone();
1282    }
1283
1284    private static InetAddress[] getAddressesFromNameService(String host, InetAddress reqAddr)
1285        throws UnknownHostException
1286    {
1287        InetAddress[] addresses = null;
1288        boolean success = false;
1289        UnknownHostException ex = null;
1290
1291        // Check whether the host is in the lookupTable.
1292        // 1) If the host isn't in the lookupTable when
1293        //    checkLookupTable() is called, checkLookupTable()
1294        //    would add the host in the lookupTable and
1295        //    return null. So we will do the lookup.
1296        // 2) If the host is in the lookupTable when
1297        //    checkLookupTable() is called, the current thread
1298        //    would be blocked until the host is removed
1299        //    from the lookupTable. Then this thread
1300        //    should try to look up the addressCache.
1301        //     i) if it found the addresses in the
1302        //        addressCache, checkLookupTable()  would
1303        //        return the addresses.
1304        //     ii) if it didn't find the addresses in the
1305        //         addressCache for any reason,
1306        //         it should add the host in the
1307        //         lookupTable and return null so the
1308        //         following code would do  a lookup itself.
1309        if ((addresses = checkLookupTable(host)) == null) {
1310            try {
1311                // This is the first thread which looks up the addresses
1312                // this host or the cache entry for this host has been
1313                // expired so this thread should do the lookup.
1314                for (NameService nameService : nameServices) {
1315                    try {
1316                        /*
1317                         * Do not put the call to lookup() inside the
1318                         * constructor.  if you do you will still be
1319                         * allocating space when the lookup fails.
1320                         */
1321
1322                        addresses = nameService.lookupAllHostAddr(host);
1323                        success = true;
1324                        break;
1325                    } catch (UnknownHostException uhe) {
1326                        if (host.equalsIgnoreCase("localhost")) {
1327                            InetAddress[] local = new InetAddress[] { impl.loopbackAddress() };
1328                            addresses = local;
1329                            success = true;
1330                            break;
1331                        }
1332                        else {
1333                            addresses = unknown_array;
1334                            success = false;
1335                            ex = uhe;
1336                        }
1337                    }
1338                }
1339
1340                // More to do?
1341                if (reqAddr != null && addresses.length > 1 && !addresses[0].equals(reqAddr)) {
1342                    // Find it?
1343                    int i = 1;
1344                    for (; i < addresses.length; i++) {
1345                        if (addresses[i].equals(reqAddr)) {
1346                            break;
1347                        }
1348                    }
1349                    // Rotate
1350                    if (i < addresses.length) {
1351                        InetAddress tmp, tmp2 = reqAddr;
1352                        for (int j = 0; j < i; j++) {
1353                            tmp = addresses[j];
1354                            addresses[j] = tmp2;
1355                            tmp2 = tmp;
1356                        }
1357                        addresses[i] = tmp2;
1358                    }
1359                }
1360                // Cache the address.
1361                cacheAddresses(host, addresses, success);
1362
1363                if (!success && ex != null)
1364                    throw ex;
1365
1366            } finally {
1367                // Delete host from the lookupTable and notify
1368                // all threads waiting on the lookupTable monitor.
1369                updateLookupTable(host);
1370            }
1371        }
1372
1373        return addresses;
1374    }
1375
1376
1377    private static InetAddress[] checkLookupTable(String host) {
1378        synchronized (lookupTable) {
1379            // If the host isn't in the lookupTable, add it in the
1380            // lookuptable and return null. The caller should do
1381            // the lookup.
1382            if (lookupTable.containsKey(host) == false) {
1383                lookupTable.put(host, null);
1384                return null;
1385            }
1386
1387            // If the host is in the lookupTable, it means that another
1388            // thread is trying to look up the addresses of this host.
1389            // This thread should wait.
1390            while (lookupTable.containsKey(host)) {
1391                try {
1392                    lookupTable.wait();
1393                } catch (InterruptedException e) {
1394                }
1395            }
1396        }
1397
1398        // The other thread has finished looking up the addresses of
1399        // the host. This thread should retry to get the addresses
1400        // from the addressCache. If it doesn't get the addresses from
1401        // the cache, it will try to look up the addresses itself.
1402        InetAddress[] addresses = getCachedAddresses(host);
1403        if (addresses == null) {
1404            synchronized (lookupTable) {
1405                lookupTable.put(host, null);
1406                return null;
1407            }
1408        }
1409
1410        return addresses;
1411    }
1412
1413    private static void updateLookupTable(String host) {
1414        synchronized (lookupTable) {
1415            lookupTable.remove(host);
1416            lookupTable.notifyAll();
1417        }
1418    }
1419
1420    /**
1421     * Returns an <code>InetAddress</code> object given the raw IP address .
1422     * The argument is in network byte order: the highest order
1423     * byte of the address is in <code>getAddress()[0]</code>.
1424     *
1425     * <p> This method doesn't block, i.e. no reverse name service lookup
1426     * is performed.
1427     *
1428     * <p> IPv4 address byte array must be 4 bytes long and IPv6 byte array
1429     * must be 16 bytes long
1430     *
1431     * @param addr the raw IP address in network byte order
1432     * @return  an InetAddress object created from the raw IP address.
1433     * @exception  UnknownHostException  if IP address is of illegal length
1434     * @since 1.4
1435     */
1436    public static InetAddress getByAddress(byte[] addr)
1437        throws UnknownHostException {
1438        return getByAddress(null, addr);
1439    }
1440
1441    private static InetAddress cachedLocalHost = null;
1442    private static long cacheTime = 0;
1443    private static final long maxCacheTime = 5000L;
1444    private static final Object cacheLock = new Object();
1445
1446    /**
1447     * Returns the address of the local host. This is achieved by retrieving
1448     * the name of the host from the system, then resolving that name into
1449     * an <code>InetAddress</code>.
1450     *
1451     * <P>Note: The resolved address may be cached for a short period of time.
1452     * </P>
1453     *
1454     * <p>If there is a security manager, its
1455     * <code>checkConnect</code> method is called
1456     * with the local host name and <code>-1</code>
1457     * as its arguments to see if the operation is allowed.
1458     * If the operation is not allowed, an InetAddress representing
1459     * the loopback address is returned.
1460     *
1461     * @return     the address of the local host.
1462     *
1463     * @exception  UnknownHostException  if the local host name could not
1464     *             be resolved into an address.
1465     *
1466     * @see SecurityManager#checkConnect
1467     * @see java.net.InetAddress#getByName(java.lang.String)
1468     */
1469    public static InetAddress getLocalHost() throws UnknownHostException {
1470
1471        SecurityManager security = System.getSecurityManager();
1472        try {
1473            String local = impl.getLocalHostName();
1474
1475            if (security != null) {
1476                security.checkConnect(local, -1);
1477            }
1478
1479            if (local.equals("localhost")) {
1480                return impl.loopbackAddress();
1481            }
1482
1483            InetAddress ret = null;
1484            synchronized (cacheLock) {
1485                long now = System.currentTimeMillis();
1486                if (cachedLocalHost != null) {
1487                    if ((now - cacheTime) < maxCacheTime) // Less than 5s old?
1488                        ret = cachedLocalHost;
1489                    else
1490                        cachedLocalHost = null;
1491                }
1492
1493                // we are calling getAddressesFromNameService directly
1494                // to avoid getting localHost from cache
1495                if (ret == null) {
1496                    InetAddress[] localAddrs;
1497                    try {
1498                        localAddrs =
1499                            InetAddress.getAddressesFromNameService(local, null);
1500                    } catch (UnknownHostException uhe) {
1501                        // Rethrow with a more informative error message.
1502                        UnknownHostException uhe2 =
1503                            new UnknownHostException(local + ": " +
1504                                                     uhe.getMessage());
1505                        uhe2.initCause(uhe);
1506                        throw uhe2;
1507                    }
1508                    cachedLocalHost = localAddrs[0];
1509                    cacheTime = now;
1510                    ret = localAddrs[0];
1511                }
1512            }
1513            return ret;
1514        } catch (java.lang.SecurityException e) {
1515            return impl.loopbackAddress();
1516        }
1517    }
1518
1519    /**
1520     * Perform class load-time initializations.
1521     */
1522    private static native void init();
1523
1524
1525    /*
1526     * Returns the InetAddress representing anyLocalAddress
1527     * (typically 0.0.0.0 or ::0)
1528     */
1529    static InetAddress anyLocalAddress() {
1530        return impl.anyLocalAddress();
1531    }
1532
1533    /*
1534     * Load and instantiate an underlying impl class
1535     */
1536    static InetAddressImpl loadImpl(String implName) {
1537        Object impl = null;
1538
1539        /*
1540         * Property "impl.prefix" will be prepended to the classname
1541         * of the implementation object we instantiate, to which we
1542         * delegate the real work (like native methods).  This
1543         * property can vary across implementations of the java.
1544         * classes.  The default is an empty String "".
1545         */
1546        String prefix = AccessController.doPrivileged(
1547                      new GetPropertyAction("impl.prefix", ""));
1548        try {
1549            impl = Class.forName("java.net." + prefix + implName).newInstance();
1550        } catch (ClassNotFoundException e) {
1551            System.err.println("Class not found: java.net." + prefix +
1552                               implName + ":\ncheck impl.prefix property " +
1553                               "in your properties file.");
1554        } catch (InstantiationException e) {
1555            System.err.println("Could not instantiate: java.net." + prefix +
1556                               implName + ":\ncheck impl.prefix property " +
1557                               "in your properties file.");
1558        } catch (IllegalAccessException e) {
1559            System.err.println("Cannot access class: java.net." + prefix +
1560                               implName + ":\ncheck impl.prefix property " +
1561                               "in your properties file.");
1562        }
1563
1564        if (impl == null) {
1565            try {
1566                impl = Class.forName(implName).newInstance();
1567            } catch (Exception e) {
1568                throw new Error("System property impl.prefix incorrect");
1569            }
1570        }
1571
1572        return (InetAddressImpl) impl;
1573    }
1574
1575    private void readObjectNoData (ObjectInputStream s) throws
1576                         IOException, ClassNotFoundException {
1577        if (getClass().getClassLoader() != null) {
1578            throw new SecurityException ("invalid address type");
1579        }
1580    }
1581
1582    private static final long FIELDS_OFFSET;
1583    private static final sun.misc.Unsafe UNSAFE;
1584
1585    static {
1586        try {
1587            sun.misc.Unsafe unsafe = sun.misc.Unsafe.getUnsafe();
1588            FIELDS_OFFSET = unsafe.objectFieldOffset(
1589                InetAddress.class.getDeclaredField("holder")
1590            );
1591            UNSAFE = unsafe;
1592        } catch (ReflectiveOperationException e) {
1593            throw new Error(e);
1594        }
1595    }
1596
1597    private void readObject (ObjectInputStream s) throws
1598                         IOException, ClassNotFoundException {
1599        if (getClass().getClassLoader() != null) {
1600            throw new SecurityException ("invalid address type");
1601        }
1602        GetField gf = s.readFields();
1603        String host = (String)gf.get("hostName", null);
1604        int address= gf.get("address", 0);
1605        int family= gf.get("family", 0);
1606        InetAddressHolder h = new InetAddressHolder(host, address, family);
1607        UNSAFE.putObject(this, FIELDS_OFFSET, h);
1608    }
1609
1610    /* needed because the serializable fields no longer exist */
1611
1612    /**
1613     * @serialField hostName String
1614     * @serialField address int
1615     * @serialField family int
1616     */
1617    private static final ObjectStreamField[] serialPersistentFields = {
1618        new ObjectStreamField("hostName", String.class),
1619        new ObjectStreamField("address", int.class),
1620        new ObjectStreamField("family", int.class),
1621    };
1622
1623    private void writeObject (ObjectOutputStream s) throws
1624                        IOException {
1625        if (getClass().getClassLoader() != null) {
1626            throw new SecurityException ("invalid address type");
1627        }
1628        PutField pf = s.putFields();
1629        pf.put("hostName", holder().hostName);
1630        pf.put("address", holder().address);
1631        pf.put("family", holder().family);
1632        s.writeFields();
1633        s.flush();
1634    }
1635
1636    private static final int NETID_UNSET = 0;
1637
1638    /**
1639     * Returns true if the string is a valid numeric IPv4 or IPv6 address (such as "192.168.0.1").
1640     * This copes with all forms of address that Java supports, detailed in the {@link InetAddress}
1641     * class documentation.
1642     *
1643     * @hide used by frameworks/base to ensure that a getAllByName won't cause a DNS lookup.
1644     */
1645    public static boolean isNumeric(String address) {
1646        InetAddress inetAddress = parseNumericAddressNoThrow(address);
1647        return inetAddress != null && disallowDeprecatedFormats(address, inetAddress) != null;
1648    }
1649
1650    private static InetAddress parseNumericAddressNoThrow(String address) {
1651        // Accept IPv6 addresses (only) in square brackets for compatibility.
1652        if (address.startsWith("[") && address.endsWith("]") && address.indexOf(':') != -1) {
1653            address = address.substring(1, address.length() - 1);
1654        }
1655        StructAddrinfo hints = new StructAddrinfo();
1656        hints.ai_flags = AI_NUMERICHOST;
1657        InetAddress[] addresses = null;
1658        try {
1659            addresses = Libcore.os.android_getaddrinfo(address, hints, NETID_UNSET);
1660        } catch (GaiException ignored) {
1661        }
1662        return (addresses != null) ? addresses[0] : null;
1663    }
1664
1665    private static InetAddress disallowDeprecatedFormats(String address, InetAddress inetAddress) {
1666        // Only IPv4 addresses are problematic.
1667        if (!(inetAddress instanceof Inet4Address) || address.indexOf(':') != -1) {
1668            return inetAddress;
1669        }
1670        // If inet_pton(3) can't parse it, it must have been a deprecated format.
1671        // We need to return inet_pton(3)'s result to ensure that numbers assumed to be octal
1672        // by getaddrinfo(3) are reinterpreted by inet_pton(3) as decimal.
1673        return Libcore.os.inet_pton(AF_INET, address);
1674    }
1675
1676    /**
1677     * Returns an InetAddress corresponding to the given numeric address (such
1678     * as {@code "192.168.0.1"} or {@code "2001:4860:800d::68"}).
1679     * This method will never do a DNS lookup. Non-numeric addresses are errors.
1680     *
1681     * @hide used by frameworks/base's NetworkUtils.numericToInetAddress
1682     * @throws IllegalArgumentException if {@code numericAddress} is not a numeric address
1683     */
1684    public static InetAddress parseNumericAddress(String numericAddress) {
1685        if (numericAddress == null || numericAddress.isEmpty()) {
1686            return Inet6Address.LOOPBACK;
1687        }
1688        InetAddress result = parseNumericAddressNoThrow(numericAddress);
1689        result = disallowDeprecatedFormats(numericAddress, result);
1690        if (result == null) {
1691            throw new IllegalArgumentException("Not a numeric address: " + numericAddress);
1692        }
1693        return result;
1694    }
1695
1696    /* @hide */
1697    public static void clearDnsCache() {
1698        System.logW("OJ: DNS cache clear requested, not implemented");
1699    }
1700
1701    /**
1702     * Operates identically to {@code getByName} except host resolution is
1703     * performed on the network designated by {@code netId}.
1704     *
1705     * @param host
1706     *            the hostName to be resolved to an address or {@code null}.
1707     * @param netId the network to use for host resolution.
1708     * @return the {@code InetAddress} instance representing the host.
1709     * @throws UnknownHostException if the address lookup fails.
1710     * @hide internal use only
1711     */
1712    public static InetAddress getByNameOnNet(String host, int netId) throws UnknownHostException {
1713        return getAllByNameImpl(host, netId)[0];
1714    }
1715
1716    /**
1717     * Operates identically to {@code getAllByName} except host resolution is
1718     * performed on the network designated by {@code netId}.
1719     *
1720     * @param host the hostname or literal IP string to be resolved.
1721     * @param netId the network to use for host resolution.
1722     * @return the array of addresses associated with the specified host.
1723     * @throws UnknownHostException if the address lookup fails.
1724     * @hide internal use only
1725     */
1726    public static InetAddress[] getAllByNameOnNet(String host, int netId) throws UnknownHostException {
1727        return getAllByNameImpl(host, netId).clone();
1728    }
1729
1730    /**
1731     * Returns the InetAddresses for {@code host} on network {@code netId}. The
1732     * returned array is shared and must be cloned before it is returned to
1733     * application code.
1734     */
1735    private static InetAddress[] getAllByNameImpl(String host, int netId) throws UnknownHostException {
1736        if (host == null || host.isEmpty()) {
1737            return loopbackAddresses();
1738        }
1739
1740        // Is it a numeric address?
1741        InetAddress result = parseNumericAddressNoThrow(host);
1742        if (result != null) {
1743            result = disallowDeprecatedFormats(host, result);
1744            if (result == null) {
1745                throw new UnknownHostException("Deprecated IPv4 address format: " + host);
1746            }
1747            return new InetAddress[] { result };
1748        }
1749
1750        return lookupHostByName(host, netId).clone();
1751    }
1752
1753    /**
1754     * Resolves a hostname to its IP addresses using a cache.
1755     *
1756     * @param host the hostname to resolve.
1757     * @param netId the network to perform resolution upon.
1758     * @return the IP addresses of the host.
1759     */
1760    private static InetAddress[] lookupHostByName(String host, int netId)
1761            throws UnknownHostException {
1762        BlockGuard.getThreadPolicy().onNetwork();
1763        try {
1764            StructAddrinfo hints = new StructAddrinfo();
1765            hints.ai_flags = AI_ADDRCONFIG;
1766            hints.ai_family = AF_UNSPEC;
1767            // If we don't specify a socket type, every address will appear twice, once
1768            // for SOCK_STREAM and one for SOCK_DGRAM. Since we do not return the family
1769            // anyway, just pick one.
1770            hints.ai_socktype = SOCK_STREAM;
1771            InetAddress[] addresses = Libcore.os.android_getaddrinfo(host, hints, netId);
1772            // TODO: should getaddrinfo set the hostname of the InetAddresses it returns?
1773            for (InetAddress address : addresses) {
1774                address.holder().hostName = host;
1775            }
1776            return addresses;
1777        } catch (GaiException gaiException) {
1778            // If the failure appears to have been a lack of INTERNET permission, throw a clear
1779            // SecurityException to aid in debugging this common mistake.
1780            // http://code.google.com/p/android/issues/detail?id=15722
1781            if (gaiException.getCause() instanceof ErrnoException) {
1782                if (((ErrnoException) gaiException.getCause()).errno == EACCES) {
1783                    throw new SecurityException("Permission denied (missing INTERNET permission?)", gaiException);
1784                }
1785            }
1786            // Otherwise, throw an UnknownHostException.
1787            String detailMessage = "Unable to resolve host \"" + host + "\": " + Libcore.os.gai_strerror(gaiException.error);
1788            throw gaiException.rethrowAsUnknownHostException(detailMessage);
1789        }
1790    }
1791
1792    private static InetAddress[] loopbackAddresses() {
1793        return new InetAddress[] { Inet6Address.LOOPBACK, Inet4Address.LOOPBACK };
1794    }
1795}
1796
1797/*
1798 * Simple factory to create the impl
1799 */
1800class InetAddressImplFactory {
1801
1802    static InetAddressImpl create() {
1803        return InetAddress.loadImpl(isIPv6Supported() ?
1804                                    "Inet6AddressImpl" : "Inet4AddressImpl");
1805    }
1806
1807    static native boolean isIPv6Supported();
1808}
1809