nmap / npcap

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

API: pcap_next_ex did not get all the packets that met the requirements #727

Open DraAngel opened 4 months ago

DraAngel commented 4 months ago

I packed 200,000 packets using pcap_sendqueue_queue with a sequence number field added to the packet. Then I use pcap_sendqueue_transmit to send it to another computer in the local area network. The log message printed shows that there were no abnormalities in the delivery process, and the monitoring results in Wiresshark show that the packets were sent normally. send log: log1 Wireshark: screen

Then I use pcap_next_ex to fetch the packet from the local adapter, filter it according to the ip information it was sent, and print the sequence number information in the packet.However, after sorting through the printed information, I found that the packet sequence number was sometimes lost in the middle or at the end. receive log: log2

The following is part of the sending and receiving code, is there something wrong with my code? send:

for (int i = 0; i < pktSize; ++ i){
    ...//header

     ...//packet

    if (pcap_sendqueue_queue(squeue, pktheader, packet) == -1)
    {
        printf("Warning: packet buffer too small, not all the packets will be sent.\n");
        break;
    }
    npacks++;
}

if ((res = pcap_sendqueue_transmit(outdesc, squeue, sync)) < squeue->len){ printf("An error occurred sending the packets: %s."" Only %d bytes were sent\n", pcap_geterr(outdesc), res); } printf("\nTotal packets generated = %d", npacks);

listenToPcap:

while ((res = pcap_next_ex(adhandle, &header, &pkt_data)) >= 0) {
    if (res == 0)
    {
        ...
        continue;
    }
    if (res == -1) {
        ...
                   return;
    }
    ip_header* ih;
    udp_header* uh;
    u_int srcIndex;
    ih = ...//

    if (xx!= ih->saddr.byte1 || yy != ih->saddr.byte2 ... ...)//The ip filter is the same as in Wireshark
    {
        continue;
    }
    u_int ip_len = (ih->ver_ihl & 0xf) * 4;
    uh = (udp_header*)((u_char*)ih + ip_len);
           //index print
    srcIndex = uh->index;
    printf("%d\n", srcIndex);
    ... ....//data
}
DraAngel commented 4 months ago

npcap version:1.79 npcap-sdk version:1.13

guyharris commented 4 months ago

How many dropped packets does pcap_stats() report in ps_drop?

DraAngel commented 4 months ago

Should I write fetch ps_drop in the timeout branch

guyharris commented 4 months ago

Should I write fetch ps_drop in the timeout branch

Since your capture loop seems not to ever exit, the right place to try it might be to, every N packets, for some value of N, call pcap_stats() and, if ps_drop is non-zero, print its current value as a count of dropped packets.

DraAngel commented 4 months ago

Well. I tried to get ps_drop every 15678 packets, and the results seemed a little hard to understand. The code looks like this:

    srcIndex = uh->index;
    if (srcIndex % 15678 == 0)
    {
        int size;
        pcap_stat* stat = pcap_stats_ex(adhandle, &size);
        printf("drop num: %d\n", stat->ps_drop);
    }
DraAngel commented 4 months ago

The results show that most of the packets are lost. 111

DraAngel commented 4 months ago

I set the buffer size and the packet buffer timeout, and now I can fetch all the packets! Thank you for your help, Sir.

DraAngel commented 4 months ago

Another question, if I want to use Npcap to reliably transfer 1 gigabit data to another device in the LAN in the shortest possible time, is there any good advice?

DraAngel commented 4 months ago

Now, I set the buffer size to 2*1024*1024*1024 (which seems to be the maximum for an int), the packet buffer timeout to 1000, and the ps_dropto end up being 0. As I scale up the number of packets to 2M, ps_dropstarts to become nonzero during reads. However, the number of packets monitored by Wireshark was as expected. Am I setting my parameters wrong or missing some configuration items?