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 import java.net.spi.InetAddressResolver.LookupPolicy;
 29 
 30 import static java.net.InetAddress.PLATFORM_LOOKUP_POLICY;


 31 
 32 /*
 33  * Package private implementation of InetAddressImpl for dual
 34  * IPv4/IPv6 stack.
 35  * <p>
 36  * If InetAddress.preferIPv6Address is true then anyLocalAddress()
 37  * and localHost() will return IPv6 addresses, otherwise IPv4 addresses.
 38  *
 39  * loopbackAddress() will return the first valid loopback address in
 40  * [IPv6 loopback, IPv4 loopback] if InetAddress.preferIPv6Address is true,
 41  * else [IPv4 loopback, IPv6 loopback].
 42  * If neither are valid it will fallback to the first address tried.
 43  *
 44  * @since 1.4
 45  */
 46 final class Inet6AddressImpl implements InetAddressImpl {
 47 
 48     public native String getLocalHostName() throws UnknownHostException;
 49 
 50     public InetAddress[] lookupAllHostAddr(String hostname, LookupPolicy lookupPolicy)
 51             throws UnknownHostException {
 52         return lookupAllHostAddr(hostname, lookupPolicy.characteristics());
 53     }
 54 
 55     private native InetAddress[] lookupAllHostAddr(String hostname, int characteristics)
 56             throws UnknownHostException;
 57 
 58     public native String getHostByAddr(byte[] addr) throws UnknownHostException;
 59 
 60     private native boolean isReachable0(byte[] addr, int scope, int timeout,
 61                                         byte[] inf, int ttl, int if_scope)
 62         throws IOException;
 63 
 64     public boolean isReachable(InetAddress addr, int timeout,
 65                                NetworkInterface netif, int ttl)
 66         throws IOException
 67     {
 68         byte[] ifaddr = null;
 69         int scope = -1;
 70         int netif_scope = -1;
 71         if (netif != null) {
 72             /*
 73              * Let's make sure we bind to an address of the proper family.
 74              * Which means same family as addr because at this point it could
 75              * be either an IPv6 address or an IPv4 address (case of a dual
 76              * stack system).
 77              */
 78             java.util.Enumeration<InetAddress> it = netif.getInetAddresses();
 79             InetAddress inetaddr;
 80             while (it.hasMoreElements()) {
 81                 inetaddr = it.nextElement();
 82                 if (inetaddr.getClass().isInstance(addr)) {
 83                     ifaddr = inetaddr.getAddress();
 84                     if (inetaddr instanceof Inet6Address) {
 85                         netif_scope = ((Inet6Address) inetaddr).getScopeId();
 86                     }
 87                     break;
 88                 }
 89             }
 90             if (ifaddr == null) {
 91                 // Interface doesn't support the address family of
 92                 // the destination
 93                 return false;
 94             }
 95         }
 96         if (addr instanceof Inet6Address)
 97             scope = ((Inet6Address) addr).getScopeId();
 98         return isReachable0(addr.getAddress(), scope, timeout, ifaddr, ttl, netif_scope);
 99     }
100 
101     public synchronized InetAddress anyLocalAddress() {
102         if (anyLocalAddress == null) {
103             int flags = PLATFORM_LOOKUP_POLICY.characteristics();
104             if (InetAddress.ipv6AddressesFirst(flags) ||
105                 InetAddress.systemAddressesOrder(flags)) {
106                 anyLocalAddress = new Inet6Address();
107                 anyLocalAddress.holder().hostName = "::";
108             } else {
109                 anyLocalAddress = (new Inet4AddressImpl()).anyLocalAddress();
110             }
111         }
112         return anyLocalAddress;
113     }
114 
115     public synchronized InetAddress loopbackAddress() {
116         if (loopbackAddress == null) {
117             int flags = PLATFORM_LOOKUP_POLICY.characteristics();
118             boolean preferIPv6Address = InetAddress.ipv6AddressesFirst(flags) ||
119                     InetAddress.systemAddressesOrder(flags);
120 
121             for (int i = 0; i < 2; i++) {
122                 InetAddress address;
123                 // Order the candidate addresses by preference.
124                 if (i == (preferIPv6Address ? 0 : 1)) {
125                     address = new Inet6Address("localhost",
126                             new byte[]{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
127                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01});
128                 } else {
129                     address = new Inet4Address("localhost", new byte[]{ 0x7f,0x00,0x00,0x01 });
130                 }
131                 if (i == 0) {
132                     // In case of failure, default to the preferred address.
133                     loopbackAddress = address;
134                 }
135                 try {
136                     if (!NetworkInterface.isBoundInetAddress(address)) {
137                         continue;
138                     }
139                 } catch (SocketException e) {
140                     continue;
141                 }
142                 loopbackAddress = address;
143                 break;
144             }
145         }
146         return loopbackAddress;
147     }
148 
149     private InetAddress anyLocalAddress;
150     private InetAddress loopbackAddress;
151 }
--- EOF ---