[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
* 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@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);