WinAPI - Why does ICMPSendEcho2Ex report false timeouts when Timeout is set below 1000ms?

Edit: I started asking this as a PowerShell / .Net question and couldn't find a link to it online. With feedback, it looks like it's a WINAPI issue, so it's edit / rewrite / redo, but most of the tests and .Net reference link for this reason.

Summary

The WINAPI ping function IcmpSendEcho2

seems to have a sync error if the ping timeout parameter is set below 1000ms (1 second). This causes it to return intermittent false timeout errors. Instead of the proportional "lower timeout = more failures" behavior, this appears to be disabling expected behavior> = 1000ms +, <= 999ms causes spurious timeouts, often in an alternating success / failure / success / failure pattern.

I call them bogus timeouts because I have a WireShark packet capture showing a response packet bouncing back during the timeout, and in part because a 1ms change shouldn't be a significant time, where responses usually have 500-800ms headroom, and partly because I can run two parallel sets of pings with different timeouts and see different behavior between them.

In the comments of my original .Net question, @wOxxOm has:

and @Lieven Keersmaekers researched and found things beyond my skill level to interpret:

  • "I can repeat that this is a basic WINAPI problem. After successful execution and requesting a timeout in IPHLPAPI!IcmpSendEcho2Ex

    : the parameter 000003e7

    is on the stack, both set the event and return in IPHLPAPI!IcmpEchoRequestComplete

    with a difference in the eax success register containing 00000000

    , and the eax timeout register containing 00000102

    ( WAIT_TIMEOUT)

  • "Compiling 64-bit version of C #, no more calls to IPHLPAPI

    . Sequential thing that is displayed clr.dll GetLastError()

    returns WSA_QOS_ADMISSION_FAILURE

    for timeouts. Also in my example there is a sequential order of execution of threads between success and timeout, slightly different."

    • This StackOverflow question indicates what WSA_QOS_ADMISSION_FAILURE

      could be a bug and in fact IP_REQ_TIMED_OUT

      .

Testing steps:

Select a remote host and set continuous pings. (The IP address in my examples is from Baidu.cn (China) and has ping responses of around ~ 310ms for me). The expected behavior for all of them is almost entirely ping responses, with occasional drops due to network conditions.

PowerShell / .Net , with 999ms timeout, actual result is fancy response / drop / response / drop templates, much more than expected:

$Pinger = New-Object -TypeName System.Net.NetworkInformation.Ping
while($true) { 
    $Pinger.Send('111.13.101.208', 999)
    start-sleep -Seconds 1
}

      

ping.exe command line with 999ms timeout, actual result is more reliable (edit: but later results also find this in the question):

ping 111.13.101.208 -t -w 999

      

PowerShell / .Net , with 1000ms timeout, the actual result will be as expected:

$Pinger = New-Object -TypeName System.Net.NetworkInformation.Ping
while($true) { 
    $Pinger.Send('111.13.101.208', 1000)
    start-sleep -Seconds 1
}

      

It repeats from C # too, but now I edited this code, it looks like it is a WinAPI issue.

Example screenshot of them walking side by side

  • Left, .Net with 999ms timeout and 50% failure.
  • Center, command line, almost all answers.
  • Right, .Net with 1000ms timeout, almost all answers.

Comparison of ping command line and two PowerShell messages


Previous Research / Background

I started with a 500ms timeout and the number of fake responses seems to vary depending on the ping response time of the remote host:

  • pinging something 30ms away TimedOut reports about 1 in 10 peaks
  • pinging something 100ms timedOut reports around 1 to 4 ping
  • pinging something 300ms from TimedOut reports about 1 to 2 ping

From the same computer, on the same internet connection, sends the same amount of data (32-byte buffer) with the same 500ms timeout, without using any other large bandwidth. I don't run antivirus network filter outside of Windows 10 by default, two other people I know have confirmed this frequent TimedOut actions on their computers (now two more in the comments), with more or less timeouts, so it shouldn't be my network card or drivers or ISP.

Capture WireShark packet for ping response that is falsely reported as timeout

I pinged manually four times up to 100ms of the host with a 500ms timeout while WireShark was capturing network traffic. PowerShell screenshot:

Ping from PowerShell - 4 sent, 3 replies

Screenshot of WireShark:

WireShark message log of messages showing 4 sent, 4 replies

Note that WireShark logs 4 requests, 4 responses are returned, each with a time difference of about 0.11s (110ms) - all within a timeout, but PowerShell incorrectly reports the latter as a timeout.

Related questions

Googling shows me a bunch of problems with System.Net.NetworkInformation.Ping

but none of them looks the same, like

The documentation for Ping () warns about success with a low timeout, but I don't see it warns that the timeout can erroneously report a failure if set below 1 second.

Edit: Now when I search for ICMPSendEcho2, I found exactly this problem described earlier in a blog post in May 2015 here: https://www.frameflow.com/ping-utility-flaw-in-windows-api-creating-false -timeouts / - search for the same behavior, but no more detailed explanation. They say it ping.exe

does, when I originally thought it wasn't. They also say:

  • "In our tests, we were unable to reproduce it on Windows Server 2003 R2 or Windows Server 2008 R2, but it was consistently viewed on Windows Server 2012 R2 and the latest builds of Windows 10."

Why? What is wrong with the timeout handling that causes it to ignore ping reps entering the network stack entirely? Why is 1000ms a significant reduction?

+3


source to share





All Articles