1 /*
2  * Copyright (c) 2002, 2016, 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 static java.net.InetAddress.PREFER_IPV6_VALUE;
29 import static java.net.InetAddress.PREFER_SYSTEM_VALUE;
30
31 /*
32  * Package private implementation of InetAddressImpl for dual
33  * IPv4/IPv6 stack.
34  * <p>
35  * If InetAddress.preferIPv6Address is true then anyLocalAddress(),
36  * loopbackAddress(), and localHost() will return IPv6 addresses,
37  * otherwise IPv4 addresses.
38  *
39  * @since 1.4
40  */

41 class Inet6AddressImpl implements InetAddressImpl {
42
43     public native String getLocalHostName() throws UnknownHostException;
44
45     public native InetAddress[] lookupAllHostAddr(String hostname)
46         throws UnknownHostException;
47
48     public native String getHostByAddr(byte[] addr) throws UnknownHostException;
49
50     private native boolean isReachable0(byte[] addr, int scope, int timeout,
51                                         byte[] inf, int ttl, int if_scope)
52         throws IOException;
53
54     public boolean isReachable(InetAddress addr, int timeout,
55                                NetworkInterface netif, int ttl)
56         throws IOException
57     {
58         byte[] ifaddr = null;
59         int scope = -1;
60         int netif_scope = -1;
61         if (netif != null) {
62             /*
63              * Let's make sure we bind to an address of the proper family.
64              * Which means same family as addr because at this point it could
65              * be either an IPv6 address or an IPv4 address (case of a dual
66              * stack system).
67              */

68             java.util.Enumeration<InetAddress> it = netif.getInetAddresses();
69             InetAddress inetaddr = null;
70             while (it.hasMoreElements()) {
71                 inetaddr = it.nextElement();
72                 if (inetaddr.getClass().isInstance(addr)) {
73                     ifaddr = inetaddr.getAddress();
74                     if (inetaddr instanceof Inet6Address) {
75                         netif_scope = ((Inet6Address) inetaddr).getScopeId();
76                     }
77                     break;
78                 }
79             }
80             if (ifaddr == null) {
81                 // Interface doesn't support the address family of
82                 // the destination
83                 return false;
84             }
85         }
86         if (addr instanceof Inet6Address)
87             scope = ((Inet6Address) addr).getScopeId();
88         return isReachable0(addr.getAddress(), scope, timeout, ifaddr, ttl, netif_scope);
89     }
90
91     public synchronized InetAddress anyLocalAddress() {
92         if (anyLocalAddress == null) {
93             if (InetAddress.preferIPv6Address == PREFER_IPV6_VALUE ||
94                 InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE) {
95                 anyLocalAddress = new Inet6Address();
96                 anyLocalAddress.holder().hostName = "::";
97             } else {
98                 anyLocalAddress = (new Inet4AddressImpl()).anyLocalAddress();
99             }
100         }
101         return anyLocalAddress;
102     }
103
104     public synchronized InetAddress loopbackAddress() {
105         if (loopbackAddress == null) {
106              if (InetAddress.preferIPv6Address == PREFER_IPV6_VALUE ||
107                  InetAddress.preferIPv6Address == PREFER_SYSTEM_VALUE) {
108                  byte[] loopback =
109                         {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110                          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
111                  loopbackAddress = new Inet6Address("localhost", loopback);
112              } else {
113                 loopbackAddress = (new Inet4AddressImpl()).loopbackAddress();
114              }
115         }
116         return loopbackAddress;
117     }
118
119     private InetAddress anyLocalAddress;
120     private InetAddress loopbackAddress;
121 }
122