I'm trying to do some simple packet capturing with pcap, and so I've created a handle to listen through eth0. My issue is with the pcap_loop(handle, 10, myCallback, NULL);
line near the end of my code. I'm trying to use pcap_loop
.
The expected output is supposed to be:
eth0
Activated!
1
2
3
...
10
Done processing packets!
Current output is missing the increments:
eth0
Activated!
Done processing packets!
Currently it's just skipping right through to "Done processing packets!" and I have no idea why. Even if it doesn't go to the callback, it should still be waiting on packets as the ;count' parameter (see documentation for pcap_loop) is set to 10.
#include <iostream>
#include <pcap.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void myCallback(u_char *useless, const struct pcap_pkthdr* hdr, const u_char*packet){
static int count = 1;
std::cout <<count<<std::endl;
count ++;
}
int main(){
char errbuf[PCAP_ERRBUF_SIZE];
char * devName;
char* net;
char* mask;
const u_char*packet;
struct in_addr addr;
struct pcap_pkthdr hdr;
bpf_u_int32 netp;
bpf_u_int32 maskp;
pcap_if_t *devs;
pcap_findalldevs(&devs, errbuf);
devName = pcap_lookupdev(errbuf);
std::cout <<devName<<std::endl;
int success = pcap_lookupnet(devName, &netp, &maskp, errbuf);
if(success<0){
exit(EXIT_FAILURE);
}
pcap_freealldevs(devs);
//Create a handle
pcap_t *handle = pcap_create(devName, errbuf);
pcap_set_promisc(handle, 1);
pcap_can_set_rfmon(handle);
//Activate the handle
if(pcap_activate(handle)){
std::cout <<"Activated!"<<std::endl;
}
else{
exit(EXIT_FAILURE);
}
pcap_loop(handle, 10, myCallback, NULL);
std::cout <<"Done processing packets!"<<std::endl;
//close handle
pcap_close(handle);
}
pcap_findalldevs(&devs, errbuf);
That call isn't doing anything useful, as you're not doing anything with devs
other than freeing it. (You also aren't checking whether it succeeds or fails.) You might as well remove it unless you have some need to know what all the devices on which you can capture are.
pcap_can_set_rfmon(handle);
That all isn't doing anything useful, as you're not checking its return value. If you are capturing on a Wi-Fi device, and you want to capture in monitor mode, you call pcap_set_rfmon()
- not pcap_can_set_rfmon()
- on the handle after creating and before activating the handle.
//Activate the handle if(pcap_activate(handle)){ std::cout <<"Activated!"<<std::endl; } else{ exit(EXIT_FAILURE); }
To quote the pcap_activate()
man page:
RETURN VALUE
pcap_activate() returns 0 on success without warnings, PCAP_WARN-
ING_PROMISC_NOTSUP on success on a device that doesn't support promis-
cuous mode if promiscuous mode was requested, PCAP_WARNING on success
with any other warning, PCAP_ERROR_ACTIVATED if the handle has already
been activated, PCAP_ERROR_NO_SUCH_DEVICE if the capture source speci-
fied when the handle was created doesn't exist, PCAP_ERROR_PERM_DENIED
if the process doesn't have permission to open the capture source,
PCAP_ERROR_RFMON_NOTSUP if monitor mode was specified but the capture
source doesn't support monitor mode, PCAP_ERROR_IFACE_NOT_UP if the
capture source is not up, and PCAP_ERROR if another error occurred. If
PCAP_WARNING or PCAP_ERROR is returned, pcap_geterr() or pcap_perror()
may be called with p as an argument to fetch or display a message
describing the warning or error. If PCAP_WARNING_PROMISC_NOTSUP,
PCAP_ERROR_NO_SUCH_DEVICE, or PCAP_ERROR_PERM_DENIED is returned,
pcap_geterr() or pcap_perror() may be called with p as an argument to
fetch or display an message giving additional details about the problem
that might be useful for debugging the problem if it's unexpected.
This means that the code above is 100% wrong - if pcap_activate()
returns a non-zero value, it may have failed, and if it returns 0, it succeeded.
If the return value is negative, it's an error value, and it has failed. If it's non-zero but positive, it's a warning value; it has succeeded, but, for example, it might not have turned promiscuous mode on, as the OS or device might not let promiscuous mode be set.
So what you want is, instead:
//Activate the handle
int status;
status = pcap_activate(handle);
if(status >= 0){
if(status == PCAP_WARNING){
// warning
std:cout << "Activated, with warning: " << pcap_geterror(handle) << std::endl;
}
else if (status != 0){
// warning
std:cout << "Activated, with warning: " << pcap_statustostr(status) << std::endl;
}
else{
// no warning
std::cout <<"Activated!"<<std::endl;
}
}
else{
if(status == PCAP_ERROR){
std:cout << "Failed to activate: " << pcap_geterror(handle) << std::endl;
}
else{
std:cout << "Failed to activate: " << pcap_statustostr(status) << std::endl;
}
exit(EXIT_FAILURE);
}