#include "cap.hpp"
#include "net.hpp"
#include "stream.hpp"
#include "main.hpp"
#include <pcap.h>
static pcap_t* cap = NULL;
static void cap_callback(u_char* stream, const pcap_pkthdr* hdr, const u_char* pkt) {
if (hdr->caplen != hdr->len) {
LOG("ignoring truncated capture (%u != %u)", hdr->caplen, hdr->len);
return;
}
uint32_t len = hdr->caplen;
packet_t p;
if (!p.parse(hdr->ts, pkt, len)) {
LOG("cannot parse packet");
return;
}
((Stream*)stream)->push(p);
}
void cap_loop(const char* dev, const char* filter) {
// open device for reading (promiscuous)
char errbuf[PCAP_ERRBUF_SIZE] = {0};
cap = pcap_open_live((dev && *dev)? dev: "any", BUFSIZ, 1, -1, errbuf);
if (!cap) {
LOG("pcap_open_live(): %s", errbuf);
return;
} else if (*errbuf) {
LOG("pcap_open_live(): %s", errbuf);
}
// compile and set program as filter
if (filter && *filter) {
bpf_program fp;
if (pcap_compile(cap, &fp, filter, 1, PCAP_NETMASK_UNKNOWN) == -1) {
LOG("pcap_compile(): %s (ignored)", pcap_geterr(cap));
} else {
if (pcap_setfilter(cap, &fp) == -1) {
LOG("pcap_setfilter(): %s (ignored)", pcap_geterr(cap));
}
pcap_freecode(&fp);
}
}
// loop until pcap_breakloop
Stream stream;
int rv;
do {
rv = pcap_loop(cap, -1, cap_callback, (u_char*)&stream);
} while (rv == 0);
if (rv == -1) {
LOG("pcap_loop(): %s", pcap_geterr(cap));
}
pcap_close(cap);
cap = NULL;
}
void cap_breakloop() {
if (cap) {
pcap_breakloop(cap);
}
}