[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
This commit is contained in:
Stanislav Motylkov 2022-06-28 23:36:30 +03:00
parent 35a816a24e
commit 846c9aa1fd
No known key found for this signature in database
GPG key ID: AFE513258CBA9E92

View file

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