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