7163874: InetAddress.isReachable should support pinging 0.0.0.0
authoryoudwei
Fri, 11 May 2012 16:20:46 +0800
changeset 12688 f15fd32c975e
parent 12687 3e67c9656fe5
child 12689 35cbede4f958
7163874: InetAddress.isReachable should support pinging 0.0.0.0 Reviewed-by: alanb, chegar
jdk/src/share/native/java/net/net_util.h
jdk/src/solaris/native/java/net/Inet4AddressImpl.c
jdk/src/solaris/native/java/net/Inet6AddressImpl.c
jdk/src/solaris/native/java/net/net_util_md.c
jdk/test/java/net/Inet4Address/PingThis.java
--- a/jdk/src/share/native/java/net/net_util.h	Thu May 10 11:19:22 2012 -0700
+++ b/jdk/src/share/native/java/net/net_util.h	Fri May 11 16:20:46 2012 +0800
@@ -139,6 +139,9 @@
 int
 NET_IsEqual(jbyte* caddr1, jbyte* caddr2);
 
+int
+NET_IsZeroAddr(jbyte* caddr);
+
 /* Socket operations
  *
  * These work just like the JVM_* procedures, except that they may do some
--- a/jdk/src/solaris/native/java/net/Inet4AddressImpl.c	Thu May 10 11:19:22 2012 -0700
+++ b/jdk/src/solaris/native/java/net/Inet4AddressImpl.c	Fri May 11 16:20:46 2012 +0800
@@ -671,12 +671,19 @@
            * We did receive something, but is it what we were expecting?
            * I.E.: A ICMP_ECHOREPLY packet with the proper PID.
            */
-          if (icmplen >= 8 && icmp->icmp_type == ICMP_ECHOREPLY &&
-               (ntohs(icmp->icmp_id) == pid) &&
-               (him->sin_addr.s_addr == sa_recv.sin_addr.s_addr)) {
-            close(fd);
-            return JNI_TRUE;
-          }
+          if (icmplen >= 8 && icmp->icmp_type == ICMP_ECHOREPLY
+               && (ntohs(icmp->icmp_id) == pid)) {
+            if ((him->sin_addr.s_addr == sa_recv.sin_addr.s_addr)) {
+              close(fd);
+              return JNI_TRUE;
+            }
+
+            if (him->sin_addr.s_addr == 0) {
+              close(fd);
+              return JNI_TRUE;
+            }
+         }
+
         }
       } while (tmout2 > 0);
       timeout -= 1000;
--- a/jdk/src/solaris/native/java/net/Inet6AddressImpl.c	Thu May 10 11:19:22 2012 -0700
+++ b/jdk/src/solaris/native/java/net/Inet6AddressImpl.c	Fri May 11 16:20:46 2012 +0800
@@ -532,10 +532,15 @@
            *       from the host that we are trying to determine is reachable.
            */
           if (n >= 8 && icmp6->icmp6_type == ICMP6_ECHO_REPLY &&
-              (ntohs(icmp6->icmp6_id) == pid) &&
-              NET_IsEqual(caddr, recv_caddr)) {
-            close(fd);
-            return JNI_TRUE;
+              (ntohs(icmp6->icmp6_id) == pid)) {
+            if (NET_IsEqual(caddr, recv_caddr)) {
+              close(fd);
+              return JNI_TRUE;
+            }
+            if (NET_IsZeroAddr(caddr)) {
+              close(fd);
+              return JNI_TRUE;
+            }
           }
         }
       } while (tmout2 > 0);
--- a/jdk/src/solaris/native/java/net/net_util_md.c	Thu May 10 11:19:22 2012 -0700
+++ b/jdk/src/solaris/native/java/net/net_util_md.c	Fri May 11 16:20:46 2012 +0800
@@ -961,6 +961,16 @@
     return 1;
 }
 
+int NET_IsZeroAddr(jbyte* caddr) {
+    int i;
+    for (i = 0; i < 16; i++) {
+        if (caddr[i] != 0) {
+            return 0;
+        }
+    }
+    return 1;
+}
+
 /*
  * Map the Java level socket option to the platform specific
  * level and option name.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/Inet4Address/PingThis.java	Fri May 11 16:20:46 2012 +0800
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Portions Copyright (c) 2012 IBM Corporation
+ */
+
+/* @test
+ * @bug 7163874
+ * @summary InetAddress.isReachable is returning false
+ *          for InetAdress 0.0.0.0 and ::0
+ * @run main PingThis
+ * @run main/othervm -Djava.net.preferIPv4Stack=true PingThis
+ */
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+public class PingThis {
+    private static boolean hasIPv6() throws Exception {
+        List<NetworkInterface> nics = Collections.list(NetworkInterface
+                .getNetworkInterfaces());
+        for (NetworkInterface nic : nics) {
+            List<InetAddress> addrs = Collections.list(nic.getInetAddresses());
+            for (InetAddress addr : addrs) {
+                if (addr instanceof Inet6Address)
+                    return true;
+            }
+        }
+
+        return false;
+    }
+
+    public static void main(String args[]) throws Exception {
+        if (System.getProperty("os.name").startsWith("Windows")) {
+            return;
+        }
+
+        boolean preferIPv4Stack = "true".equals(System
+                .getProperty("java.net.preferIPv4Stack"));
+        List<String> addrs = new ArrayList<String>();
+        InetAddress inetAddress = null;
+
+        addrs.add("0.0.0.0");
+        if (!preferIPv4Stack) {
+            if (hasIPv6()) {
+                addrs.add("::0");
+            }
+        }
+
+        for (String addr : addrs) {
+            inetAddress = InetAddress.getByName(addr);
+            System.out.println("The target ip is "
+                    + inetAddress.getHostAddress());
+            boolean isReachable = inetAddress.isReachable(3000);
+            System.out.println("the target is reachable: " + isReachable);
+            if (isReachable) {
+                System.out.println("Test passed ");
+            } else {
+                System.out.println("Test failed ");
+                throw new Exception("address " + inetAddress.getHostAddress()
+                        + " can not be reachable!");
+            }
+        }
+    }
+}