[IPHLPAPI] Fix IcmpSendEcho output when host is not reachable
authorStanislav Motylkov <x86corez@gmail.com>
Tue, 23 Jan 2018 21:28:55 +0000 (00:28 +0300)
committerGed Murphy <gedmurphy@reactos.org>
Wed, 31 Jan 2018 17:28:21 +0000 (17:28 +0000)
- Add missing error code to DDK/NDIS
- Fix error code in IP driver
- Patch MSAFD to reply correct WSA error code
- Fix IcmpSendEcho function
  - Fix returning error code in ICMP_ECHO_REPLY (see MSDN)
  - Fix returning host address (using GetBestInterface and GetIpAddrTable functions)
- Fix GetBestRoute function (it is used by GetBestInterface)

Relates to #318 and CORE-14241

dll/win32/iphlpapi/icmp.c
dll/win32/iphlpapi/iphlpapi_main.c
dll/win32/msafd/misc/dllmain.c
sdk/include/ddk/ndis.h
sdk/lib/drivers/ip/network/neighbor.c

index ab0245a..95fbe1b 100644 (file)
@@ -496,6 +496,40 @@ static DWORD system_icmp(
 }
 #endif
 
+BOOL
+GetIPv4ByIndex(
+    _In_  DWORD              Index,
+    _Out_ IPAddr *           Address
+)
+{
+    PMIB_IPADDRTABLE pIpAddrTable;
+    ULONG dwSize = 0;
+    BOOL result = FALSE;
+
+    if (GetIpAddrTable(NULL, &dwSize, FALSE) != ERROR_INSUFFICIENT_BUFFER)
+    {
+        return result;
+    }
+    pIpAddrTable = HeapAlloc(GetProcessHeap(), 0, dwSize);
+
+    if (GetIpAddrTable(pIpAddrTable, &dwSize, FALSE) == NO_ERROR)
+    {
+        INT i;
+
+        for (i = 0; i < (*pIpAddrTable).dwNumEntries; i++)
+        {
+            if ((*pIpAddrTable).table[i].dwIndex == Index)
+            {
+                *Address = (IPAddr)(*pIpAddrTable).table[i].dwAddr;
+                result = TRUE;
+                break;
+            }
+        }
+    }
+    HeapFree(GetProcessHeap(), 0, pIpAddrTable);
+    return result;
+}
+
 /***********************************************************************
  *             IcmpSendEcho (IPHLPAPI.@)
  */
