Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any way to change the behavior of synchronous Windows API SendARP?

I'm writing a local network scanner on Windows to find online hosts with IP Helper Functions, which is equivalent to nmap -PR but without WinPcap. I know SendARP will block and send ARP request 3 times if the remote host doesn't respond, so I use std::async to create one threads for each host, but the problem is I want to send an ARP request every 20ms so it would not be too much ARP packets in a very short time.

#include <iostream>
#include <future>
#include <vector>

#include <winsock2.h>
#include <iphlpapi.h>


#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")

using namespace std;

int main(int argc, char **argv)
{
    ULONG MacAddr[2];       /* for 6-byte hardware addresses */
    ULONG PhysAddrLen = 6;  /* default to length of six bytes */
    memset(&MacAddr, 0xff, sizeof (MacAddr));
    PhysAddrLen = 6;

    IPAddr SrcIp = 0;
    IPAddr DestIp = 0;

    char buf[64] = {0};

    size_t start = time(NULL);

    std::vector<std::future<DWORD> > vResults;

    for (auto i = 1; i< 255; i++)
    {
        sprintf(buf, "192.168.1.%d", i);
        DestIp = inet_addr(buf);
        vResults.push_back(std::async(std::launch::async, std::ref(SendARP), DestIp, SrcIp, MacAddr, &PhysAddrLen));
        Sleep(20);
    }

    for (auto it= vResults.begin(); it != vResults.end(); ++it)
    {
        if (it->get() == NO_ERROR)
        {
            std::cout<<"host up\n";
        } 
    }

    std::cout<<"time elapsed "<<(time(NULL) - start)<<std::endl;

    return 0;
}

At first I can do this by calling Sleep(20) after launching a thread, but once SendARP in these threads re-send ARP requests if no replies from remote host, it's out of my control, and I see many requests in a very short time(<10ms) in Wireshark, so my question is:

  1. Any way to make SendARP asynchronous?
  2. if not, can I control the sent timing of SendARP in threads?
like image 548
jfly Avatar asked Sep 04 '25 02:09

jfly


1 Answers

There doesn't seem to be any way to force SendARP to act in a non-blocking manner, it would appear that when a host is unreachable, it will try to re-query several times before giving up.

As for the solution, nothing you want to hear. the MSDN Docs state that there's a newer API that deprecates SendARP called ResolveIpNetEntry2 that can also do the same thing, but it also appears to behave in the same manner.

The struct it receives contains a field called ReachabilityTime.LastUnreachable which is: The time, in milliseconds, that a node assumes a neighbor is unreachable after not having received a reachability confirmation.

However, it does not appear to have any real effect.

The best way to do it, is to use WinPCap or some other driver, there doesn't seem to be a way of solving your problem in userland.

like image 148
A. Smoliak Avatar answered Sep 06 '25 16:09

A. Smoliak