From 846c9aa1fda75e928745f22fac6072d0b924f5ec Mon Sep 17 00:00:00 2001 From: Stanislav Motylkov Date: Tue, 28 Jun 2022 23:36:30 +0300 Subject: [PATCH] [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 - * */ #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(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);