@@ -671,22 +705,34 @@ DWORD WINAPI IcmpSendEcho(
     res=sendto(icp->sid, (const char*)reqbuf, reqsize, 0, (struct sockaddr*)&addr, sizeof(addr));
     HeapFree(GetProcessHeap (), 0, reqbuf);
     if (res<0) {
+        DWORD dwBestIfIndex;
+        IPAddr IP4Addr;
+
+        ZeroMemory(&ier->Address, sizeof(ier->Address));
+
+        if (GetBestInterface(addr.sin_addr.s_addr, &dwBestIfIndex) == NO_ERROR &&
+            GetIPv4ByIndex(dwBestIfIndex, &IP4Addr))
+        {
+            memcpy(&ier->Address, &IP4Addr, sizeof(IP4Addr));
+        }
+
         if (WSAGetLastError()==WSAEMSGSIZE)
-            SetLastError(IP_PACKET_TOO_BIG);
+            ier->Status = IP_PACKET_TOO_BIG;
         else {
             switch (WSAGetLastError()) {
             case WSAENETUNREACH:
-                SetLastError(IP_DEST_NET_UNREACHABLE);
+                ier->Status = IP_DEST_NET_UNREACHABLE;
                 break;
             case WSAEHOSTUNREACH:
-                SetLastError(IP_DEST_HOST_UNREACHABLE);
+                ier->Status = IP_DEST_HOST_UNREACHABLE;
                 break;
             default:
                 TRACE("unknown error: errno=%d\n",WSAGetLastError());
-                SetLastError(IP_GENERAL_FAILURE);
+                ier->Status = IP_GENERAL_FAILURE;
+                ZeroMemory(&ier->Address, sizeof(ier->Address));
             }
         }
-        return 0;
+        return 1;
     }
 
     /* Get the reply */
@@ -848,7 +894,10 @@ DWORD WINAPI IcmpSendEcho(
     HeapFree(GetProcessHeap(), 0, ip_header);
     res=ier-(ICMP_ECHO_REPLY*)ReplyBuffer;
     if (res==0)
+    {
+        ier->Status = IP_REQ_TIMED_OUT;
         SetLastError(IP_REQ_TIMED_OUT);
+    }
     TRACE("received %d replies\n",res);
     return res;
 }
index af8cbd1..c06796f 100644 (file)
@@ -767,18 +767,19 @@ DWORD WINAPI GetBestRoute(DWORD dwDestAddr, DWORD dwSourceAddr, PMIB_IPFORWARDRO
 
   AllocateAndGetIpForwardTableFromStack(&table, FALSE, GetProcessHeap(), 0);
   if (table) {
-    DWORD ndx, matchedBits, matchedNdx = 0;
+    DWORD ndx, minMaskSize, matchedNdx = 0;
 
-    for (ndx = 0, matchedBits = 0; ndx < table->dwNumEntries; ndx++) {
+    for (ndx = 0, minMaskSize = 255; ndx < table->dwNumEntries; ndx++) {
       if ((dwDestAddr & table->table[ndx].dwForwardMask) ==
        (table->table[ndx].dwForwardDest & table->table[ndx].dwForwardMask)) {
-        DWORD numShifts, mask;
+        DWORD hostMaskSize;
 
-        for (numShifts = 0, mask = table->table[ndx].dwForwardMask;
-         mask && !(mask & 1); mask >>= 1, numShifts++)
-          ;
-        if (numShifts > matchedBits) {
-          matchedBits = numShifts;
+        if (!_BitScanForward(&hostMaskSize, ntohl(table->table[ndx].dwForwardMask)))
+        {
+            hostMaskSize = 32;
+        }
+        if (hostMaskSize < minMaskSize) {
+          minMaskSize = hostMaskSize;
           matchedNdx = ndx;
         }
       }
index c0de49b..f6e04ae 100644 (file)
@@ -579,6 +579,9 @@ TranslateNtStatusError(NTSTATUS Status)
        case STATUS_NETWORK_UNREACHABLE:
           return WSAENETUNREACH;
 
+       case STATUS_HOST_UNREACHABLE:
+          return WSAEHOSTUNREACH;
+
        case STATUS_INVALID_PARAMETER:
           return WSAEINVAL;
 
index fef3b2e..028dd1f 100644 (file)
@@ -509,6 +509,7 @@ typedef MDL NDIS_BUFFER, *PNDIS_BUFFER;
 #define NDIS_STATUS_TOKEN_RING_OPEN_ERROR       ((NDIS_STATUS)0xC0011000L)
 #define NDIS_STATUS_INVALID_DEVICE_REQUEST      ((NDIS_STATUS)STATUS_INVALID_DEVICE_REQUEST)
 #define NDIS_STATUS_NETWORK_UNREACHABLE         ((NDIS_STATUS)STATUS_NETWORK_UNREACHABLE)
+#define NDIS_STATUS_HOST_UNREACHABLE            ((NDIS_STATUS)STATUS_HOST_UNREACHABLE)
 
 #if NDIS_SUPPORT_NDIS6
 
index a7c1d35..7477a8f 100644 (file)
@@ -144,7 +144,7 @@ VOID NBTimeout(VOID)
                     if (NCE->State & NUD_INCOMPLETE)
                     {
                         /* We couldn't get an address to this IP at all */
-                        Status = NDIS_STATUS_NETWORK_UNREACHABLE;
+                        Status = NDIS_STATUS_HOST_UNREACHABLE;
                     }
                     else
                     {