https://git.reactos.org/?p=reactos.git;a=commitdiff;h=846c9aa1fda75e928745f22fac6072d0b924f5ec

commit 846c9aa1fda75e928745f22fac6072d0b924f5ec
Author:     Stanislav Motylkov <[email protected]>
AuthorDate: Tue Jun 28 23:36:30 2022 +0300
Commit:     Stanislav Motylkov <[email protected]>
CommitDate: Tue Jun 28 23:42:09 2022 +0300

    [TRACERT] Fix displaying hop address on last ping timeout
    
    - Update source file header per coding rules
    - Store intermediate responses to display the hop address
    - Add separate function to get response stats from buffer
    - Add Cleanup label to free resources in a single place
    - Move local variables around to allow Cleanup goto
    
    CORE-18232
---
 base/applications/network/tracert/tracert.cpp | 109 +++++++++++++++++++-------
 1 file changed, 82 insertions(+), 27 deletions(-)

diff --git a/base/applications/network/tracert/tracert.cpp 
b/base/applications/network/tracert/tracert.cpp
index 8081a0ada7d..85b4aeb0908 100644
--- a/base/applications/network/tracert/tracert.cpp
+++ b/base/applications/network/tracert/tracert.cpp
@@ -1,10 +1,8 @@
 /*
  * PROJECT:     ReactOS trace route utility
- * LICENSE:     GPL - See COPYING in the top level directory
- * FILE:        base/applications/network/tracert/tracert.cpp
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
  * PURPOSE:     Trace network paths through networks
  * COPYRIGHT:   Copyright 2018 Ged Murphy <[email protected]>
- *
  */
 
 #ifdef __REACTOS__
@@ -275,15 +273,13 @@ PrintHopInfo(_In_ PVOID Buffer)
     return (Status == 0);
 }
 
