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.IPPROTO_IPV6;
5248e205e5e0bc55b5c7b11df445da39c5be890623Yi Kongimport static android.system.OsConstants.IPV6_UNICAST_HOPS;
5348e205e5e0bc55b5c7b11df445da39c5be890623Yi Kongimport static android.system.OsConstants.SOCK_DGRAM;
54c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamathimport static android.system.OsConstants.SOCK_STREAM;
55c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Package private implementation of InetAddressImpl for dual
58c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath * IPv4/IPv6 stack. {@code #anyLocalAddress()} will always return an IPv6 address.
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.4
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiclass Inet6AddressImpl implements InetAddressImpl {
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
655427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath    // @GuardedBy(Inet6AddressImpl.class)
665427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath    private static InetAddress anyLocalAddress;
675427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath    // @GuardedBy(Inet6AddressImpl.class)
685427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath    private static InetAddress[] loopbackAddresses;
69c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
70c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    private static final AddressCache addressCache = new AddressCache();
71c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
72c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    @Override
73c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    public InetAddress[] lookupAllHostAddr(String host, int netId) throws UnknownHostException {
74c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        if (host == null || host.isEmpty()) {
756975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer            // Android-changed: Return both the Inet4 and Inet6 loopback addresses
76c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // when host == null or empty.
77c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            return loopbackAddresses();
78c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        }
79c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
80c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        // Is it a numeric address?
81c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        InetAddress result = InetAddress.parseNumericAddressNoThrow(host);
82c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        if (result != null) {
83c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            result = InetAddress.disallowDeprecatedFormats(host, result);
84c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            if (result == null) {
85c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                throw new UnknownHostException("Deprecated IPv4 address format: " + host);
86c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            }
87c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            return new InetAddress[] { result };
88c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        }
89c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
90d960ef32a57a91e4ea0976a2bbd97b8ec0fd2cf0Narayan Kamath        return lookupHostByName(host, netId);
91c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    }
92c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
93c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    /**
94c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath     * Resolves a hostname to its IP addresses using a cache.
95c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath     *
96c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath     * @param host the hostname to resolve.
97c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath     * @param netId the network to perform resolution upon.
98c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath     * @return the IP addresses of the host.
99c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath     */
100c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    private static InetAddress[] lookupHostByName(String host, int netId)
101c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            throws UnknownHostException {
102c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        BlockGuard.getThreadPolicy().onNetwork();
103c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        // Do we have a result cached?
104c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        Object cachedResult = addressCache.get(host, netId);
105c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        if (cachedResult != null) {
106c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            if (cachedResult instanceof InetAddress[]) {
107c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                // A cached positive result.
108c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                return (InetAddress[]) cachedResult;
109c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            } else {
110c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                // A cached negative result.
111c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                throw new UnknownHostException((String) cachedResult);
112c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            }
113c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        }
114c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        try {
115c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            StructAddrinfo hints = new StructAddrinfo();
116c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            hints.ai_flags = AI_ADDRCONFIG;
117c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            hints.ai_family = AF_UNSPEC;
118c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // If we don't specify a socket type, every address will appear twice, once
119c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // for SOCK_STREAM and one for SOCK_DGRAM. Since we do not return the family
120c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // anyway, just pick one.
121c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            hints.ai_socktype = SOCK_STREAM;
122c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            InetAddress[] addresses = Libcore.os.android_getaddrinfo(host, hints, netId);
123c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // TODO: should getaddrinfo set the hostname of the InetAddresses it returns?
124c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            for (InetAddress address : addresses) {
125c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                address.holder().hostName = host;
126c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            }
127c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            addressCache.put(host, netId, addresses);
128c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            return addresses;
129c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        } catch (GaiException gaiException) {
130c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // If the failure appears to have been a lack of INTERNET permission, throw a clear
131c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // SecurityException to aid in debugging this common mistake.
132c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // http://code.google.com/p/android/issues/detail?id=15722
133c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            if (gaiException.getCause() instanceof ErrnoException) {
134c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                if (((ErrnoException) gaiException.getCause()).errno == EACCES) {
135c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                    throw new SecurityException("Permission denied (missing INTERNET permission?)", gaiException);
136c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath                }
137c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            }
138c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            // Otherwise, throw an UnknownHostException.
139c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            String detailMessage = "Unable to resolve host \"" + host + "\": " + Libcore.os.gai_strerror(gaiException.error);
140c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            addressCache.putUnknownHost(host, netId, detailMessage);
141c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath            throw gaiException.rethrowAsUnknownHostException(detailMessage);
142c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        }
143c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    }
144c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
145c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    @Override
146c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    public String getHostByAddr(byte[] addr) throws UnknownHostException {
147c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        BlockGuard.getThreadPolicy().onNetwork();
148c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
149c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        return getHostByAddr0(addr);
150c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    }
151c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
152c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    @Override
153c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    public void clearAddressCache() {
154c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath        addressCache.clear();
155c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    }
156c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
157c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    @Override
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public boolean isReachable(InetAddress addr, int timeout, NetworkInterface netif, int ttl) throws IOException {
1592be229c284db4293a86200fa800886fed137e567Yi Kong        // Android-changed: rewritten on the top of IoBridge and Libcore.os
1602be229c284db4293a86200fa800886fed137e567Yi Kong        InetAddress sourceAddr = null;
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (netif != null) {
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /*
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * Let's make sure we bind to an address of the proper family.
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * Which means same family as addr because at this point it could
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * be either an IPv6 address or an IPv4 address (case of a dual
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             * stack system).
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski             */
1683a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong            java.util.Enumeration<InetAddress> it = netif.getInetAddresses();
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            InetAddress inetaddr = null;
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            while (it.hasMoreElements()) {
1713a6411ec91b24e73f36301d0075bc7b052894ae9Yi Kong                inetaddr = it.nextElement();
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                if (inetaddr.getClass().isInstance(addr)) {
1732be229c284db4293a86200fa800886fed137e567Yi Kong                    sourceAddr = inetaddr;
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                    break;
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                }
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
1772be229c284db4293a86200fa800886fed137e567Yi Kong
1782be229c284db4293a86200fa800886fed137e567Yi Kong            if (sourceAddr == null) {
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // Interface doesn't support the address family of
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                // the destination
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return false;
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
184c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath
18548e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        // Try ICMP first
18648e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        if (icmpEcho(addr, timeout, sourceAddr, ttl)) {
18748e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            return true;
18848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        }
18948e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
19048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        // No good, let's fall back to TCP
19148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        return tcpEcho(addr, timeout, sourceAddr, ttl);
19248e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong    }
19348e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
19448e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong    private boolean tcpEcho(InetAddress addr, int timeout, InetAddress sourceAddr, int ttl)
19548e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            throws IOException {
19648e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        FileDescriptor fd = null;
197838dc8ab4b456d91e56b46f7deb76a8f97145563Narayan Kamath        try {
19848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            fd = IoBridge.socket(AF_INET6, SOCK_STREAM, 0);
19948e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            if (ttl > 0) {
20048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                IoBridge.setSocketOption(fd, IoBridge.JAVA_IP_TTL, ttl);
20148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            }
2022be229c284db4293a86200fa800886fed137e567Yi Kong            if (sourceAddr != null) {
2032be229c284db4293a86200fa800886fed137e567Yi Kong                IoBridge.bind(fd, sourceAddr, 0);
2042be229c284db4293a86200fa800886fed137e567Yi Kong            }
2052be229c284db4293a86200fa800886fed137e567Yi Kong            IoBridge.connect(fd, addr, 7 /* Echo-protocol port */, timeout);
2062be229c284db4293a86200fa800886fed137e567Yi Kong            return true;
2072be229c284db4293a86200fa800886fed137e567Yi Kong        } catch (IOException e) {
2082be229c284db4293a86200fa800886fed137e567Yi Kong            // Connection refused by remote (ECONNREFUSED) implies reachable. Otherwise silently
2092be229c284db4293a86200fa800886fed137e567Yi Kong            // ignore the exception and return false.
2102be229c284db4293a86200fa800886fed137e567Yi Kong            Throwable cause = e.getCause();
2112be229c284db4293a86200fa800886fed137e567Yi Kong            return cause instanceof ErrnoException
2122be229c284db4293a86200fa800886fed137e567Yi Kong                    && ((ErrnoException) cause).errno == ECONNREFUSED;
2132be229c284db4293a86200fa800886fed137e567Yi Kong        } finally {
2142be229c284db4293a86200fa800886fed137e567Yi Kong            IoBridge.closeAndSignalBlockedThreads(fd);
215838dc8ab4b456d91e56b46f7deb76a8f97145563Narayan Kamath        }
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong    protected boolean icmpEcho(InetAddress addr, int timeout, InetAddress sourceAddr, int ttl)
21948e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            throws IOException {
22048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
22148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        FileDescriptor fd = null;
22248e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        try {
22348e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            boolean isIPv4 = addr instanceof Inet4Address;
22448e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            int domain = isIPv4 ? AF_INET : AF_INET6;
22548e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            int icmpProto = isIPv4 ? IPPROTO_ICMP : IPPROTO_ICMPV6;
22648e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            fd = IoBridge.socket(domain, SOCK_DGRAM, icmpProto);
22748e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
22848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            if (ttl > 0) {
22948e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                IoBridge.setSocketOption(fd, IoBridge.JAVA_IP_TTL, ttl);
23048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            }
23148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            if (sourceAddr != null) {
23248e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                IoBridge.bind(fd, sourceAddr, 0);
23348e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            }
23448e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
23548e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            byte[] packet;
23648e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
23748e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            // ICMP is unreliable, try sending requests every second until timeout.
23848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            for (int to = timeout, seq = 0; to > 0; ++seq) {
23948e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                int sockTo = to >= 1000 ? 1000 : to;
24048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
24148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                IoBridge.setSocketOption(fd, SocketOptions.SO_TIMEOUT, sockTo);
24248e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
24348e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                packet = StructIcmpHdr.IcmpEchoHdr(isIPv4, seq).getBytes();
24448e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                IoBridge.sendto(fd, packet, 0, packet.length, 0, addr, 0);
2452c0c75bb3c933b4cc03e9fbe0c30df1e4be1cc48Yi Kong                final int icmpId = IoBridge.getLocalInetSocketAddress(fd).getPort();
24648e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
24748e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                byte[] received = new byte[packet.length];
24848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                DatagramPacket receivedPacket = new DatagramPacket(received, packet.length);
24948e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                int size = IoBridge
25048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                        .recvfrom(true, fd, received, 0, received.length, 0, receivedPacket, false);
25148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                if (size == packet.length) {
25248e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                    byte expectedType = isIPv4 ? (byte) ICMP_ECHOREPLY
25348e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                            : (byte) ICMP6_ECHO_REPLY;
25448e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                    if (receivedPacket.getAddress().equals(addr)
25548e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                            && received[0] == expectedType
25648e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                            && received[4] == (byte) (icmpId >> 8)
25748e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                            && received[5] == (byte) icmpId
25848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                            && received[6] == (byte) (seq >> 8)
25948e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                            && received[7] == (byte) seq) {
26048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                        // This is the packet we're expecting.
26148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                        return true;
26248e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                    }
26348e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                }
26448e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                to -= sockTo;
26548e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            }
26648e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        } catch (IOException e) {
26748e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            // Silently ignore and fall back.
26848e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        } finally {
26948e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            try {
27048e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong                Libcore.os.close(fd);
27148e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong            } catch (ErrnoException e) { }
27248e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        }
27348e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
27448e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong        return false;
27548e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong    }
27648e205e5e0bc55b5c7b11df445da39c5be890623Yi Kong
277c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    @Override
278c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    public InetAddress anyLocalAddress() {
2795427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath        synchronized (Inet6AddressImpl.class) {
2805427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            // We avoid initializing anyLocalAddress during <clinit> to avoid issues
2815427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            // caused by the dependency chains of these classes. InetAddress depends on
2825427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            // InetAddressImpl, but Inet6Address & Inet4Address are its subclasses.
2835427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            // Also see {@code loopbackAddresses).
2845427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            if (anyLocalAddress == null) {
2855427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath                Inet6Address anyAddress = new Inet6Address();
2865427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath                anyAddress.holder().hostName = "::";
2875427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath                anyLocalAddress = anyAddress;
2885427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            }
2895427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath
2905427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            return anyLocalAddress;
2915427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath        }
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
294c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    @Override
295c2614bb1297234d89f1a428a8b589bb1373a68ddNarayan Kamath    public InetAddress[] loopbackAddresses() {
2965427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath        synchronized (Inet6AddressImpl.class) {
2975427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            // We avoid initializing anyLocalAddress during <clinit> to avoid issues
2985427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            // caused by the dependency chains of these classes. InetAddress depends on
2995427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            // InetAddressImpl, but Inet6Address & Inet4Address are its subclasses.
3005427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            // Also see {@code anyLocalAddress).
3015427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            if (loopbackAddresses == null) {
3025427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath                loopbackAddresses = new InetAddress[]{Inet6Address.LOOPBACK, Inet4Address.LOOPBACK};
3035427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            }
3045427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath
3055427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath            return loopbackAddresses;
3065427c8d283752ae3c41fb0bb083d562060c5be08Narayan Kamath        }
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
309b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong    private String getHostByAddr0(byte[] addr) throws UnknownHostException {
310b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong        // Android-changed: Rewritten on the top of Libcore.os
311b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong        InetAddress hostaddr = InetAddress.getByAddress(addr);
312b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong        try {
313b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong            return Libcore.os.getnameinfo(hostaddr, NI_NAMEREQD);
314b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong        } catch (GaiException e) {
315b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong            UnknownHostException uhe = new UnknownHostException(hostaddr.toString());
316b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong            uhe.initCause(e);
317b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong            throw uhe;
318b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong        }
319b11d8b52b4ea85ab56a033fc76b21bf3b50a1b3eYi Kong    }
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
321