8135305: InetAddress.isReachable reports true when loopback interface is specified
authorrobm
Thu, 01 Oct 2015 00:09:51 +0100
changeset 32845 e630c3008f2c
parent 32844 1861a8cd73ba
child 32846 5383225ebd0d
8135305: InetAddress.isReachable reports true when loopback interface is specified Reviewed-by: michaelm
jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c
jdk/test/java/net/InetAddress/IsReachableViaLoopbackTest.java
--- a/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c	Wed Sep 30 15:25:29 2015 -0700
+++ b/jdk/src/java.base/windows/native/libnet/Inet4AddressImpl.c	Thu Oct 01 00:09:51 2015 +0100
@@ -283,8 +283,11 @@
  * Returns true is an ECHO_REPLY is received, otherwise, false.
  */
 static jboolean
-ping4(JNIEnv *env, unsigned long ipaddr, jint timeout) {
-
+ping4(JNIEnv *env,
+      unsigned long src_addr,
+      unsigned long dest_addr,
+      jint timeout)
+{
     // See https://msdn.microsoft.com/en-us/library/aa366050%28VS.85%29.aspx
 
     HANDLE hIcmpFile;
@@ -307,14 +310,29 @@
         return JNI_FALSE;
     }
 
-    dwRetVal = IcmpSendEcho(hIcmpFile,  // HANDLE IcmpHandle,
-                            ipaddr,     // IPAddr DestinationAddress,
-                            SendData,   // LPVOID RequestData,
-                            sizeof(SendData),   // WORD RequestSize,
-                            NULL,       // PIP_OPTION_INFORMATION RequestOptions,
-                            ReplyBuffer,// LPVOID ReplyBuffer,
-                            ReplySize,  // DWORD ReplySize,
-                            timeout);   // DWORD Timeout
+    if (src_addr == 0) {
+        dwRetVal = IcmpSendEcho(hIcmpFile,  // HANDLE IcmpHandle,
+                                dest_addr,  // IPAddr DestinationAddress,
+                                SendData,   // LPVOID RequestData,
+                                sizeof(SendData),   // WORD RequestSize,
+                                NULL,       // PIP_OPTION_INFORMATION RequestOptions,
+                                ReplyBuffer,// LPVOID ReplyBuffer,
+                                ReplySize,  // DWORD ReplySize,
+                                timeout);   // DWORD Timeout
+    } else {
+        dwRetVal = IcmpSendEcho2Ex(hIcmpFile,  // HANDLE IcmpHandle,
+                                   NULL,       // HANDLE Event
+                                   NULL,       // PIO_APC_ROUTINE ApcRoutine
+                                   NULL,       // ApcContext
+                                   src_addr,   // IPAddr SourceAddress,
+                                   dest_addr,  // IPAddr DestinationAddress,
+                                   SendData,   // LPVOID RequestData,
+                                   sizeof(SendData),   // WORD RequestSize,
+                                   NULL,       // PIP_OPTION_INFORMATION RequestOptions,
+                                   ReplyBuffer,// LPVOID ReplyBuffer,
+                                   ReplySize,  // DWORD ReplySize,
+                                   timeout);   // DWORD Timeout
+    }
 
     free(ReplyBuffer);
     IcmpCloseHandle(hIcmpFile);
@@ -337,9 +355,9 @@
                                            jint timeout,
                                            jbyteArray ifArray,
                                            jint ttl) {
-    jint addr;
+    jint src_addr = 0;
+    jint dest_addr = 0;
     jbyte caddr[4];
-    struct sockaddr_in him;
     int sz;
 
     /**
@@ -349,14 +367,28 @@
     if (sz != 4) {
       return JNI_FALSE;
     }
-    memset((char *) &him, 0, sizeof(him));
     memset((char *) caddr, 0, sizeof(caddr));
     (*env)->GetByteArrayRegion(env, addrArray, 0, 4, caddr);
-    addr = ((caddr[0]<<24) & 0xff000000);
-    addr |= ((caddr[1] <<16) & 0xff0000);
-    addr |= ((caddr[2] <<8) & 0xff00);
-    addr |= (caddr[3] & 0xff);
-    addr = htonl(addr);
+    dest_addr = ((caddr[0]<<24) & 0xff000000);
+    dest_addr |= ((caddr[1] <<16) & 0xff0000);
+    dest_addr |= ((caddr[2] <<8) & 0xff00);
+    dest_addr |= (caddr[3] & 0xff);
+    dest_addr = htonl(dest_addr);
 
-    return ping4(env, addr, timeout);
+    /**
+     * If a network interface was specified, let's convert its address
+     * as well.
+     */
+    if (!(IS_NULL(ifArray))) {
+        memset((char *) caddr, 0, sizeof(caddr));
+        (*env)->GetByteArrayRegion(env, ifArray, 0, 4, caddr);
+        src_addr = ((caddr[0]<<24) & 0xff000000);
+        src_addr |= ((caddr[1] <<16) & 0xff0000);
+        src_addr |= ((caddr[2] <<8) & 0xff00);
+        src_addr |= (caddr[3] & 0xff);
+        src_addr = htonl(src_addr);
+    }
+
+    return ping4(env, src_addr, dest_addr, timeout);
 }
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/net/InetAddress/IsReachableViaLoopbackTest.java	Thu Oct 01 00:09:51 2015 +0100
@@ -0,0 +1,40 @@
+import java.io.*;
+import java.net.*;
+import java.util.*;
+
+/**
+ * @test
+ * @bug 8135305
+ * @summary ensure we can't ping external hosts via loopback if
+ */
+
+public class IsReachableViaLoopbackTest {
+    public static void main(String[] args) {
+        try {
+            InetAddress addr = InetAddress.getByName("localhost");
+            InetAddress remoteAddr = InetAddress.getByName("bugs.openjdk.java.net");
+            if (!addr.isReachable(10000))
+                throw new RuntimeException("Localhost should always be reachable");
+            NetworkInterface inf = NetworkInterface.getByInetAddress(addr);
+            if (inf != null) {
+                if (!addr.isReachable(inf, 20, 10000)) {
+                    throw new RuntimeException("Localhost should always be reachable");
+                } else {
+                    System.out.println(addr + "  is reachable");
+                }
+                if (remoteAddr.isReachable(inf, 20, 10000)) {
+                    throw new RuntimeException(remoteAddr + " is reachable");
+                } else {
+                    System.out.println(remoteAddr + "  is NOT reachable");
+                }
+            } else {
+                System.out.println("inf == null");
+            }
+
+        } catch (IOException e) {
+            throw new RuntimeException("Unexpected exception:" + e);
+        }
+        System.out.println("IsReachableViaLoopbackTest EXIT");
+    }
+}
+