https://git.reactos.org/?p=reactos.git;a=commitdiff;h=63ad8a71c03cddea9e4d3f14243230d01da75087

commit 63ad8a71c03cddea9e4d3f14243230d01da75087
Author:     Stanislav Motylkov <[email protected]>
AuthorDate: Wed Jan 24 00:28:55 2018 +0300
Commit:     Ged Murphy <[email protected]>
CommitDate: Wed Jan 31 17:28:21 2018 +0000

    [IPHLPAPI] Fix IcmpSendEcho output when host is not reachable
    
    - 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             | 59 ++++++++++++++++++++++++++++++++---
 dll/win32/iphlpapi/iphlpapi_main.c    | 17 +++++-----
 dll/win32/msafd/misc/dllmain.c        |  3 ++
 sdk/include/ddk/ndis.h                |  1 +
 sdk/lib/drivers/ip/network/neighbor.c |  2 +-
 5 files changed, 68 insertions(+), 14 deletions(-)

diff --git a/dll/win32/iphlpapi/icmp.c b/dll/win32/iphlpapi/icmp.c
index ab0245a2dc..95fbe1bdca 100644
--- a/dll/win32/iphlpapi/icmp.c
+++ b/dll/win32/iphlpapi/icmp.c
@@ -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;
 }
diff --git a/dll/win32/iphlpapi/iphlpapi_main.c 
b/dll/win32/iphlpapi/iphlpapi_main.c
index af8cbd1805..c06796f6d8 100644
--- a/dll/win32/iphlpapi/iphlpapi_main.c
+++ b/dll/win32/iphlpapi/iphlpapi_main.c
@@ -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;
         }
       }
diff --git a/dll/win32/msafd/misc/dllmain.c b/dll/win32/msafd/misc/dllmain.c
index c0de49ba28..f6e04ae5fc 100644
--- a/dll/win32/msafd/misc/dllmain.c
+++ b/dll/win32/msafd/misc/dllmain.c
@@ -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;
 
diff --git a/sdk/include/ddk/ndis.h b/sdk/include/ddk/ndis.h
index fef3b2e0f9..028dd1f49b 100644
--- a/sdk/include/ddk/ndis.h
+++ b/sdk/include/ddk/ndis.h
@@ -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
 
diff --git a/sdk/lib/drivers/ip/network/neighbor.c 
b/sdk/lib/drivers/ip/network/neighbor.c
index a7c1d35eea..7477a8f9f3 100644
--- a/sdk/lib/drivers/ip/network/neighbor.c
+++ b/sdk/lib/drivers/ip/network/neighbor.c
@@ -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
                     {

Reply via email to