151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project
37f4b1b8935a58d3f44351083cf5ef19045761de3Yi Kong * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.net;
27c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamathimport android.system.ErrnoException;
28c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamathimport android.system.GaiException;
29c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamathimport android.system.StructAddrinfo;
3048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kongimport android.system.StructIcmpHdr;
3148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
32c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamathimport dalvik.system.BlockGuard;
332be229c284db4293a86200fa800886fed137e567Yi Kong
342be229c284db4293a86200fa800886fed137e567Yi Kongimport libcore.io.IoBridge;
35c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamathimport libcore.io.Libcore;
36c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
372be229c284db4293a86200fa800886fed137e567Yi Kongimport java.io.FileDescriptor;
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.io.IOException;
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kongimport static android.system.OsConstants.AF_INET;
4148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kongimport static android.system.OsConstants.AF_INET6;
42c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamathimport static android.system.OsConstants.AF_UNSPEC;
43c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamathimport static android.system.OsConstants.AI_ADDRCONFIG;
44c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamathimport static android.system.OsConstants.EACCES;
452be229c284db4293a86200fa800886fed137e567Yi Kongimport static android.system.OsConstants.ECONNREFUSED;
46b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kongimport static android.system.OsConstants.NI_NAMEREQD;
4748e205e5e0bc55b5c7b11df445da39c5be890623Yi Kongimport static android.system.OsConstants.ICMP6_ECHO_REPLY;
4848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kongimport static android.system.OsConstants.ICMP_ECHOREPLY;
4948e205e5e0bc55b5c7b11df445da39c5be890623Yi Kongimport static android.system.OsConstants.IPPROTO_ICMP;
5048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kongimport static android.system.OsConstants.IPPROTO_ICMPV6;
5148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kongimport static android.system.OsConstants.SOCK_DGRAM;
52c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamathimport static android.system.OsConstants.SOCK_STREAM;
53c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
5471921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang// Android-note: Android-specific behavior and Linux-based implementation
5571921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang// http://b/36933260 Implement root-less ICMP for isReachable()
5671921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang// http://b/28609551 Rewrite getHostByAddr0 using POSIX library Libcore.os.
5771921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang// http://b/25861497 Add BlockGuard checks.
5871921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang// http://b/26700324 Fix odd dependency chains of the static InetAddress.
5971921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang// anyLocalAddress() Let anyLocalAddress() always return an IPv6 address.
6071921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang// Let loopbackAddresses() return both Inet4 and Inet6 loopbacks.
6171921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang// Rewrote hostname lookup methods on top of Libcore.os. Merge implementation from InetAddress
6271921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang//   and remove native methods in this class
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Package private implementation of InetAddressImpl for dual
65c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath * IPv4/IPv6 stack. {@code #anyLocalAddress()} will always return an IPv6 address.
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.4
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiclass Inet6AddressImpl implements InetAddressImpl {
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
725427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath    // @GuardedBy(Inet6AddressImpl.class)
735427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath    private static InetAddress anyLocalAddress;
745427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath    // @GuardedBy(Inet6AddressImpl.class)
755427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath    private static InetAddress[] loopbackAddresses;
76c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
77c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    private static final AddressCache addressCache = new AddressCache();
78c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
7971921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang    // BEGIN Android-changed: Rewrote hostname lookup methods on top of Libcore.os.
8071921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang    /*
8171921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang    public native String getLocalHostName() throws UnknownHostException;
8271921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang    public native InetAddress[]
8371921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang        lookupAllHostAddr(String hostname) throws UnknownHostException;
8471921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang    public native String getHostByAddr(byte[] addr) throws UnknownHostException;
8571921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang    private native boolean isReachable0(byte[] addr, int scope, int timeout, byte[] inf, int ttl, int if_scope) throws IOException;
8671921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang    */
87c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    @Override
88c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    public InetAddress[] lookupAllHostAddr(String host, int netId) throws UnknownHostException {
89c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        if (host == null || host.isEmpty()) {
906975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer            // Android-changed: Return both the Inet4 and Inet6 loopback addresses
91c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // when host == null or empty.
92c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            return loopbackAddresses();
93c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        }
94c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
95c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        // Is it a numeric address?
96c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        InetAddress result = InetAddress.parseNumericAddressNoThrow(host);
97c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        if (result != null) {
98c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            result = InetAddress.disallowDeprecatedFormats(host, result);
99c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            if (result == null) {
100c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                throw new UnknownHostException("Deprecated IPv4 address format: " + host);
101c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            }
102c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            return new InetAddress[] { result };
103c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        }
104c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
105d960ef32a57a91e4ea0976a2bbd97b8ec0fd2cf0Narayan Kamath        return lookupHostByName(host, netId);
106c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    }
107c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
108c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    /**
109c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath     * Resolves a hostname to its IP addresses using a cache.
110c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath     *
111c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath     * @param host the hostname to resolve.
112c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath     * @param netId the network to perform resolution upon.
113c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath     * @return the IP addresses of the host.
114c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath     */
115c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    private static InetAddress[] lookupHostByName(String host, int netId)
116c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            throws UnknownHostException {
117c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        BlockGuard.getThreadPolicy().onNetwork();
118c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        // Do we have a result cached?
119c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        Object cachedResult = addressCache.get(host, netId);
120c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        if (cachedResult != null) {
121c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            if (cachedResult instanceof InetAddress[]) {
122c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                // A cached positive result.
123c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                return (InetAddress[]) cachedResult;
124c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            } else {
125c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                // A cached negative result.
126c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                throw new UnknownHostException((String) cachedResult);
127c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            }
128c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        }
129c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        try {
130c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            StructAddrinfo hints = new StructAddrinfo();
131c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            hints.ai_flags = AI_ADDRCONFIG;
132c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            hints.ai_family = AF_UNSPEC;
133c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // If we don't specify a socket type, every address will appear twice, once
134c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // for SOCK_STREAM and one for SOCK_DGRAM. Since we do not return the family
135c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // anyway, just pick one.
136c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            hints.ai_socktype = SOCK_STREAM;
137c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            InetAddress[] addresses = Libcore.os.android_getaddrinfo(host, hints, netId);
138c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // TODO: should getaddrinfo set the hostname of the InetAddresses it returns?
139c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            for (InetAddress address : addresses) {
140c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                address.holder().hostName = host;
1418eb286d0dbb87d9152f2bd3617629844ce2a913dPrzemyslaw Szczepaniak                address.holder().originalHostName = host;
142c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            }
143c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            addressCache.put(host, netId, addresses);
144c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            return addresses;
145c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        } catch (GaiException gaiException) {
146c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // If the failure appears to have been a lack of INTERNET permission, throw a clear
147c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // SecurityException to aid in debugging this common mistake.
148c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // http://code.google.com/p/android/issues/detail?id=15722
149c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            if (gaiException.getCause() instanceof ErrnoException) {
150c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                if (((ErrnoException) gaiException.getCause()).errno == EACCES) {
151c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                    throw new SecurityException("Permission denied (missing INTERNET permission?)", gaiException);
152c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                }
153c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            }
154c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // Otherwise, throw an UnknownHostException.
155c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            String detailMessage = "Unable to resolve host \"" + host + "\": " + Libcore.os.gai_strerror(gaiException.error);
156c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            addressCache.putUnknownHost(host, netId, detailMessage);
157c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            throw gaiException.rethrowAsUnknownHostException(detailMessage);
158c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        }
159c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    }
160c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
161c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    @Override
162c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    public String getHostByAddr(byte[] addr) throws UnknownHostException {
163c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        BlockGuard.getThreadPolicy().onNetwork();
164c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
165c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        return getHostByAddr0(addr);
166c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    }
167c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
168c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    @Override
169c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    public void clearAddressCache() {
170c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        addressCache.clear();
171c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    }
17271921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang    // END Android-changed: Rewrote hostname lookup methods on top of Libcore.os.
173c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
174c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    @Override
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean isReachable(InetAddress addr, int timeout, NetworkInterface netif, int ttl) throws IOException {
17671921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang        // Android-changed: rewritten on the top of IoBridge and Libcore.os.
1772be229c284db4293a86200fa800886fed137e567Yi Kong        InetAddress sourceAddr = null;
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (netif != null) {
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /*
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * Let's make sure we bind to an address of the proper family.
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * Which means same family as addr because at this point it could
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * be either an IPv6 address or an IPv4 address (case of a dual
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * stack system).
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             */
1853a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong            java.util.Enumeration<InetAddress> it = netif.getInetAddresses();
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            InetAddress inetaddr = null;
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (it.hasMoreElements()) {
1883a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong                inetaddr = it.nextElement();
18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (inetaddr.getClass().isInstance(addr)) {
1902be229c284db4293a86200fa800886fed137e567Yi Kong                    sourceAddr = inetaddr;
19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    break;
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
1942be229c284db4293a86200fa800886fed137e567Yi Kong
1952be229c284db4293a86200fa800886fed137e567Yi Kong            if (sourceAddr == null) {
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Interface doesn't support the address family of
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // the destination
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return false;
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
201c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
20271921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang        // Android-changed: http://b/36933260 Implement root-less ICMP for isReachable().
20371921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang        /*
20471921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang        if (addr instanceof Inet6Address)
20571921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang            scope = ((Inet6Address) addr).getScopeId();
20671921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang        return isReachable0(addr.getAddress(), scope, timeout, ifaddr, ttl, netif_scope);
20771921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang        */
20848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        // Try ICMP first
20948e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        if (icmpEcho(addr, timeout, sourceAddr, ttl)) {
21048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            return true;
21148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        }
21248e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
21348e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        // No good, let's fall back to TCP
21448e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        return tcpEcho(addr, timeout, sourceAddr, ttl);
21548e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong    }
21648e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
21771921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang    // BEGIN Android-added: http://b/36933260 Implement root-less ICMP for isReachable().
21848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong    private boolean tcpEcho(InetAddress addr, int timeout, InetAddress sourceAddr, int ttl)
21948e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            throws IOException {
22048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        FileDescriptor fd = null;
221838dc8ab4b456d91e56b46f7deb76a8f97145563Narayan Kamath        try {
22248e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            fd = IoBridge.socket(AF_INET6, SOCK_STREAM, 0);
22348e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            if (ttl > 0) {
22448e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                IoBridge.setSocketOption(fd, IoBridge.JAVA_IP_TTL, ttl);
22548e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            }
2262be229c284db4293a86200fa800886fed137e567Yi Kong            if (sourceAddr != null) {
2272be229c284db4293a86200fa800886fed137e567Yi Kong                IoBridge.bind(fd, sourceAddr, 0);
2282be229c284db4293a86200fa800886fed137e567Yi Kong            }
2292be229c284db4293a86200fa800886fed137e567Yi Kong            IoBridge.connect(fd, addr, 7 /* Echo-protocol port */, timeout);
2302be229c284db4293a86200fa800886fed137e567Yi Kong            return true;
2312be229c284db4293a86200fa800886fed137e567Yi Kong        } catch (IOException e) {
2322be229c284db4293a86200fa800886fed137e567Yi Kong            // Connection refused by remote (ECONNREFUSED) implies reachable. Otherwise silently
2332be229c284db4293a86200fa800886fed137e567Yi Kong            // ignore the exception and return false.
2342be229c284db4293a86200fa800886fed137e567Yi Kong            Throwable cause = e.getCause();
2352be229c284db4293a86200fa800886fed137e567Yi Kong            return cause instanceof ErrnoException
2362be229c284db4293a86200fa800886fed137e567Yi Kong                    && ((ErrnoException) cause).errno == ECONNREFUSED;
2372be229c284db4293a86200fa800886fed137e567Yi Kong        } finally {
2382be229c284db4293a86200fa800886fed137e567Yi Kong            IoBridge.closeAndSignalBlockedThreads(fd);
239838dc8ab4b456d91e56b46f7deb76a8f97145563Narayan Kamath        }
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24248e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong    protected boolean icmpEcho(InetAddress addr, int timeout, InetAddress sourceAddr, int ttl)
24348e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            throws IOException {
24448e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
24548e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        FileDescriptor fd = null;
24648e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        try {
24748e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            boolean isIPv4 = addr instanceof Inet4Address;
24848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            int domain = isIPv4 ? AF_INET : AF_INET6;
24948e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            int icmpProto = isIPv4 ? IPPROTO_ICMP : IPPROTO_ICMPV6;
25048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            fd = IoBridge.socket(domain, SOCK_DGRAM, icmpProto);
25148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
25248e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            if (ttl > 0) {
25348e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                IoBridge.setSocketOption(fd, IoBridge.JAVA_IP_TTL, ttl);
25448e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            }
25548e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            if (sourceAddr != null) {
25648e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                IoBridge.bind(fd, sourceAddr, 0);
25748e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            }
25848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
25948e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            byte[] packet;
26048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
26148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            // ICMP is unreliable, try sending requests every second until timeout.
26248e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            for (int to = timeout, seq = 0; to > 0; ++seq) {
26348e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                int sockTo = to >= 1000 ? 1000 : to;
26448e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
26548e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                IoBridge.setSocketOption(fd, SocketOptions.SO_TIMEOUT, sockTo);
26648e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
26748e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                packet = StructIcmpHdr.IcmpEchoHdr(isIPv4, seq).getBytes();
26848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                IoBridge.sendto(fd, packet, 0, packet.length, 0, addr, 0);
2692c0c75bb3c933b4cc03e9fbe0c30df1e4be1cc48Yi Kong                final int icmpId = IoBridge.getLocalInetSocketAddress(fd).getPort();
27048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
27148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                byte[] received = new byte[packet.length];
27248e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                DatagramPacket receivedPacket = new DatagramPacket(received, packet.length);
27348e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                int size = IoBridge
27448e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                        .recvfrom(true, fd, received, 0, received.length, 0, receivedPacket, false);
27548e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                if (size == packet.length) {
27648e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                    byte expectedType = isIPv4 ? (byte) ICMP_ECHOREPLY
27748e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                            : (byte) ICMP6_ECHO_REPLY;
27848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                    if (receivedPacket.getAddress().equals(addr)
27948e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                            && received[0] == expectedType
28048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                            && received[4] == (byte) (icmpId >> 8)
28148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                            && received[5] == (byte) icmpId
28248e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                            && received[6] == (byte) (seq >> 8)
28348e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                            && received[7] == (byte) seq) {
28448e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                        // This is the packet we're expecting.
28548e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                        return true;
28648e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                    }
28748e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                }
28848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                to -= sockTo;
28948e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            }
29048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        } catch (IOException e) {
29148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            // Silently ignore and fall back.
29248e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        } finally {
29368997dc82c20258a27ee1a33642e0275abda272aLuis Hector Chavez            if (fd != null) {
29468997dc82c20258a27ee1a33642e0275abda272aLuis Hector Chavez                try {
29568997dc82c20258a27ee1a33642e0275abda272aLuis Hector Chavez                    Libcore.os.close(fd);
29668997dc82c20258a27ee1a33642e0275abda272aLuis Hector Chavez                } catch (ErrnoException e) { }
29768997dc82c20258a27ee1a33642e0275abda272aLuis Hector Chavez            }
29848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        }
29948e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
30048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        return false;
30148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong    }
30271921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang    // END Android-added: http://b/36933260 Implement root-less ICMP for isReachable().
30348e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
30471921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang    // BEGIN Android-changed: Let anyLocalAddress() always return an IPv6 address.
305c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    @Override
306c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    public InetAddress anyLocalAddress() {
3075427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath        synchronized (Inet6AddressImpl.class) {
3085427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            // We avoid initializing anyLocalAddress during <clinit> to avoid issues
3095427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            // caused by the dependency chains of these classes. InetAddress depends on
3105427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            // InetAddressImpl, but Inet6Address & Inet4Address are its subclasses.
31171921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang            // Also see {@code loopbackAddresses). http://b/26700324
3125427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            if (anyLocalAddress == null) {
3135427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath                Inet6Address anyAddress = new Inet6Address();
3145427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath                anyAddress.holder().hostName = "::";
3155427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath                anyLocalAddress = anyAddress;
3165427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            }
3175427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath
3185427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            return anyLocalAddress;
3195427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath        }
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
32171921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang    // END Android-changed: Let anyLocalAddress() always return an IPv6 address.
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
32371921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang    // BEGIN Android-changed: Let loopbackAddresses() return both Inet4 and Inet6 loopbacks.
324c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    @Override
325c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    public InetAddress[] loopbackAddresses() {
3265427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath        synchronized (Inet6AddressImpl.class) {
3275427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            // We avoid initializing anyLocalAddress during <clinit> to avoid issues
3285427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            // caused by the dependency chains of these classes. InetAddress depends on
3295427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            // InetAddressImpl, but Inet6Address & Inet4Address are its subclasses.
3305427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            // Also see {@code anyLocalAddress).
3315427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            if (loopbackAddresses == null) {
3325427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath                loopbackAddresses = new InetAddress[]{Inet6Address.LOOPBACK, Inet4Address.LOOPBACK};
3335427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            }
3345427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath
3355427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            return loopbackAddresses;
3365427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath        }
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
33871921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang    // END Android-changed: Let loopbackAddresses() return both Inet4 and Inet6 loopbacks.
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
34071921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang    // BEGIN Android-changed: b/28609551 Rewrite getHostByAddr0 using POSIX library Libcore.os.
341b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong    private String getHostByAddr0(byte[] addr) throws UnknownHostException {
342b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong        // Android-changed: Rewritten on the top of Libcore.os
343b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong        InetAddress hostaddr = InetAddress.getByAddress(addr);
344b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong        try {
345b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong            return Libcore.os.getnameinfo(hostaddr, NI_NAMEREQD);
346b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong        } catch (GaiException e) {
347b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong            UnknownHostException uhe = new UnknownHostException(hostaddr.toString());
348b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong            uhe.initCause(e);
349b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong            throw uhe;
350b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong        }
351b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong    }
35271921cf74d80daa1e93e130fcd11b11abb12ead0Victor Chang    // END Android-changed: b/28609551 Rewrite getHostByAddr0 using POSIX library Libcore.os.
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
354