#include <stdio.h>
#include <stdlib.h>
#include <pcap.h>
#define BUFFER_SIZE 65535
char errbuf[PCAP_ERRBUF_SIZE];
int main(int argc, char **argv)
{
int d;
pcap_if_t *alldevsp;
pcap_t *pkt_handle;
if((pcap_findalldevs(&alldevsp,errbuf))==-1)
{
printf("findalldevices: %s\n",errbuf);
exit(1);
}
printf("Availabel network devices are\n");
pcap_if_t *temp = alldevsp;
while((temp)!=NULL)
{
printf("%s: %s\n",(temp)->name,(temp)->description);
(temp)=(temp)->next;
}
pcap_freealldevs(alldevsp);
pkt_handle = pcap_create("wlan1",errbuf);
if(pkt_handle==NULL)
{
printf("create: %s\n",errbuf);
exit(1);
}
if((pcap_set_rfmon(pkt_handle, 1))!=0)
{
printf("Monitor mode could not be set\n");
exit(1);
}
if((pcap_set_buffer_size(pkt_handle, BUFFER_SIZE))!=0)
{
printf("ERROR\n");
exit(1);
}
if((d=(pcap_activate(pkt_handle)))!=0)
{
if(d==PCAP_ERROR_RFMON_NOTSUP)
printf("%d : PCAP_ERROR_RFMON_NOTSUP\n",d);
if(d==PCAP_WARNING)
printf("%d : PCAP_WARNING\n",d);
if(d==PCAP_ERROR)
printf("%d : PCAP_ERROR\n",d);
pcap_perror(pkt_handle,"Activate");
exit(1);
}
printf("d=%d\n",d);
while(1)
{
scanf("%d",&d);
if(d==-1)
break;
}
pcap_close(pkt_handle);
printf("Bye\n");
return 0;
}
When you run the above program using:
gcc -Wall -lpcap sample.c -o sample
I get the follwing error:
-1 : PCAP_ERROR
Activate: can't mmap rx ring: Invalid argument
However, if I comment out the section of code containing pcap_set_buffer_size()
function call, the program works perfectly fine.
So, what is this problem with pcap_set_buffer_size()
?
Why is it causing pcap_activate()
to fail?
For a recent 64bit Linux:
Any buffer size equal or larger then 65616 should do.
For how the value is calculated please see the implementation of create_ring()
in pcap-linux.c
from the libpcap
sources.
The default is 2*1024*1024 = 2097152.
The default buffer size on windows is 1000000.
Update:
The buffer size to be set by pcap_set_buffer_size()
refers to the (ring-)buffer, which stores the already received packages. The optimal size depends on the use case and on the affordable system resources (non-pageable memory).
Please see the following statements on the receive buffer's size verbatim from man pcap
:
Packets that arrive for a capture are stored in a buffer, so that they do not have to be read by the application as soon as they arrive. On some platforms, the buffer's size can be set; a size that's too small could mean that, if too many packets are being captured and the snapshot length doesn't limit the amount of data that's buffered, packets could be dropped if the buffer fills up before the application can read packets from it, while a size that's too large could use more non-pageable operating system memory than is necessary to prevent packets from being dropped.
Update 1:
Anyway, the buffer's size should be least the snap length set for the handle in use, plus some bytes needed to properly align the buffer itself, otherwise activating the handle ends up as described in the original question.
One can retrieve the handle's current snap length using pcap_snapshot()
. The default snap length is 65535 bytes.