1 /*
  2  * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 package java.net;
 26 
 27 import java.io.IOException;
 28 
 29 import static java.net.InetAddress.IPv6;
 30 import static java.net.InetAddress.PREFER_IPV6_VALUE;
 31 import static java.net.InetAddress.PREFER_SYSTEM_VALUE;
 32 
 33 /*
 34  * Package private implementation of InetAddressImpl for dual
 35  * IPv4/IPv6 stack.
 36  * <p>
 37  * If InetAddress.preferIPv6Address is true then anyLocalAddress()
 38  * and localHost() will return IPv6 addresses, otherwise IPv4 addresses.
 39  *
 40  * loopbackAddress() will return the first valid loopback address in
 41  * [IPv6 loopback, IPv4 loopback] if InetAddress.preferIPv6Address is true,
 42  * else [IPv4 loopback, IPv6 loopback].
 43  * If neither are valid it will fallback to the first address tried.
 44  *
 45  * @since 1.4
 46  */
 47 final class Inet6AddressImpl implements InetAddressImpl {
 48 
 49     public native String getLocalHostName() throws UnknownHostException;
 50 
 51     public native InetAddress[] lookupAllHostAddr(String hostname)
 52         throws UnknownHostException;
 53 
 54     public native String getHostByAddr(byte[] addr) throws UnknownHostException;
 55 
 56     private native boolean isReachable0(byte[] addr, int scope, int timeout,
 57                                         byte[] inf, int ttl, int if_scope)
 58         throws IOException;
 59 
 60     public boolean isReachable(InetAddress addr, int timeout,
 61                                NetworkInterface netif, int ttl)
 62         throws IOException
 63     {
 64         byte[] ifaddr = null;
 65         int scope = -1;
 66         int netif_scope = -1;
 67         if (netif != null) {
 68             /*
 69              * Let's make sure we bind to an address of the proper family.
 70              * Which means same family as addr because at this point it could
 71              * be either an IPv6 address or an IPv4 address (case of a dual
 72              * stack system).
 73              */
 74             java.util.Enumeration<InetAddress> it = netif.getInetAddresses();
 75             InetAddress inetaddr;
 76             while (it.hasMoreElements()) {
 77                 inetaddr = it.nextElement();
 78                 if (inetaddr.getClass().isInstance(addr)) {
 79                     ifaddr = inetaddr.getAddress();
 80                     if (inetaddr instanceof Inet6Address) {
 81                         netif_scope = ((Inet6Address) inetaddr).getScopeId();
 82                     }
 83                     break;
 84                 }
 85             }
 86             if (ifaddr == null) {
 87                 // Interface doesn't support the address family of
 88                 // the destination
 89                 return false;
 90             }
 91         }
 92         if (addr instanceof Inet6Address)
 93             scope = ((Inet6Address) addr).getScopeId();
 94         return isReachable0(addr.getAddress(), scope, timeout, ifaddr, ttl, netif_scope);
 95     }
 96 
 97     public synchronized InetAddress anyLocalAddress() {
 98         if (anyLocalAddress == null) {
 99             if (InetAddress.preferIPv6Address == PREFER_IPV6_VALUE ||
100                 InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE) {
101                 anyLocalAddress = new Inet6Address();
102                 anyLocalAddress.holder().hostName = "::";
103             } else {
104                 anyLocalAddress = (new Inet4AddressImpl()).anyLocalAddress();
105             }
106         }
107         return anyLocalAddress;
108     }
109 
110     public synchronized InetAddress loopbackAddress() {
111         if (loopbackAddress == null) {
112             boolean preferIPv6Address =
113                 InetAddress.preferIPv6Address == PREFER_IPV6_VALUE ||
114                 InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE;
115 
116             for (int i = 0; i < 2; i++) {
117                 InetAddress address;
118                 // Order the candidate addresses by preference.
119                 if (i == (preferIPv6Address ? 0 : 1)) {
120                     address = new Inet6Address("localhost",
121                             new byte[]{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01});
123                 } else {
124                     address = new Inet4Address("localhost", new byte[]{ 0x7f,0x00,0x00,0x01 });
125                 }
126                 if (i == 0) {
127                     // In case of failure, default to the preferred address.
128                     loopbackAddress = address;
129                 }
130                 try {
131                     if (!NetworkInterface.isBoundInetAddress(address)) {
132                         continue;
133                     }
134                 } catch (SocketException e) {
135                     continue;
136                 }
137                 loopbackAddress = address;
138                 break;
139             }
140         }
141         return loopbackAddress;
142     }
143 
144     private InetAddress anyLocalAddress;
145     private InetAddress loopbackAddress;
146 }