nmap / npcap

Nmap Project's Windows packet capture and transmission library
https://npcap.com
Other
2.97k stars 514 forks source link

Create API calls for non-blocking packet writes #747

Open fyodor opened 1 month ago

fyodor commented 1 month ago

Npcap offers ways to read packets asynchronously, but packet writes are always blocking. We basically use the Windows version of the UNIX write() syscall. This is because we wait around to ensure the write was successful and return the appropriate error code if not. This usually doesn't take very long, but we did have one Npcap OEM redistribution license customer recently report that it could take up to 3ms and that caused problems for their real-time software.

The simplest approach would be to make all packet writes asynchronous, but that would be problematic for folks who would prefer waiting a millisecond or so to ensure the write was successful. So a better approach would probably be to offer an asynchronous option for those who want it.

We looked at how the (now obsolete) Winpcap system handled it. The system call to give the packet to the driver was synchronous, but the driver called an asynchronous NDIS function and returned immediately. It would give the illusion of being fire-and-forget. You get errors if you did something dumb with the packet structure as defined in Packet.dll API, but you don't get to find out if Windows actually sent your packet. Also the driver also did a wait for an event that the NDIS callback would set, so still it was effectively a blocking call.

Npcap has changed that: the write handler is asynchronous and indicates that to Windows by returning STATUS_PENDING. Then Windows does the work of waiting. That means the way is clear for Packet.dll to use Windows-provided synchronization routines like WriteFileEx and LPOVERLAPPED struct to do the work.

We would want to coordinate with the libpcap team--probably open an issue on their tracker to discuss how they prefer to handle asynchronous calls like this. That way we may be able to get a standardized and cross-platform solution.

dmiller-nmap commented 1 month ago

Some thoughts and notes from my research:

guyharris commented 1 month ago

and Linux could treat it as struct aiocb *

s;Linux;platforms supporting the POSIX asynchronous I/O interface;

Although that requires that the platform's mechanism for transmitting packets also support that interface. (But details such as that probably belong on the libpcap issues list.)