-static bool
-DecodeResponse(
+static ULONG
+GetResponseStats(
     _In_ PVOID ReplyBuffer,
-    _In_ bool OutputHopAddress,
-    _Out_ bool& FoundTarget
+    _Out_ ULONG& RoundTripTime,
+    _Out_ PVOID& AddressInfo
 )
 {
-    ULONG RoundTripTime;
-    PVOID AddressInfo;
     ULONG Status;
 
     if (Info.Family == AF_INET6)
@@ -308,6 +304,22 @@ DecodeResponse(
         AddressInfo = &EchoReplyV4->Address;
     }
 
+    return Status;
+}
+
+static bool
+DecodeResponse(
+    _In_ PVOID ReplyBuffer,
+    _In_ PVOID LastGoodResponse,
+    _In_ bool OutputHopAddress,
+    _Out_ bool& GoodResponse,
+    _Out_ bool& FoundTarget
+)
+{
+    ULONG RoundTripTime;
+    PVOID AddressInfo;
+    ULONG Status = GetResponseStats(ReplyBuffer, RoundTripTime, AddressInfo);
+
     switch (Status)
     {
     case IP_SUCCESS:
@@ -320,6 +332,7 @@ DecodeResponse(
         {
             OutputText(IDS_HOP_ZERO);
         }
+        GoodResponse = true;
         break;
 
     case IP_DEST_HOST_UNREACHABLE:
@@ -352,6 +365,10 @@ DecodeResponse(
 
     if (OutputHopAddress)
     {
+        if (Status == IP_REQ_TIMED_OUT && LastGoodResponse)
+        {
+            Status = GetResponseStats(LastGoodResponse, RoundTripTime, 
AddressInfo);
+        }
         if (Status == IP_SUCCESS)
         {
             FoundTarget = true;
@@ -374,18 +391,22 @@ static bool
 RunTraceRoute()
 {
     bool Success = false;
+    PVOID ReplyBuffer = NULL, LastGoodResponse = NULL;
+    DWORD ReplySize;
+
+    HANDLE heap = GetProcessHeap();
+    bool Quit = false;
+    ULONG HopCount = 1;
+    bool FoundTarget = false;
+
     Success = ResolveTarget();
     if (!Success)
     {
         OutputText(IDS_UNABLE_RESOLVE, Info.HostName);
-        return false;
+        goto Cleanup;
     }
 
-    BYTE SendBuffer[PACKET_SIZE];
-
-    PVOID ReplyBuffer;
-
-    DWORD ReplySize = PACKET_SIZE + SIZEOF_ICMP_ERROR + SIZEOF_IO_STATUS_BLOCK;
+    ReplySize = PACKET_SIZE + SIZEOF_ICMP_ERROR + SIZEOF_IO_STATUS_BLOCK;
     if (Info.Family == AF_INET6)
     {
         ReplySize += sizeof(ICMPV6_ECHO_REPLY);
@@ -399,12 +420,11 @@ RunTraceRoute()
 #endif
     }
 
-    HANDLE heap = GetProcessHeap();
     ReplyBuffer = HeapAlloc(heap, HEAP_ZERO_MEMORY, ReplySize);
     if (ReplyBuffer == NULL)
     {
-        FreeAddrInfoW(Info.Target);
-        return false;
+        Success = false;
+        goto Cleanup;
     }
 
     if (Info.Family == AF_INET6)
@@ -417,9 +437,8 @@ RunTraceRoute()
     }
     if (Info.hIcmpFile == INVALID_HANDLE_VALUE)
     {
-        HeapFree(heap, 0, ReplyBuffer);
-        FreeAddrInfoW(Info.Target);
-        return false;
+        Success = false;
+        goto Cleanup;
     }
 
     OutputText(IDS_TRACE_INFO, Info.HostName, Info.TargetIP, Info.MaxHops);
@@ -427,15 +446,21 @@ RunTraceRoute()
     IP_OPTION_INFORMATION IpOptionInfo;
     ZeroMemory(&IpOptionInfo, sizeof(IpOptionInfo));
 
-    bool Quit = false;
-    ULONG HopCount = 1;
-    bool FoundTarget = false;
     while ((HopCount <= Info.MaxHops) && (FoundTarget == false) && (Quit == 
false))
     {
         OutputText(IDS_HOP_COUNT, HopCount);
 
+        if (LastGoodResponse)
+        {
+            HeapFree(heap, 0, LastGoodResponse);
+            LastGoodResponse = NULL;
+        }
+
         for (int Ping = 1; Ping <= NUM_OF_PINGS; Ping++)
         {
+            BYTE SendBuffer[PACKET_SIZE];
+            bool GoodResponse = false;
+
             IpOptionInfo.Ttl = static_cast<UCHAR>(HopCount);
 
             if (Info.Family == AF_INET6)
@@ -473,7 +498,11 @@ RunTraceRoute()
                                      Info.Timeout);
             }
 
-            if (DecodeResponse(ReplyBuffer, (Ping == NUM_OF_PINGS), 
FoundTarget) == false)
+            if (DecodeResponse(ReplyBuffer,
+                               LastGoodResponse,
+                               (Ping == NUM_OF_PINGS),
+                               GoodResponse,
+                               FoundTarget) == false)
             {
                 Quit = true;
                 break;
@@ -484,6 +513,21 @@ RunTraceRoute()
                 Success = true;
                 break;
             }
+
+            if (GoodResponse)
+            {
+                if (LastGoodResponse)
+                {
+                    HeapFree(heap, 0, LastGoodResponse);
+                }
+                LastGoodResponse = HeapAlloc(heap, HEAP_ZERO_MEMORY, 
ReplySize);
+                if (LastGoodResponse == NULL)
+                {
+                    Success = false;
+                    goto Cleanup;
+                }
+                CopyMemory(LastGoodResponse, ReplyBuffer, ReplySize);
+            }
         }
 
         HopCount++;
@@ -492,8 +536,19 @@ RunTraceRoute()
 
     OutputText(IDS_TRACE_COMPLETE);
 
-    HeapFree(heap, 0, ReplyBuffer);
-    FreeAddrInfoW(Info.Target);
+Cleanup:
+    if (ReplyBuffer)
+    {
+        HeapFree(heap, 0, ReplyBuffer);
+    }
+    if (LastGoodResponse)
+    {
+        HeapFree(heap, 0, LastGoodResponse);
+    }
+    if (Info.Target)
+    {
+        FreeAddrInfoW(Info.Target);
+    }
     if (Info.hIcmpFile)
     {
         IcmpCloseHandle(Info.hIcmpFile);

Reply via email to