#include <sys/types.h>
#include <sys/param.h>
#include <sys/time.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "gmt2local.h"
#include "pcap.h"
#include "inet.h"
#include "capture.h"
#define DEFAULT_SNAPLEN 1500
pcap_t *pc;
int datalinkOffset;
int captureDebug = 0;
unsigned int thisTimeZone;
void CaptureInit(u_int32_t sourceIP, u_int16_t sourcePort,
u_int32_t targetIP, u_int16_t targetPort, char *dev)
{
char *device = NULL;
char errbuf[PCAP_ERRBUF_SIZE];
int snaplen = DEFAULT_SNAPLEN;
int promisc = 1;
int timeout = 10;
char filtercmds[255];
bpf_u_int32 netmask = 0;
struct bpf_program filter;
char source[18];
char target[18];
int i;
thisTimeZone = gmt2local(0);
if (dev != NULL) {
device = dev;
} else {
device = pcap_lookupdev(errbuf);
if (device == NULL) {
fprintf(stderr, "Can't find capture device: %s\n", errbuf);
exit(-1);
}
}
if (captureDebug) {
printf("Device name is %s\n", device);
}
pc = pcap_open_live(device, snaplen, promisc, timeout, errbuf);
if (pc == NULL) {
fprintf(stderr,"Can't open capture device %s: %s\n",device, errbuf);
exit(-1);
}
i = pcap_snapshot(pc);
if (snaplen < i) {
fprintf(stderr, "Warning: snaplen raised to %d from %d",
snaplen, i);
}
if ((i = pcap_datalink(pc)) < 0) {
fprintf(stderr,"Unable to determine datalink type for %s: %s\n",
device, errbuf);
exit(-1);
}
switch(i) {
case DLT_EN10MB: datalinkOffset = 14; break;
case DLT_IEEE802: datalinkOffset = 22; break;
case DLT_NULL: datalinkOffset = 4; break;
case DLT_SLIP:
case DLT_PPP: datalinkOffset = 24; break;
case DLT_RAW: datalinkOffset = 0; break;
default:
fprintf(stderr,"Unknown datalink type %d\n",i);
exit(-1);
break;
}
if (InetAddress(sourceIP) < 0) {
fprintf(stderr, "Invalid source IP address (%d)\n", sourceIP);
exit(-1);
}
strncpy(source, InetAddress(sourceIP), sizeof(source) - 1);
strncpy(target, InetAddress(targetIP), sizeof(target) - 1);
sprintf(filtercmds,
"host %s and host %s and port %d\n",
source, target, targetPort);
if (captureDebug) {
printf("datalinkOffset = %d\n", datalinkOffset);
printf("filter = %s\n", filtercmds);
}
if (pcap_compile(pc, &filter, filtercmds, 1, netmask) < 0) {
printf("Error: %s", pcap_geterr(pc));
exit(-1);
}
if (pcap_setfilter(pc, &filter) < 0) {
fprintf(stderr, "Can't set filter: %s",pcap_geterr(pc));
exit(-1);
}
if (captureDebug) {
printf("Listening on %s...\n", device);
}
}
char *CaptureGetPacket(struct pcap_pkthdr *pi)
{
const u_char *p;
p = pcap_next(pc, (struct pcap_pkthdr *)pi);
if (p != NULL) {
p += datalinkOffset;
}
pi->ts.tv_sec = (pi->ts.tv_sec + thisTimeZone) % 86400;
return (char *)p;
}
void CaptureEnd()
{
struct pcap_stat stat;
if (pcap_stats(pc, &stat) < 0) {
(void)fprintf(stderr, "pcap_stats: %s\n", pcap_geterr(pc));
}
else {
(void)fprintf(stderr, "%d packets received by filter\n", stat.ps_recv);
(void)fprintf(stderr, "%d packets dropped by kernel\n", stat.ps_drop);
}
pcap_close(pc);
}