• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17 
18 package java.net;
19 
20 import dalvik.system.BlockGuard;
21 import java.io.FileDescriptor;
22 import java.io.IOException;
23 import java.io.ObjectInputStream;
24 import java.io.ObjectOutputStream;
25 import java.io.ObjectStreamException;
26 import java.io.ObjectStreamField;
27 import java.io.Serializable;
28 import java.nio.ByteOrder;
29 import java.util.Arrays;
30 import java.util.Collections;
31 import java.util.Comparator;
32 import java.util.Enumeration;
33 import java.util.List;
34 import java.util.concurrent.CountDownLatch;
35 import java.util.concurrent.atomic.AtomicBoolean;
36 import libcore.io.ErrnoException;
37 import libcore.io.GaiException;
38 import libcore.io.IoBridge;
39 import libcore.io.Libcore;
40 import libcore.io.Memory;
41 import libcore.io.StructAddrinfo;
42 import static libcore.io.OsConstants.*;
43 
44 /**
45  * An Internet Protocol (IP) address. This can be either an IPv4 address or an IPv6 address, and
46  * in practice you'll have an instance of either {@code Inet4Address} or {@code Inet6Address} (this
47  * class cannot be instantiated directly). Most code does not need to distinguish between the two
48  * families, and should use {@code InetAddress}.
49  *
50  * <p>An {@code InetAddress} may have a hostname (accessible via {@code getHostName}), but may not,
51  * depending on how the {@code InetAddress} was created.
52  *
53  * <h4>IPv4 numeric address formats</h4>
54  * <p>The {@code getAllByName} method accepts IPv4 addresses in the "decimal-dotted-quad" form only:
55  * <ul>
56  * <li>{@code "1.2.3.4"} - 1.2.3.4
57  * </ul>
58  *
59  * <h4>IPv6 numeric address formats</h4>
60  * <p>The {@code getAllByName} method accepts IPv6 addresses in the following forms (this text
61  * comes from <a href="http://www.ietf.org/rfc/rfc2373.txt">RFC 2373</a>, which you should consult
62  * for full details of IPv6 addressing):
63  * <ul>
64  * <li><p>The preferred form is {@code x:x:x:x:x:x:x:x}, where the 'x's are the
65  * hexadecimal values of the eight 16-bit pieces of the address.
66  * Note that it is not necessary to write the leading zeros in an
67  * individual field, but there must be at least one numeral in every
68  * field (except for the case described in the next bullet).
69  * Examples:
70  * <pre>
71  *     FEDC:BA98:7654:3210:FEDC:BA98:7654:3210
72  *     1080:0:0:0:8:800:200C:417A</pre>
73  * </li>
74  * <li>Due to some methods of allocating certain styles of IPv6
75  * addresses, it will be common for addresses to contain long strings
76  * of zero bits.  In order to make writing addresses containing zero
77  * bits easier a special syntax is available to compress the zeros.
78  * The use of "::" indicates multiple groups of 16-bits of zeros.
79  * The "::" can only appear once in an address.  The "::" can also be
80  * used to compress the leading and/or trailing zeros in an address.
81  *
82  * For example the following addresses:
83  * <pre>
84  *     1080:0:0:0:8:800:200C:417A  a unicast address
85  *     FF01:0:0:0:0:0:0:101        a multicast address
86  *     0:0:0:0:0:0:0:1             the loopback address
87  *     0:0:0:0:0:0:0:0             the unspecified addresses</pre>
88  * may be represented as:
89  * <pre>
90  *     1080::8:800:200C:417A       a unicast address
91  *     FF01::101                   a multicast address
92  *     ::1                         the loopback address
93  *     ::                          the unspecified addresses</pre>
94  * </li>
95  * <li><p>An alternative form that is sometimes more convenient when dealing
96  * with a mixed environment of IPv4 and IPv6 nodes is
97  * {@code x:x:x:x:x:x:d.d.d.d}, where the 'x's are the hexadecimal values of
98  * the six high-order 16-bit pieces of the address, and the 'd's are
99  * the decimal values of the four low-order 8-bit pieces of the
100  * address (standard IPv4 representation).  Examples:
101  * <pre>
102  *     0:0:0:0:0:0:13.1.68.3
103  *     0:0:0:0:0:FFFF:129.144.52.38</pre>
104  * or in compressed form:
105  * <pre>
106  *     ::13.1.68.3
107  *     ::FFFF:129.144.52.38</pre>
108  * </li>
109  * </ul>
110  * <p>Scopes are given using a trailing {@code %} followed by the scope id, as in
111  * {@code 1080::8:800:200C:417A%2} or {@code 1080::8:800:200C:417A%en0}.
112  * See <a href="https://www.ietf.org/rfc/rfc4007.txt">RFC 4007</a> for more on IPv6's scoped
113  * address architecture.
114  *
115  * <p>Additionally, for backwards compatibility, IPv6 addresses may be surrounded by square
116  * brackets.
117  *
118  * <h4>DNS caching</h4>
119  * <p>In Android 4.0 (Ice Cream Sandwich) and earlier, DNS caching was performed both by
120  * InetAddress and by the C library, which meant that DNS TTLs could not be honored correctly.
121  * In later releases, caching is done solely by the C library and DNS TTLs are honored.
122  *
123  * @see Inet4Address
124  * @see Inet6Address
125  */
126 public class InetAddress implements Serializable {
127     /** Our Java-side DNS cache. */
128     private static final AddressCache addressCache = new AddressCache();
129 
130     private static final long serialVersionUID = 3286316764910316507L;
131 
132     private int family;
133 
134     byte[] ipaddress;
135 
136     String hostName;
137 
138     /**
139      * Used by the DatagramSocket.disconnect implementation.
140      * @hide internal use only
141      */
142     public static final InetAddress UNSPECIFIED = new InetAddress(AF_UNSPEC, null, null);
143 
144     /**
145      * Constructs an {@code InetAddress}.
146      *
147      * Note: this constructor is for subclasses only.
148      */
InetAddress(int family, byte[] ipaddress, String hostName)149     InetAddress(int family, byte[] ipaddress, String hostName) {
150         this.family = family;
151         this.ipaddress = ipaddress;
152         this.hostName = hostName;
153     }
154 
155     /**
156      * Compares this {@code InetAddress} instance against the specified address
157      * in {@code obj}. Two addresses are equal if their address byte arrays have
158      * the same length and if the bytes in the arrays are equal.
159      *
160      * @param obj
161      *            the object to be tested for equality.
162      * @return {@code true} if both objects are equal, {@code false} otherwise.
163      */
164     @Override
equals(Object obj)165     public boolean equals(Object obj) {
166         if (!(obj instanceof InetAddress)) {
167             return false;
168         }
169         return Arrays.equals(this.ipaddress, ((InetAddress) obj).ipaddress);
170     }
171 
172     /**
173      * Returns the IP address represented by this {@code InetAddress} instance
174      * as a byte array. The elements are in network order (the highest order
175      * address byte is in the zeroth element).
176      *
177      * @return the address in form of a byte array.
178      */
getAddress()179     public byte[] getAddress() {
180         return ipaddress.clone();
181     }
182 
183     /**
184      * Converts an array of byte arrays representing raw IP addresses of a host
185      * to an array of InetAddress objects.
186      *
187      * @param rawAddresses the raw addresses to convert.
188      * @param hostName the hostname corresponding to the IP address.
189      * @return the corresponding InetAddresses, appropriately sorted.
190      */
bytesToInetAddresses(byte[][] rawAddresses, String hostName)191     private static InetAddress[] bytesToInetAddresses(byte[][] rawAddresses, String hostName)
192             throws UnknownHostException {
193         // Convert the byte arrays to InetAddresses.
194         InetAddress[] returnedAddresses = new InetAddress[rawAddresses.length];
195         for (int i = 0; i < rawAddresses.length; i++) {
196             returnedAddresses[i] = makeInetAddress(rawAddresses[i], hostName);
197         }
198         return returnedAddresses;
199     }
200 
201     /**
202      * Gets all IP addresses associated with the given {@code host} identified
203      * by name or literal IP address. The IP address is resolved by the
204      * configured name service. If the host name is empty or {@code null} an
205      * {@code UnknownHostException} is thrown. If the host name is a literal IP
206      * address string an array with the corresponding single {@code InetAddress}
207      * is returned.
208      *
209      * @param host the hostname or literal IP string to be resolved.
210      * @return the array of addresses associated with the specified host.
211      * @throws UnknownHostException if the address lookup fails.
212      */
getAllByName(String host)213     public static InetAddress[] getAllByName(String host) throws UnknownHostException {
214         return getAllByNameImpl(host).clone();
215     }
216 
217     /**
218      * Returns the InetAddresses for {@code host}. The returned array is shared
219      * and must be cloned before it is returned to application code.
220      */
getAllByNameImpl(String host)221     private static InetAddress[] getAllByNameImpl(String host) throws UnknownHostException {
222         if (host == null || host.isEmpty()) {
223             return loopbackAddresses();
224         }
225 
226         // Is it a numeric address?
227         InetAddress result = parseNumericAddressNoThrow(host);
228         if (result != null) {
229             result = disallowDeprecatedFormats(host, result);
230             if (result == null) {
231                 throw new UnknownHostException("Deprecated IPv4 address format: " + host);
232             }
233             return new InetAddress[] { result };
234         }
235 
236         return lookupHostByName(host).clone();
237     }
238 
makeInetAddress(byte[] bytes, String hostName)239     private static InetAddress makeInetAddress(byte[] bytes, String hostName) throws UnknownHostException {
240         if (bytes.length == 4) {
241             return new Inet4Address(bytes, hostName);
242         } else if (bytes.length == 16) {
243             return new Inet6Address(bytes, hostName, 0);
244         } else {
245             throw badAddressLength(bytes);
246         }
247     }
248 
disallowDeprecatedFormats(String address, InetAddress inetAddress)249     private static InetAddress disallowDeprecatedFormats(String address, InetAddress inetAddress) {
250         // Only IPv4 addresses are problematic.
251         if (!(inetAddress instanceof Inet4Address) || address.indexOf(':') != -1) {
252             return inetAddress;
253         }
254         // If inet_pton(3) can't parse it, it must have been a deprecated format.
255         // We need to return inet_pton(3)'s result to ensure that numbers assumed to be octal
256         // by getaddrinfo(3) are reinterpreted by inet_pton(3) as decimal.
257         return Libcore.os.inet_pton(AF_INET, address);
258     }
259 
parseNumericAddressNoThrow(String address)260     private static InetAddress parseNumericAddressNoThrow(String address) {
261         // Accept IPv6 addresses (only) in square brackets for compatibility.
262         if (address.startsWith("[") && address.endsWith("]") && address.indexOf(':') != -1) {
263             address = address.substring(1, address.length() - 1);
264         }
265         StructAddrinfo hints = new StructAddrinfo();
266         hints.ai_flags = AI_NUMERICHOST;
267         InetAddress[] addresses = null;
268         try {
269             addresses = Libcore.os.getaddrinfo(address, hints);
270         } catch (GaiException ignored) {
271         }
272         return (addresses != null) ? addresses[0] : null;
273     }
274 
275     /**
276      * Returns the address of a host according to the given host string name
277      * {@code host}. The host string may be either a machine name or a dotted
278      * string IP address. If the latter, the {@code hostName} field is
279      * determined upon demand. {@code host} can be {@code null} which means that
280      * an address of the loopback interface is returned.
281      *
282      * @param host
283      *            the hostName to be resolved to an address or {@code null}.
284      * @return the {@code InetAddress} instance representing the host.
285      * @throws UnknownHostException
286      *             if the address lookup fails.
287      */
getByName(String host)288     public static InetAddress getByName(String host) throws UnknownHostException {
289         return getAllByNameImpl(host)[0];
290     }
291 
292     /**
293      * Returns the numeric representation of this IP address (such as "127.0.0.1").
294      */
getHostAddress()295     public String getHostAddress() {
296         return Libcore.os.getnameinfo(this, NI_NUMERICHOST); // Can't throw.
297     }
298 
299     /**
300      * Returns the host name corresponding to this IP address. This may or may not be a
301      * fully-qualified name. If the IP address could not be resolved, the numeric representation
302      * is returned instead (see {@link #getHostAddress}).
303      */
getHostName()304     public String getHostName() {
305         if (hostName == null) {
306             try {
307                 hostName = getHostByAddrImpl(this).hostName;
308             } catch (UnknownHostException ex) {
309                 hostName = getHostAddress();
310             }
311         }
312         return hostName;
313     }
314 
315     /**
316      * Returns the fully qualified hostname corresponding to this IP address.
317      */
getCanonicalHostName()318     public String getCanonicalHostName() {
319         try {
320             return getHostByAddrImpl(this).hostName;
321         } catch (UnknownHostException ex) {
322             return getHostAddress();
323         }
324     }
325 
326     /**
327      * Returns an {@code InetAddress} for the local host if possible, or the
328      * loopback address otherwise. This method works by getting the hostname,
329      * performing a DNS lookup, and then taking the first returned address.
330      * For devices with multiple network interfaces and/or multiple addresses
331      * per interface, this does not necessarily return the {@code InetAddress}
332      * you want.
333      *
334      * <p>Multiple interface/address configurations were relatively rare
335      * when this API was designed, but multiple interfaces are the default for
336      * modern mobile devices (with separate wifi and radio interfaces), and
337      * the need to support both IPv4 and IPv6 has made multiple addresses
338      * commonplace. New code should thus avoid this method except where it's
339      * basically being used to get a loopback address or equivalent.
340      *
341      * <p>There are two main ways to get a more specific answer:
342      * <ul>
343      * <li>If you have a connected socket, you should probably use
344      * {@link Socket#getLocalAddress} instead: that will give you the address
345      * that's actually in use for that connection. (It's not possible to ask
346      * the question "what local address would a connection to a given remote
347      * address use?"; you have to actually make the connection and see.)</li>
348      * <li>For other use cases, see {@link NetworkInterface}, which lets you
349      * enumerate all available network interfaces and their addresses.</li>
350      * </ul>
351      *
352      * <p>Note that if the host doesn't have a hostname set&nbsp;&ndash; as
353      * Android devices typically don't&nbsp;&ndash; this method will
354      * effectively return the loopback address, albeit by getting the name
355      * {@code localhost} and then doing a lookup to translate that to
356      * {@code 127.0.0.1}.
357      *
358      * @return an {@code InetAddress} representing the local host, or the
359      * loopback address.
360      * @throws UnknownHostException
361      *             if the address lookup fails.
362      */
getLocalHost()363     public static InetAddress getLocalHost() throws UnknownHostException {
364         String host = Libcore.os.uname().nodename;
365         return lookupHostByName(host)[0];
366     }
367 
368     /**
369      * Gets the hashcode of the represented IP address.
370      *
371      * @return the appropriate hashcode value.
372      */
373     @Override
hashCode()374     public int hashCode() {
375         return Arrays.hashCode(ipaddress);
376     }
377 
378     /**
379      * Resolves a hostname to its IP addresses using a cache.
380      *
381      * @param host the hostname to resolve.
382      * @return the IP addresses of the host.
383      */
lookupHostByName(String host)384     private static InetAddress[] lookupHostByName(String host) throws UnknownHostException {
385         BlockGuard.getThreadPolicy().onNetwork();
386         // Do we have a result cached?
387         Object cachedResult = addressCache.get(host);
388         if (cachedResult != null) {
389             if (cachedResult instanceof InetAddress[]) {
390                 // A cached positive result.
391                 return (InetAddress[]) cachedResult;
392             } else {
393                 // A cached negative result.
394                 throw new UnknownHostException((String) cachedResult);
395             }
396         }
397         try {
398             StructAddrinfo hints = new StructAddrinfo();
399             hints.ai_flags = AI_ADDRCONFIG;
400             hints.ai_family = AF_UNSPEC;
401             // If we don't specify a socket type, every address will appear twice, once
402             // for SOCK_STREAM and one for SOCK_DGRAM. Since we do not return the family
403             // anyway, just pick one.
404             hints.ai_socktype = SOCK_STREAM;
405             InetAddress[] addresses = Libcore.os.getaddrinfo(host, hints);
406             // TODO: should getaddrinfo set the hostname of the InetAddresses it returns?
407             for (InetAddress address : addresses) {
408                 address.hostName = host;
409             }
410             addressCache.put(host, addresses);
411             return addresses;
412         } catch (GaiException gaiException) {
413             // If the failure appears to have been a lack of INTERNET permission, throw a clear
414             // SecurityException to aid in debugging this common mistake.
415             // http://code.google.com/p/android/issues/detail?id=15722
416             if (gaiException.getCause() instanceof ErrnoException) {
417                 if (((ErrnoException) gaiException.getCause()).errno == EACCES) {
418                     throw new SecurityException("Permission denied (missing INTERNET permission?)", gaiException);
419                 }
420             }
421             // Otherwise, throw an UnknownHostException.
422             String detailMessage = "Unable to resolve host \"" + host + "\": " + Libcore.os.gai_strerror(gaiException.error);
423             addressCache.putUnknownHost(host, detailMessage);
424             throw gaiException.rethrowAsUnknownHostException(detailMessage);
425         }
426     }
427 
428     /**
429      * Removes all entries from the VM's DNS cache. This does not affect the C library's DNS
430      * cache, nor any caching DNS servers between you and the canonical server.
431      * @hide
432      */
clearDnsCache()433     public static void clearDnsCache() {
434         addressCache.clear();
435     }
436 
getHostByAddrImpl(InetAddress address)437     private static InetAddress getHostByAddrImpl(InetAddress address) throws UnknownHostException {
438         BlockGuard.getThreadPolicy().onNetwork();
439         try {
440             String hostname = Libcore.os.getnameinfo(address, NI_NAMEREQD);
441             return makeInetAddress(address.ipaddress.clone(), hostname);
442         } catch (GaiException gaiException) {
443             throw gaiException.rethrowAsUnknownHostException();
444         }
445     }
446 
447     /**
448      * Returns a string containing the host name (if available) and host address.
449      * For example: {@code "www.google.com/74.125.224.115"} or {@code "/127.0.0.1"}.
450      *
451      * <p>IPv6 addresses may additionally include an interface name or scope id.
452      * For example: {@code "www.google.com/2001:4860:4001:803::1013%eth0"} or
453      * {@code "/2001:4860:4001:803::1013%2"}.
454      */
toString()455     @Override public String toString() {
456         return (hostName == null ? "" : hostName) + "/" + getHostAddress();
457     }
458 
459     /**
460      * Returns true if the string is a valid numeric IPv4 or IPv6 address (such as "192.168.0.1").
461      * This copes with all forms of address that Java supports, detailed in the {@link InetAddress}
462      * class documentation.
463      *
464      * @hide used by frameworks/base to ensure that a getAllByName won't cause a DNS lookup.
465      */
isNumeric(String address)466     public static boolean isNumeric(String address) {
467         InetAddress inetAddress = parseNumericAddressNoThrow(address);
468         return inetAddress != null && disallowDeprecatedFormats(address, inetAddress) != null;
469     }
470 
471     /**
472      * Returns an InetAddress corresponding to the given numeric address (such
473      * as {@code "192.168.0.1"} or {@code "2001:4860:800d::68"}).
474      * This method will never do a DNS lookup. Non-numeric addresses are errors.
475      *
476      * @hide used by frameworks/base's NetworkUtils.numericToInetAddress
477      * @throws IllegalArgumentException if {@code numericAddress} is not a numeric address
478      */
parseNumericAddress(String numericAddress)479     public static InetAddress parseNumericAddress(String numericAddress) {
480         if (numericAddress == null || numericAddress.isEmpty()) {
481             return Inet6Address.LOOPBACK;
482         }
483         InetAddress result = parseNumericAddressNoThrow(numericAddress);
484         result = disallowDeprecatedFormats(numericAddress, result);
485         if (result == null) {
486             throw new IllegalArgumentException("Not a numeric address: " + numericAddress);
487         }
488         return result;
489     }
490 
loopbackAddresses()491     private static InetAddress[] loopbackAddresses() {
492         return new InetAddress[] { Inet6Address.LOOPBACK, Inet4Address.LOOPBACK };
493     }
494 
495     /**
496      * Returns the IPv6 loopback address {@code ::1} or the IPv4 loopback address {@code 127.0.0.1}.
497      * @since 1.7
498      * @hide 1.7
499      */
getLoopbackAddress()500     public static InetAddress getLoopbackAddress() {
501         return Inet6Address.LOOPBACK;
502     }
503 
504     /**
505      * Returns whether this is the IPv6 unspecified wildcard address {@code ::}
506      * or the IPv4 "any" address, {@code 0.0.0.0}.
507      */
isAnyLocalAddress()508     public boolean isAnyLocalAddress() {
509         return false;
510     }
511 
512     /**
513      * Returns whether this address is a link-local address or not.
514      *
515      * <p>Valid IPv6 link-local addresses have the prefix {@code fe80::/10}.
516      *
517      * <p><a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a>
518      * "Default Address Selection for Internet Protocol Version 6 (IPv6)" states
519      * that both IPv4 auto-configuration addresses (prefix {@code 169.254/16}) and
520      * IPv4 loopback addresses (prefix {@code 127/8}) have link-local scope, but
521      * {@link Inet4Address} only considers the auto-configuration addresses
522      * to have link-local scope. That is: the IPv4 loopback address returns false.
523      */
isLinkLocalAddress()524     public boolean isLinkLocalAddress() {
525         return false;
526     }
527 
528     /**
529      * Returns whether this address is a loopback address or not.
530      *
531      * <p>Valid IPv4 loopback addresses have the prefix {@code 127/8}.
532      *
533      * <p>The only valid IPv6 loopback address is {@code ::1}.
534      */
isLoopbackAddress()535     public boolean isLoopbackAddress() {
536         return false;
537     }
538 
539     /**
540      * Returns whether this address is a global multicast address or not.
541      *
542      * <p>Valid IPv6 global multicast addresses have the prefix {@code ffxe::/16},
543      * where {@code x} is a set of flags and the additional 112 bits make
544      * up the global multicast address space.
545      *
546      * <p>Valid IPv4 global multicast addresses are the range of addresses
547      * from {@code 224.0.1.0} to {@code 238.255.255.255}.
548      */
isMCGlobal()549     public boolean isMCGlobal() {
550         return false;
551     }
552 
553     /**
554      * Returns whether this address is a link-local multicast address or not.
555      *
556      * <p>Valid IPv6 link-local multicast addresses have the prefix {@code ffx2::/16},
557      * where x is a set of flags and the additional 112 bits make up the link-local multicast
558      * address space.
559      *
560      * <p>Valid IPv4 link-local multicast addresses have the prefix {@code 224.0.0/24}.
561      */
isMCLinkLocal()562     public boolean isMCLinkLocal() {
563         return false;
564     }
565 
566     /**
567      * Returns whether this address is a node-local multicast address or not.
568      *
569      * <p>Valid IPv6 node-local multicast addresses have the prefix {@code ffx1::/16},
570      * where x is a set of flags and the additional 112 bits make up the link-local multicast
571      * address space.
572      *
573      * <p>There are no valid IPv4 node-local multicast addresses.
574      */
isMCNodeLocal()575     public boolean isMCNodeLocal() {
576         return false;
577     }
578 
579     /**
580      * Returns whether this address is a organization-local multicast address or not.
581      *
582      * <p>Valid IPv6 organization-local multicast addresses have the prefix {@code ffx8::/16},
583      * where x is a set of flags and the additional 112 bits make up the link-local multicast
584      * address space.
585      *
586      * <p>Valid IPv4 organization-local multicast addresses have the prefix {@code 239.192/14}.
587      */
isMCOrgLocal()588     public boolean isMCOrgLocal() {
589         return false;
590     }
591 
592     /**
593      * Returns whether this address is a site-local multicast address or not.
594      *
595      * <p>Valid IPv6 site-local multicast addresses have the prefix {@code ffx5::/16},
596      * where x is a set of flags and the additional 112 bits make up the link-local multicast
597      * address space.
598      *
599      * <p>Valid IPv4 site-local multicast addresses have the prefix {@code 239.255/16}.
600      */
isMCSiteLocal()601     public boolean isMCSiteLocal() {
602         return false;
603     }
604 
605     /**
606      * Returns whether this address is a multicast address or not.
607      *
608      * <p>Valid IPv6 multicast addresses have the prefix {@code ff::/8}.
609      *
610      * <p>Valid IPv4 multicast addresses have the prefix {@code 224/4}.
611      */
isMulticastAddress()612     public boolean isMulticastAddress() {
613         return false;
614     }
615 
616     /**
617      * Returns whether this address is a site-local address or not.
618      *
619      * <p>For the purposes of this method, valid IPv6 site-local addresses have
620      * the deprecated prefix {@code fec0::/10} from
621      * <a href="http://www.ietf.org/rfc/rfc1884.txt">RFC 1884</a>,
622      * <i>not</i> the modern prefix {@code fc00::/7} from
623      * <a href="http://www.ietf.org/rfc/rfc4193.txt">RFC 4193</a>.
624      *
625      * <p><a href="http://www.ietf.org/rfc/rfc3484.txt">RFC 3484</a>
626      * "Default Address Selection for Internet Protocol Version 6 (IPv6)" states
627      * that IPv4 private addresses have the prefix {@code 10/8}, {@code 172.16/12},
628      * or {@code 192.168/16}.
629      *
630      * @return {@code true} if this instance represents a site-local address,
631      *         {@code false} otherwise.
632      */
isSiteLocalAddress()633     public boolean isSiteLocalAddress() {
634         return false;
635     }
636 
637     /**
638      * Tries to reach this {@code InetAddress}. This method first tries to use
639      * ICMP <i>(ICMP ECHO REQUEST)</i>, falling back to a TCP connection
640      * on port 7 (Echo) of the remote host.
641      *
642      * @param timeout
643      *            timeout in milliseconds before the test fails if no connection
644      *            could be established.
645      * @return {@code true} if this address is reachable, {@code false}
646      *         otherwise.
647      * @throws IOException
648      *             if an error occurs during an I/O operation.
649      * @throws IllegalArgumentException
650      *             if timeout is less than zero.
651      */
isReachable(int timeout)652     public boolean isReachable(int timeout) throws IOException {
653         return isReachable(null, 0, timeout);
654     }
655 
656     /**
657      * Tries to reach this {@code InetAddress}. This method first tries to use
658      * ICMP <i>(ICMP ECHO REQUEST)</i>, falling back to a TCP connection
659      * on port 7 (Echo) of the remote host.
660      *
661      * @param networkInterface
662      *            the network interface on which to connection should be
663      *            established.
664      * @param ttl
665      *            the maximum count of hops (time-to-live).
666      * @param timeout
667      *            timeout in milliseconds before the test fails if no connection
668      *            could be established.
669      * @return {@code true} if this address is reachable, {@code false}
670      *         otherwise.
671      * @throws IOException
672      *             if an error occurs during an I/O operation.
673      * @throws IllegalArgumentException
674      *             if ttl or timeout is less than zero.
675      */
isReachable(NetworkInterface networkInterface, final int ttl, final int timeout)676     public boolean isReachable(NetworkInterface networkInterface, final int ttl, final int timeout) throws IOException {
677         if (ttl < 0 || timeout < 0) {
678             throw new IllegalArgumentException("ttl < 0 || timeout < 0");
679         }
680 
681         // The simple case.
682         if (networkInterface == null) {
683             return isReachable(this, null, timeout);
684         }
685 
686         // Try each NetworkInterface in parallel.
687         // Use a thread pool Executor?
688         List<InetAddress> sourceAddresses = Collections.list(networkInterface.getInetAddresses());
689         if (sourceAddresses.isEmpty()) {
690             return false;
691         }
692         final InetAddress destinationAddress = this;
693         final CountDownLatch latch = new CountDownLatch(sourceAddresses.size());
694         final AtomicBoolean isReachable = new AtomicBoolean(false);
695         for (final InetAddress sourceAddress : sourceAddresses) {
696             new Thread() {
697                 @Override public void run() {
698                     try {
699                         if (isReachable(destinationAddress, sourceAddress, timeout)) {
700                             isReachable.set(true);
701                             // Wake the main thread so it can return success without
702                             // waiting for any other threads to time out.
703                             while (latch.getCount() > 0) {
704                                 latch.countDown();
705                             }
706                         }
707                     } catch (IOException ignored) {
708                     }
709                     latch.countDown();
710                 }
711             }.start();
712         }
713         try {
714             latch.await();
715         } catch (InterruptedException ignored) {
716             Thread.currentThread().interrupt(); // Leave the interrupted bit set.
717         }
718         return isReachable.get();
719     }
720 
isReachable(InetAddress destination, InetAddress source, int timeout)721     private boolean isReachable(InetAddress destination, InetAddress source, int timeout) throws IOException {
722         // TODO: try ICMP first (http://code.google.com/p/android/issues/detail?id=20106)
723         FileDescriptor fd = IoBridge.socket(true);
724         boolean reached = false;
725         try {
726             if (source != null) {
727                 IoBridge.bind(fd, source, 0);
728             }
729             IoBridge.connect(fd, destination, 7, timeout);
730             reached = true;
731         } catch (IOException e) {
732             if (e.getCause() instanceof ErrnoException) {
733                 // "Connection refused" means the IP address was reachable.
734                 reached = (((ErrnoException) e.getCause()).errno == ECONNREFUSED);
735             }
736         }
737 
738         IoBridge.closeSocket(fd);
739 
740         return reached;
741     }
742 
743     /**
744      * Equivalent to {@code getByAddress(null, ipAddress)}. Handy for addresses with
745      * no associated hostname.
746      */
getByAddress(byte[] ipAddress)747     public static InetAddress getByAddress(byte[] ipAddress) throws UnknownHostException {
748         return getByAddress(null, ipAddress, 0);
749     }
750 
751     /**
752      * Returns an {@code InetAddress} corresponding to the given network-order
753      * bytes {@code ipAddress} and {@code scopeId}.
754      *
755      * <p>For an IPv4 address, the byte array must be of length 4.
756      * For IPv6, the byte array must be of length 16. Any other length will cause an {@code
757      * UnknownHostException}.
758      *
759      * <p>No reverse lookup is performed. The given {@code hostName} (which may be null) is
760      * associated with the new {@code InetAddress} with no validation done.
761      *
762      * <p>(Note that numeric addresses such as {@code "127.0.0.1"} are names for the
763      * purposes of this API. Most callers probably want {@link #getAllByName} instead.)
764      *
765      * @throws UnknownHostException if {@code ipAddress} is null or the wrong length.
766      */
getByAddress(String hostName, byte[] ipAddress)767     public static InetAddress getByAddress(String hostName, byte[] ipAddress) throws UnknownHostException {
768         return getByAddress(hostName, ipAddress, 0);
769     }
770 
getByAddress(String hostName, byte[] ipAddress, int scopeId)771     private static InetAddress getByAddress(String hostName, byte[] ipAddress, int scopeId) throws UnknownHostException {
772         if (ipAddress == null) {
773             throw new UnknownHostException("ipAddress == null");
774         }
775         if (ipAddress.length == 4) {
776             return new Inet4Address(ipAddress.clone(), hostName);
777         } else if (ipAddress.length == 16) {
778             // First check to see if the address is an IPv6-mapped
779             // IPv4 address. If it is, then we can make it a IPv4
780             // address, otherwise, we'll create an IPv6 address.
781             if (isIPv4MappedAddress(ipAddress)) {
782                 return new Inet4Address(ipv4MappedToIPv4(ipAddress), hostName);
783             } else {
784                 return new Inet6Address(ipAddress.clone(), hostName, scopeId);
785             }
786         } else {
787             throw badAddressLength(ipAddress);
788         }
789     }
790 
badAddressLength(byte[] bytes)791     private static UnknownHostException badAddressLength(byte[] bytes) throws UnknownHostException {
792         throw new UnknownHostException("Address is neither 4 or 16 bytes: " + Arrays.toString(bytes));
793     }
794 
isIPv4MappedAddress(byte[] ipAddress)795     private static boolean isIPv4MappedAddress(byte[] ipAddress) {
796         // Check if the address matches ::FFFF:d.d.d.d
797         // The first 10 bytes are 0. The next to are -1 (FF).
798         // The last 4 bytes are varied.
799         if (ipAddress == null || ipAddress.length != 16) {
800             return false;
801         }
802         for (int i = 0; i < 10; i++) {
803             if (ipAddress[i] != 0) {
804                 return false;
805             }
806         }
807         if (ipAddress[10] != -1 || ipAddress[11] != -1) {
808             return false;
809         }
810         return true;
811     }
812 
ipv4MappedToIPv4(byte[] mappedAddress)813     private static byte[] ipv4MappedToIPv4(byte[] mappedAddress) {
814         byte[] ipv4Address = new byte[4];
815         for (int i = 0; i < 4; i++) {
816             ipv4Address[i] = mappedAddress[12 + i];
817         }
818         return ipv4Address;
819     }
820 
821     private static final ObjectStreamField[] serialPersistentFields = {
822         new ObjectStreamField("address", int.class),
823         new ObjectStreamField("family", int.class),
824         new ObjectStreamField("hostName", String.class),
825     };
826 
writeObject(ObjectOutputStream stream)827     private void writeObject(ObjectOutputStream stream) throws IOException {
828         ObjectOutputStream.PutField fields = stream.putFields();
829         if (ipaddress == null) {
830             fields.put("address", 0);
831         } else {
832             fields.put("address", Memory.peekInt(ipaddress, 0, ByteOrder.BIG_ENDIAN));
833         }
834         fields.put("family", family);
835         fields.put("hostName", hostName);
836 
837         stream.writeFields();
838     }
839 
readObject(ObjectInputStream stream)840     private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
841         ObjectInputStream.GetField fields = stream.readFields();
842         int addr = fields.get("address", 0);
843         ipaddress = new byte[4];
844         Memory.pokeInt(ipaddress, 0, addr, ByteOrder.BIG_ENDIAN);
845         hostName = (String) fields.get("hostName", null);
846         family = fields.get("family", 2);
847     }
848 
849     /*
850      * The spec requires that if we encounter a generic InetAddress in
851      * serialized form then we should interpret it as an Inet4Address.
852      */
readResolve()853     private Object readResolve() throws ObjectStreamException {
854         return new Inet4Address(ipaddress, hostName);
855     }
856 }
857