I try to sniff all the arp traffic. Here is my code:
void start(){
pcap_if_t *alldevs;
pcap_if_t *d;
char errbuf[PCAP_ERRBUF_SIZE];
int choice;
pcap_t* pcap_handle;
struct bpf_program filter;
int i=0;
if(pcap_findalldevs(&alldevs, errbuf)==-1){
fatal("pcap_findalldevs", errbuf);
return;
}
d = alldevs;
for(d=alldevs; d; d=d->next){
cout<<"#"<<i<<" "<<d->name<<endl;
if (d->description)
cout<<"description: "<<d->description<<(d->addresses==NULL?" invalid":" valid")<<endl;
++i;
}
if(i==0){
cout<<"No interfaces!"<<endl;
}
while(true){
cout<<"choose interface number: ";
cin>>choice;
if(choice<0 || choice>i-1){
cout<<"choice is out of range!"<<endl;
pcap_freealldevs(alldevs);
return;
}
d=alldevs;
for(int j=0;j<choice;++j){
d=d->next;
}
if(d->addresses==NULL)
cout<<"device is invalid!"<<endl;
else
break;
if(i==1){
return;
}
}
cout<<"@@@\tGuarding device #"<<choice<<" "<<d->name<<endl;
pcap_handle = pcap_open_live(d->name, 65535, 1, 0, errbuf);
pcap_freealldevs(alldevs);
if(pcap_handle == NULL){
fatal("pcap_open_live", errbuf);
return;
}
unsigned int netmask=((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
if(pcap_compile(pcap_handle, &filter, "arp", 1, netmask)<0){
fatal("pcap_compile", errbuf);
return;
}
if(pcap_setfilter(pcap_handle, &filter)<0){
fatal("pcap_setfilter", errbuf);
return;
}
pcap_loop(pcap_handle, 5, packet_handler, NULL);
pcap_close(pcap_handle);
}
Unfortunately, no arp packets are caught (wireshark shows me that there is arp traffic!). If I change the filter to "ip" packets are caught.. Any ideas?
regards
I would change the pcap_open_live()
call to
pcap_handle = pcap_open_live(d->name, 65535, 1, 1000, errbuf);
On several platforms, including Windows, the mechanism libpcap/WinPcap uses buffers packets up as they pass the filter, and only deliver packets to the application when the buffer fills up or the timeout expires; this is done to deliver multiple packets in one kernel->user transition, to reduce the overhead of packet capture with high volumes of traffic.
You were supplying a timeout value of 0; on several platforms, including Windows, this means "no timeout", so packets won't be delivered until the buffer fills up. ARP packets are small, and the buffer is big enough that it could take many ARP packets to fill it up; ARP packets are also relatively rare, so it could take a long time for enough ARP packets to arrive to fill it up. IP packets are bigger, sometimes much bigger, and are more frequent, so the buffer probably doesn't take too long to fill up.
A timeout value of 1000 is a timeout of 1 second, so the packets should show up within a second; that's the timeout value tcpdump uses. You can also use a lower value.