The streamlined way to do this is raw sockets. You only need one, and you can just craft all of the ICMP requests and send them continuously. Then in a separate thread you can read all the replies.
C Programming Language
Welcome to the C community!
C is quirky, flawed, and an enormous success.
... When I read commentary about suggestions for where C should go, I often think back and give thanks that it wasn't developed under the advice of a worldwide crowd.
... The only way to learn a new programming language is by writing programs in it.
- irc: #c
🌐 https://en.cppreference.com/w/c
Is there any reason why it has to be a raw socket, rather than a dgram icmp socket? (which allows you to run as non-root) Silly me for not realizing I only needed one socket. Ofc my speed would only be at most 1-2Mbps. I currently track outgoing pings in memory so I would probably need to keep a single large circular array instead for timeout purposes -- not too different from what I'm doing currently.
Dgram would work, I didn't think of that. When you have a hammer... Raw does let you do other scan methods (syn scan, open port scan, etc). Raw may require using bpf filtering.
You should be able to go pretty fast, masscan can scan the entire internet in around 5 minutes: https://github.com/robertdavidgraham/masscan
I gave it some further thought and I might be completely misguided to try and max throughput. Datagrams are completely connectionless and therefore can’t know if your router’s send buffer is full or not, unless I’m missing something internal between the kernel and the router that makes sendto block (which AFAIK only happens when the socket’s send buffer is full). Therefore most “extra” datagrams I send would just be dropped anyways. I know ICMP was a dated method of congestion control but have no idea if it would still be in use for simple pings.
Edit: apparently source quench is a thing but still, no clue if the kernel intercepts this or if it is even sent in 2026 due to deprecation
Going too hard with your scan may upset your ISP as well, even if you don't lose packets along the way.
Been a while since I've done this kind of thing, but you should be able to create a pool of sockets primed with the first batch of IP addresses, then send the packets.
On reply or timeout you then alter the connection information in the socket descriptor for that socket to point to the next address to check, and then go again.