#define PCAP_INTERFACE "lo" #define PCAP_SNAPLEN 100 #define PCAP_FILTER "not port 4430 and not port 53" #define PCAP_COUNT 20 #define PCAP_TO 300 static pcap_t * ggsniff_pcap_init(void) { pcap = my_pcap_open_live(PCAP_INTERFACE, PCAP_SNAPLEN, 1, PCAP_TO, errbuf, -1, 0); if (pcap == NULL) fatal("capture: pcap_open_live failed on interface %s\n" "with snaplen %d : %s", PCAP_INTERFACE, PCAP_SNAPLEN, errbuf); if (pcap_compile(pcap, &bprog, PCAP_FILTER, 0, 0) < 0) fatal("capture: pcap_compile failed with filter %s : %s", PCAP_FILTER, pcap_geterr(pcap)); if (pcap_setfilter(pcap, &bprog) < 0) fatal("capture: pcap_setfilter failed : %s", pcap_geterr(pcap)); } /* * reimplement pcap_open_live with more restrictions on the bpf fd : * - open device read only * - lock the fd * based on OpenBSD tcpdump, privsep_pcap.c v1.16 */ static pcap_t * my_pcap_open_live(const char *dev, int slen, int promisc, int to_ms, char *ebuf, u_int dlt, u_int dirfilt) { #if defined(__OpenBSD__) struct bpf_version bv; u_int v; pcap_t *p; char bpf[sizeof "/dev/bpf0000000000"]; int fd, n = 0; struct ifreq ifr; p = xmalloc(sizeof(*p)); bzero(p, sizeof(*p)); /* priv part */ do { snprintf(bpf, sizeof(bpf), "/dev/bpf%d", n++); fd = open(bpf, O_RDONLY); } while (fd < 0 && errno == EBUSY); if (fd < 0) return NULL; v = 32768; /* XXX this should be a user-accessible hook */ ioctl(fd, BIOCSBLEN, &v); strlcpy(ifr.ifr_name, dev, sizeof(ifr.ifr_name)); if (ioctl(fd, BIOCSETIF, &ifr) < 0) return NULL; if (dlt != (u_int) -1 && ioctl(fd, BIOCSDLT, &dlt)) return NULL; if (promisc) /* this is allowed to fail */ ioctl(fd, BIOCPROMISC, NULL); if (ioctl(fd, BIOCSDIRFILT, &dirfilt) < 0) return NULL; /* lock the descriptor */ if (ioctl(fd, BIOCLOCK, NULL) < 0) return NULL; /* end of priv part */ /* fd is locked, can only use 'safe' ioctls */ if (ioctl(fd, BIOCVERSION, &bv) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s", pcap_strerror(errno)); return NULL; } if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "kernel bpf filter out of date"); return NULL; } p->fd = fd; p->snapshot = slen; /* Get the data link layer type. */ if (ioctl(fd, BIOCGDLT, &v) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s", pcap_strerror(errno)); return NULL; } #if _BSDI_VERSION - 0 >= 199510 /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */ switch (v) { case DLT_SLIP: v = DLT_SLIP_BSDOS; break; case DLT_PPP: v = DLT_PPP_BSDOS; break; } #endif p->linktype = v; /* XXX hack from tcpdump */ if (p->linktype == DLT_PFLOG && p->snapshot < 160) p->snapshot = 160; /* set timeout */ if (to_ms != 0) { struct timeval to; to.tv_sec = to_ms / 1000; to.tv_usec = (to_ms * 1000) % 1000000; if (ioctl(p->fd, BIOCSRTIMEOUT, &to) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s", pcap_strerror(errno)); return NULL; } } if (ioctl(fd, BIOCGBLEN, &v) < 0) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s", pcap_strerror(errno)); return NULL; } p->bufsize = v; p->buffer = (u_char *)malloc(p->bufsize); if (p->buffer == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return NULL; } return p; #else /* defined(__OpenBSD__) */ return pcap_open_live(dev, slen, promisc, to_ms, ebuf); #endif }