https://git.reactos.org/?p=reactos.git;a=commitdiff;h=846c9aa1fda75e928745f…
commit 846c9aa1fda75e928745f22fac6072d0b924f5ec
Author: Stanislav Motylkov <x86corez(a)gmail.com>
AuthorDate: Tue Jun 28 23:36:30 2022 +0300
Commit: Stanislav Motylkov <x86corez(a)gmail.com>
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 <gedmurphy(a)reactos.org>
- *
*/
#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);