From: Guy Harris Date: Mon, 6 May 2013 21:16:14 +0000 (-0700) Subject: Move platform-dependent pcap_t data out of the pcap_t structure. X-Git-Tag: libpcap-1.5.0~56^2~24 X-Git-Url: https://git.tcpdump.org/libpcap/commitdiff_plain/e9e96bbc3efd45ba6d1dbb097bc09845ba54c5d6 Move platform-dependent pcap_t data out of the pcap_t structure. Put the private data right after the pcap_t structure, with a pointer to it in the pcap_t. The initial goal is to allow new pcap modules to be added without having to hack pcap-int.h. In the longer term, we may want to freeze the pcap_t structure, except possibly for adding new method pointers at the end, and provide an ABI for adding modules. We also put the stuff used by the read path at the beginning of the pcap_t structure, to try to keep it on the same set of cache lines. --- diff --git a/dlpisubs.c b/dlpisubs.c index 23c78ced..4f2150df 100644 --- a/dlpisubs.c +++ b/dlpisubs.c @@ -66,6 +66,8 @@ static const char rcsid[] _U_ = #include #include +#include + #include "pcap-int.h" #include "dlpisubs.h" @@ -79,6 +81,7 @@ static void pcap_stream_err(const char *, int, char *); int pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps) { + struct pcap_dlpi *pd = p->private; /* * "ps_recv" counts packets handed to the filter, not packets @@ -103,7 +106,7 @@ pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps) * the kernel by libpcap, but they may include packets not * yet read from libpcap by the application. */ - *ps = p->md.stat; + *ps = pd->stat; /* * Add in the drop count, as per the above comment. @@ -120,6 +123,7 @@ int pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user, int count, u_char *bufp, int len) { + struct pcap_dlpi *pd = p->private; int n, caplen, origlen; u_char *ep, *pk; struct pcap_pkthdr pkthdr; @@ -162,7 +166,7 @@ pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user, } else #endif sbp = (struct sb_hdr *)bufp; - p->md.stat.ps_drop = sbp->sbh_drops; + pd->stat.ps_drop = sbp->sbh_drops; pk = bufp + sizeof(*sbp); bufp += sbp->sbh_totlen; origlen = sbp->sbh_origlen; @@ -173,7 +177,7 @@ pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user, pk = bufp; bufp += caplen; #endif - ++p->md.stat.ps_recv; + ++pd->stat.ps_recv; if (bpf_filter(p->fcode.bf_insns, pk, origlen, caplen)) { #ifdef HAVE_SYS_BUFMOD_H pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec; diff --git a/dlpisubs.h b/dlpisubs.h index 1b57d4d2..8795af64 100644 --- a/dlpisubs.h +++ b/dlpisubs.h @@ -10,7 +10,21 @@ extern "C" { #endif /* - * Functions used by dlpisubs.c. + * Private data for capturing on DLPI devices. + */ +struct pcap_dlpi { +#ifdef HAVE_LIBDLPI + dlpi_handle_t dlpi_hd; +#endif /* HAVE_LIBDLPI */ +#ifdef DL_HP_RAWDLS + int send_fd; +#endif /* DL_HP_RAWDLS */ + + struct pcap_stat stat; +}; + +/* + * Functions defined by dlpisubs.c. */ int pcap_stats_dlpi(pcap_t *, struct pcap_stat *); int pcap_process_pkts(pcap_t *, pcap_handler, u_char *, int, u_char *, int); diff --git a/gencode.c b/gencode.c index 1cbaeebd..cb84dc48 100644 --- a/gencode.c +++ b/gencode.c @@ -141,9 +141,7 @@ static u_int orig_linktype = -1U, orig_nl = -1U, label_stack_depth = -1U; #endif /* XXX */ -#ifdef PCAP_FDDIPAD static int pcap_fddipad; -#endif /* VARARGS */ void @@ -926,9 +924,7 @@ init_linktype(p) pcap_t *p; { linktype = pcap_datalink(p); -#ifdef PCAP_FDDIPAD pcap_fddipad = p->fddipad; -#endif /* * Assume it's not raw ATM with a pseudo-header, for now. @@ -1066,13 +1062,9 @@ init_linktype(p) * XXX - should we generate code to check for SNAP? */ off_linktype = 13; -#ifdef PCAP_FDDIPAD off_linktype += pcap_fddipad; -#endif off_macpl = 13; /* FDDI MAC header length */ -#ifdef PCAP_FDDIPAD off_macpl += pcap_fddipad; -#endif off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ return; @@ -3205,8 +3197,7 @@ gen_linktype(proto) * Then we run it through "htonl()", and * generate code to compare against the result. */ - if (bpf_pcap->sf.rfile != NULL && - bpf_pcap->sf.swapped) + if (bpf_pcap->rfile != NULL && bpf_pcap->swapped) proto = SWAPLONG(proto); proto = htonl(proto); } @@ -3718,18 +3709,10 @@ gen_fhostop(eaddr, dir) switch (dir) { case Q_SRC: -#ifdef PCAP_FDDIPAD return gen_bcmp(OR_LINK, 6 + 1 + pcap_fddipad, 6, eaddr); -#else - return gen_bcmp(OR_LINK, 6 + 1, 6, eaddr); -#endif case Q_DST: -#ifdef PCAP_FDDIPAD return gen_bcmp(OR_LINK, 0 + 1 + pcap_fddipad, 6, eaddr); -#else - return gen_bcmp(OR_LINK, 0 + 1, 6, eaddr); -#endif case Q_AND: b0 = gen_fhostop(eaddr, Q_SRC); @@ -7555,7 +7538,7 @@ gen_inbound(dir) * special meta-data in the filter expression; * if it's a savefile, we can't. */ - if (bpf_pcap->sf.rfile != NULL) { + if (bpf_pcap->rfile != NULL) { /* We have a FILE *, so this is a savefile */ bpf_error("inbound/outbound not supported on linktype %d when reading savefiles", linktype); diff --git a/pcap-bpf.c b/pcap-bpf.c index 9e739dc6..10b90264 100644 --- a/pcap-bpf.c +++ b/pcap-bpf.c @@ -126,6 +126,56 @@ static int bpf_load(char *errbuf); #include "os-proto.h" #endif +/* + * Later versions of NetBSD stick padding in front of FDDI frames + * to align the IP header on a 4-byte boundary. + */ +#if defined(__NetBSD__) && __NetBSD_Version__ > 106000000 +#define PCAP_FDDIPAD 3 +#endif + +/* + * Private data for capturing on BPF devices. + */ +struct pcap_bpf { +#ifdef PCAP_FDDIPAD + int fddipad; +#endif + +#ifdef HAVE_ZEROCOPY_BPF + /* + * Zero-copy read buffer -- for zero-copy BPF. 'buffer' above will + * alternative between these two actual mmap'd buffers as required. + * As there is a header on the front size of the mmap'd buffer, only + * some of the buffer is exposed to libpcap as a whole via bufsize; + * zbufsize is the true size. zbuffer tracks the current zbuf + * assocated with buffer so that it can be used to decide which the + * next buffer to read will be. + */ + u_char *zbuf1, *zbuf2, *zbuffer; + u_int zbufsize; + u_int zerocopy; + u_int interrupted; + struct timespec firstsel; + /* + * If there's currently a buffer being actively processed, then it is + * referenced here; 'buffer' is also pointed at it, but offset by the + * size of the header. + */ + struct bpf_zbuf_header *bzh; +#endif /* HAVE_ZEROCOPY_BPF */ + + char *device; /* device name */ + int filtering_in_kernel; /* using kernel filter */ + int timeout; /* timeout for buffering */ + int must_do_on_close; /* stuff we must do when we close */ +}; + +/* + * Stuff to do when we close. + */ +#define MUST_CLEAR_RFMON 0x00000001 /* clear rfmon (monitor) mode */ + #ifdef BIOCGDLTLIST # if (defined(HAVE_NET_IF_MEDIA_H) && defined(IFM_IEEE80211)) && !defined(__APPLE__) #define HAVE_BSD_IEEE80211 @@ -184,7 +234,7 @@ static int pcap_set_datalink_bpf(pcap_t *p, int dlt); /* * For zerocopy bpf, the setnonblock/getnonblock routines need to modify - * p->md.timeout so we don't call select(2) if the pcap handle is in non- + * pb->timeout so we don't call select(2) if the pcap handle is in non- * blocking mode. We preserve the timeout supplied by pcap_open functions * to make sure it does not get clobbered if the pcap handle moves between * blocking and non-blocking mode. @@ -193,12 +243,14 @@ static int pcap_getnonblock_bpf(pcap_t *p, char *errbuf) { #ifdef HAVE_ZEROCOPY_BPF - if (p->md.zerocopy) { + struct pcap_bpf *pb = p->private; + + if (pb->zerocopy) { /* * Use a negative value for the timeout to represent that the * pcap handle is in non-blocking mode. */ - return (p->md.timeout < 0); + return (pb->timeout < 0); } #endif return (pcap_getnonblock_fd(p, errbuf)); @@ -208,23 +260,31 @@ static int pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf) { #ifdef HAVE_ZEROCOPY_BPF - if (p->md.zerocopy) { + struct pcap_bpf *pb = p->private; + + if (pb->zerocopy) { /* * Map each value to their corresponding negation to * preserve the timeout value provided with pcap_set_timeout. * (from pcap-linux.c). */ if (nonblock) { - if (p->md.timeout >= 0) { + if (pb->timeout >= 0) { /* * Indicate that we're switching to * non-blocking mode. */ - p->md.timeout = ~p->md.timeout; + pb->timeout = ~pb->timeout; } } else { - if (p->md.timeout < 0) { - p->md.timeout = ~p->md.timeout; + if (pb->timeout < 0) { + /* + * Timeout is negative, so we're currently + * in blocking mode; reverse the previous + * operation, to make the timeout non-negative + * again. + */ + pb->timeout = ~pb->timeout; } } return (0); @@ -246,25 +306,26 @@ pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf) static int pcap_next_zbuf_shm(pcap_t *p, int *cc) { + struct pcap_bpf *pb = p->private; struct bpf_zbuf_header *bzh; - if (p->md.zbuffer == p->md.zbuf2 || p->md.zbuffer == NULL) { - bzh = (struct bpf_zbuf_header *)p->md.zbuf1; + if (pb->zbuffer == pb->zbuf2 || pb->zbuffer == NULL) { + bzh = (struct bpf_zbuf_header *)pb->zbuf1; if (bzh->bzh_user_gen != atomic_load_acq_int(&bzh->bzh_kernel_gen)) { - p->md.bzh = bzh; - p->md.zbuffer = (u_char *)p->md.zbuf1; - p->buffer = p->md.zbuffer + sizeof(*bzh); + pb->bzh = bzh; + pb->zbuffer = (u_char *)pb->zbuf1; + p->buffer = pb->zbuffer + sizeof(*bzh); *cc = bzh->bzh_kernel_len; return (1); } - } else if (p->md.zbuffer == p->md.zbuf1) { - bzh = (struct bpf_zbuf_header *)p->md.zbuf2; + } else if (pb->zbuffer == pb->zbuf1) { + bzh = (struct bpf_zbuf_header *)pb->zbuf2; if (bzh->bzh_user_gen != atomic_load_acq_int(&bzh->bzh_kernel_gen)) { - p->md.bzh = bzh; - p->md.zbuffer = (u_char *)p->md.zbuf2; - p->buffer = p->md.zbuffer + sizeof(*bzh); + pb->bzh = bzh; + pb->zbuffer = (u_char *)pb->zbuf2; + p->buffer = pb->zbuffer + sizeof(*bzh); *cc = bzh->bzh_kernel_len; return (1); } @@ -283,6 +344,7 @@ pcap_next_zbuf_shm(pcap_t *p, int *cc) static int pcap_next_zbuf(pcap_t *p, int *cc) { + struct pcap_bpf *pb = p->private; struct bpf_zbuf bz; struct timeval tv; struct timespec cur; @@ -306,15 +368,15 @@ pcap_next_zbuf(pcap_t *p, int *cc) * our timeout is less then or equal to zero, handle it like a * regular timeout. */ - tmout = p->md.timeout; + tmout = pb->timeout; if (tmout) (void) clock_gettime(CLOCK_MONOTONIC, &cur); - if (p->md.interrupted && p->md.timeout) { - expire = TSTOMILLI(&p->md.firstsel) + p->md.timeout; + if (pb->interrupted && pb->timeout) { + expire = TSTOMILLI(&pb->firstsel) + pb->timeout; tmout = expire - TSTOMILLI(&cur); #undef TSTOMILLI if (tmout <= 0) { - p->md.interrupted = 0; + pb->interrupted = 0; data = pcap_next_zbuf_shm(p, cc); if (data) return (data); @@ -331,7 +393,7 @@ pcap_next_zbuf(pcap_t *p, int *cc) * the next timeout. Note that we only call select if the handle * is in blocking mode. */ - if (p->md.timeout >= 0) { + if (pb->timeout >= 0) { FD_ZERO(&r_set); FD_SET(p->fd, &r_set); if (tmout != 0) { @@ -339,11 +401,11 @@ pcap_next_zbuf(pcap_t *p, int *cc) tv.tv_usec = (tmout * 1000) % 1000000; } r = select(p->fd + 1, &r_set, NULL, NULL, - p->md.timeout != 0 ? &tv : NULL); + pb->timeout != 0 ? &tv : NULL); if (r < 0 && errno == EINTR) { - if (!p->md.interrupted && p->md.timeout) { - p->md.interrupted = 1; - p->md.firstsel = cur; + if (!pb->interrupted && pb->timeout) { + pb->interrupted = 1; + pb->firstsel = cur; } return (0); } else if (r < 0) { @@ -352,7 +414,7 @@ pcap_next_zbuf(pcap_t *p, int *cc) return (PCAP_ERROR); } } - p->md.interrupted = 0; + pb->interrupted = 0; /* * Check again for data, which may exist now that we've either been * woken up as a result of data or timed out. Try the "there's data" @@ -380,10 +442,11 @@ pcap_next_zbuf(pcap_t *p, int *cc) static int pcap_ack_zbuf(pcap_t *p) { + struct pcap_bpf *pb = p->private; - atomic_store_rel_int(&p->md.bzh->bzh_user_gen, - p->md.bzh->bzh_kernel_gen); - p->md.bzh = NULL; + atomic_store_rel_int(&pb->bzh->bzh_user_gen, + pb->bzh->bzh_kernel_gen); + pb->bzh = NULL; p->buffer = NULL; return (0); } @@ -394,7 +457,7 @@ pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_bpf)); if (p == NULL) return (NULL); @@ -790,6 +853,7 @@ pcap_stats_bpf(pcap_t *p, struct pcap_stat *ps) static int pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { + struct pcap_bpf *pb = p->private; int cc; int n = 0; register u_char *bp, *ep; @@ -825,7 +889,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) * buffer. */ #ifdef HAVE_ZEROCOPY_BPF - if (p->md.zerocopy) { + if (pb->zerocopy) { if (p->buffer != NULL) pcap_ack_zbuf(p); i = pcap_next_zbuf(p, &cc); @@ -973,7 +1037,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) * skipping that padding. #endif */ - if (p->md.use_bpf || + if (pb->filtering_in_kernel || bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) { struct pcap_pkthdr pkthdr; @@ -1240,19 +1304,20 @@ bpf_load(char *errbuf) static void pcap_cleanup_bpf(pcap_t *p) { + struct pcap_bpf *pb = p->private; #ifdef HAVE_BSD_IEEE80211 int sock; struct ifmediareq req; struct ifreq ifr; #endif - if (p->md.must_do_on_close != 0) { + if (pb->must_do_on_close != 0) { /* * There's something we have to do when closing this * pcap_t. */ #ifdef HAVE_BSD_IEEE80211 - if (p->md.must_do_on_close & MUST_CLEAR_RFMON) { + if (pb->must_do_on_close & MUST_CLEAR_RFMON) { /* * We put the interface into rfmon mode; * take it out of rfmon mode. @@ -1269,7 +1334,7 @@ pcap_cleanup_bpf(pcap_t *p) strerror(errno)); } else { memset(&req, 0, sizeof(req)); - strncpy(req.ifm_name, p->md.device, + strncpy(req.ifm_name, pb->device, sizeof(req.ifm_name)); if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) { fprintf(stderr, @@ -1284,7 +1349,7 @@ pcap_cleanup_bpf(pcap_t *p) */ memset(&ifr, 0, sizeof(ifr)); (void)strncpy(ifr.ifr_name, - p->md.device, + pb->device, sizeof(ifr.ifr_name)); ifr.ifr_media = req.ifm_current & ~IFM_IEEE80211_MONITOR; @@ -1307,11 +1372,11 @@ pcap_cleanup_bpf(pcap_t *p) * have to take the interface out of some mode. */ pcap_remove_from_pcaps_to_close(p); - p->md.must_do_on_close = 0; + pb->must_do_on_close = 0; } #ifdef HAVE_ZEROCOPY_BPF - if (p->md.zerocopy) { + if (pb->zerocopy) { /* * Delete the mappings. Note that p->buffer gets * initialized to one of the mmapped regions in @@ -1319,16 +1384,16 @@ pcap_cleanup_bpf(pcap_t *p) * null it out so that pcap_cleanup_live_common() * doesn't try to free it. */ - if (p->md.zbuf1 != MAP_FAILED && p->md.zbuf1 != NULL) - (void) munmap(p->md.zbuf1, p->md.zbufsize); - if (p->md.zbuf2 != MAP_FAILED && p->md.zbuf2 != NULL) - (void) munmap(p->md.zbuf2, p->md.zbufsize); + if (pb->zbuf1 != MAP_FAILED && pb->zbuf1 != NULL) + (void) munmap(pb->zbuf1, pb->zbufsize); + if (pb->zbuf2 != MAP_FAILED && pb->zbuf2 != NULL) + (void) munmap(pb->zbuf2, pb->zbufsize); p->buffer = NULL; } #endif - if (p->md.device != NULL) { - free(p->md.device); - p->md.device = NULL; + if (pb->device != NULL) { + free(pb->device); + pb->device = NULL; } pcap_cleanup_live_common(p); } @@ -1443,6 +1508,7 @@ check_setif_failure(pcap_t *p, int error) static int pcap_activate_bpf(pcap_t *p) { + struct pcap_bpf *pb = p->private; int status = 0; int fd; #ifdef LIFNAMSIZ @@ -1524,8 +1590,8 @@ pcap_activate_bpf(pcap_t *p) } #endif - p->md.device = strdup(p->opt.source); - if (p->md.device == NULL) { + pb->device = strdup(p->opt.source); + if (pb->device == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s", pcap_strerror(errno)); status = PCAP_ERROR; @@ -1633,7 +1699,7 @@ pcap_activate_bpf(pcap_t *p) /* * We have zerocopy BPF; use it. */ - p->md.zerocopy = 1; + pb->zerocopy = 1; /* * How to pick a buffer size: first, query the maximum buffer @@ -1663,22 +1729,22 @@ pcap_activate_bpf(pcap_t *p) #ifndef roundup #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */ #endif - p->md.zbufsize = roundup(v, getpagesize()); - if (p->md.zbufsize > zbufmax) - p->md.zbufsize = zbufmax; - p->md.zbuf1 = mmap(NULL, p->md.zbufsize, PROT_READ | PROT_WRITE, + pb->zbufsize = roundup(v, getpagesize()); + if (pb->zbufsize > zbufmax) + pb->zbufsize = zbufmax; + pb->zbuf1 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0); - p->md.zbuf2 = mmap(NULL, p->md.zbufsize, PROT_READ | PROT_WRITE, + pb->zbuf2 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE, MAP_ANON, -1, 0); - if (p->md.zbuf1 == MAP_FAILED || p->md.zbuf2 == MAP_FAILED) { + if (pb->zbuf1 == MAP_FAILED || pb->zbuf2 == MAP_FAILED) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "mmap: %s", pcap_strerror(errno)); goto bad; } memset(&bz, 0, sizeof(bz)); /* bzero() deprecated, replaced with memset() */ - bz.bz_bufa = p->md.zbuf1; - bz.bz_bufb = p->md.zbuf2; - bz.bz_buflen = p->md.zbufsize; + bz.bz_bufa = pb->zbuf1; + bz.bz_bufb = pb->zbuf2; + bz.bz_buflen = pb->zbufsize; if (ioctl(fd, BIOCSETZBUF, (caddr_t)&bz) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETZBUF: %s", pcap_strerror(errno)); @@ -1690,7 +1756,7 @@ pcap_activate_bpf(pcap_t *p) p->opt.source, pcap_strerror(errno)); goto bad; } - v = p->md.zbufsize - sizeof(struct bpf_zbuf_header); + v = pb->zbufsize - sizeof(struct bpf_zbuf_header); } else #endif { @@ -2002,8 +2068,8 @@ pcap_activate_bpf(pcap_t *p) if (v == DLT_FDDI) p->fddipad = PCAP_FDDIPAD; else - p->fddipad = 0; #endif + p->fddipad = 0; p->linktype = v; #if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT) @@ -2024,10 +2090,11 @@ pcap_activate_bpf(pcap_t *p) } #endif /* set timeout */ + pb->timeout = p->opt.timeout; #ifdef HAVE_ZEROCOPY_BPF - if (p->md.timeout != 0 && !p->md.zerocopy) { + if (pb->timeout != 0 && !pb->zerocopy) { #else - if (p->md.timeout) { + if (pb->timeout) { #endif /* * XXX - is this seconds/nanoseconds in AIX? @@ -2051,8 +2118,8 @@ pcap_activate_bpf(pcap_t *p) struct BPF_TIMEVAL bpf_to; if (IOCPARM_LEN(BIOCSRTIMEOUT) != sizeof(struct timeval)) { - bpf_to.tv_sec = p->md.timeout / 1000; - bpf_to.tv_usec = (p->md.timeout * 1000) % 1000000; + bpf_to.tv_sec = pb->timeout / 1000; + bpf_to.tv_usec = (pb->timeout * 1000) % 1000000; if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&bpf_to) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s", pcap_strerror(errno)); @@ -2061,8 +2128,8 @@ pcap_activate_bpf(pcap_t *p) } } else { #endif - to.tv_sec = p->md.timeout / 1000; - to.tv_usec = (p->md.timeout * 1000) % 1000000; + to.tv_sec = pb->timeout / 1000; + to.tv_usec = (pb->timeout * 1000) % 1000000; if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s", pcap_strerror(errno)); @@ -2149,7 +2216,7 @@ pcap_activate_bpf(pcap_t *p) } p->bufsize = v; #ifdef HAVE_ZEROCOPY_BPF - if (!p->md.zerocopy) { + if (!pb->zerocopy) { #endif p->buffer = (u_char *)malloc(p->bufsize); if (p->buffer == NULL) { @@ -2264,6 +2331,7 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) static int monitor_mode(pcap_t *p, int set) { + struct pcap_bpf *pb = p->private; int sock; struct ifmediareq req; int *media_list; @@ -2401,7 +2469,7 @@ monitor_mode(pcap_t *p, int set) return (PCAP_ERROR); } - p->md.must_do_on_close |= MUST_CLEAR_RFMON; + pb->must_do_on_close |= MUST_CLEAR_RFMON; /* * Add this to the list of pcaps to close when we exit. @@ -2578,6 +2646,8 @@ remove_802_11(pcap_t *p) static int pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp) { + struct pcap_bpf *pb = p->private; + /* * Free any user-mode filter we might happen to have installed. */ @@ -2590,7 +2660,7 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp) /* * It worked. */ - p->md.use_bpf = 1; /* filtering in the kernel */ + pb->filtering_in_kernel = 1; /* filtering in the kernel */ /* * Discard any previously-received packets, as they might @@ -2630,7 +2700,7 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp) */ if (install_bpf_program(p, fp) < 0) return (-1); - p->md.use_bpf = 0; /* filtering in userland */ + pb->filtering_in_kernel = 0; /* filtering in userland */ return (0); } diff --git a/pcap-bt-linux.c b/pcap-bt-linux.c index 037f64b9..e2268b8e 100644 --- a/pcap-bt-linux.c +++ b/pcap-bt-linux.c @@ -70,6 +70,13 @@ static int bt_inject_linux(pcap_t *, const void *, size_t); static int bt_setdirection_linux(pcap_t *, pcap_direction_t); static int bt_stats_linux(pcap_t *, struct pcap_stat *); +/* + * Private data for capturing on Linux Bluetooth devices. + */ +struct pcap_bt { + int dev_id; /* device ID of device we're bound to */ +}; + int bt_findalldevs(pcap_if_t **alldevsp, char *err_str) { @@ -169,7 +176,7 @@ bt_create(const char *device, char *ebuf, int *is_ours) /* OK, it's probably ours. */ *is_ours = 1; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_bt)); if (p == NULL) return (NULL); @@ -180,6 +187,7 @@ bt_create(const char *device, char *ebuf, int *is_ours) static int bt_activate(pcap_t* handle) { + struct pcap_bt *handlep = handle->private; struct sockaddr_hci addr; int opt; int dev_id; @@ -208,7 +216,7 @@ bt_activate(pcap_t* handle) handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = pcap_setnonblock_fd; handle->stats_op = bt_stats_linux; - handle->md.ifindex = dev_id; + handlep->dev_id = dev_id; /* Create HCI socket */ handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); @@ -253,13 +261,13 @@ bt_activate(pcap_t* handle) /* Bind socket to the HCI device */ addr.hci_family = AF_BLUETOOTH; - addr.hci_dev = handle->md.ifindex; + addr.hci_dev = handlep->dev_id; #ifdef SOCKADDR_HCI_HAS_HCI_CHANNEL addr.hci_channel = HCI_CHANNEL_RAW; #endif if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, - "Can't attach to device %d: %s", handle->md.ifindex, + "Can't attach to device %d: %s", handlep->dev_id, strerror(errno)); goto close_fail; } @@ -374,10 +382,11 @@ bt_inject_linux(pcap_t *handle, const void *buf, size_t size) static int bt_stats_linux(pcap_t *handle, struct pcap_stat *stats) { + struct pcap_bt *handlep = handle->private; int ret; struct hci_dev_info dev_info; struct hci_dev_stats * s = &dev_info.stat; - dev_info.dev_id = handle->md.ifindex; + dev_info.dev_id = handlep->dev_id; /* ignore eintr */ do { diff --git a/pcap-can-linux.c b/pcap-can-linux.c index f6a3925e..bee669b0 100644 --- a/pcap-can-linux.c +++ b/pcap-can-linux.c @@ -72,6 +72,13 @@ static int can_setfilter_linux(pcap_t *, struct bpf_program *); static int can_setdirection_linux(pcap_t *, pcap_direction_t); static int can_stats_linux(pcap_t *, struct pcap_stat *); +/* + * Private data for capturing on Linux CANbus devices. + */ +struct pcap_can { + int ifindex; /* interface index of device we're bound to */ +}; + int can_findalldevs(pcap_if_t **devlistp, char *errbuf) { @@ -124,7 +131,7 @@ can_create(const char *device, char *ebuf, int *is_ours) /* OK, it's probably ours. */ *is_ours = 1; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_can)); if (p == NULL) return (NULL); @@ -136,6 +143,7 @@ can_create(const char *device, char *ebuf, int *is_ours) static int can_activate(pcap_t* handle) { + struct pcap_can *handlep = handle->private; struct sockaddr_can addr; struct ifreq ifr; @@ -172,7 +180,7 @@ can_activate(pcap_t* handle) pcap_cleanup_live_common(handle); return PCAP_ERROR; } - handle->md.ifindex = ifr.ifr_ifindex; + handlep->ifindex = ifr.ifr_ifindex; /* allocate butter */ handle->buffer = malloc(handle->bufsize); @@ -186,11 +194,11 @@ can_activate(pcap_t* handle) /* Bind to the socket */ addr.can_family = AF_CAN; - addr.can_ifindex = handle->md.ifindex; + addr.can_ifindex = handlep->ifindex; if( bind( handle->fd, (struct sockaddr*)&addr, sizeof(addr) ) < 0 ) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't attach to device %d %d:%s", - handle->md.ifindex, errno, strerror(errno)); + handlep->ifindex, errno, strerror(errno)); pcap_cleanup_live_common(handle); return PCAP_ERROR; } @@ -199,7 +207,7 @@ can_activate(pcap_t* handle) { /* Monitor mode doesn't apply to CAN devices. */ pcap_cleanup_live_common(handle); - return PCAP_ERROR; + return PCAP_ERROR_RFMON_NOTSUP; } handle->selectable_fd = handle->fd; diff --git a/pcap-canusb-linux.c b/pcap-canusb-linux.c index f3bebbc7..b04e8b6d 100644 --- a/pcap-canusb-linux.c +++ b/pcap-canusb-linux.c @@ -42,6 +42,7 @@ #include #include #include +#include #include "pcap-int.h" #include "pcap-canusb-linux.h" @@ -74,25 +75,22 @@ struct CAN_Msg uint8_t data[8]; }; -struct canusb_t -{ +/* + * Private data for capturing on Linux CANbus USB devices. + */ +struct pcap_canusb { libusb_context *ctx; libusb_device_handle *dev; - char *serial; pthread_t worker; int rdpipe, wrpipe; - volatile int* loop; + volatile int loop; }; -static struct canusb_t canusb; -static volatile int loop; - int canusb_findalldevs(pcap_if_t **alldevsp, char *err_str) { libusb_context *fdctx; libusb_device** devs; unsigned char sernum[65]; - unsigned char buf[96]; int cnt, i; if (libusb_init(&fdctx) != 0) { @@ -119,7 +117,7 @@ int canusb_findalldevs(pcap_if_t **alldevsp, char *err_str) //It is! libusb_device_handle *dh = NULL; - if (ret = libusb_open(devs[i],&dh) == 0) + if ((ret = libusb_open(devs[i],&dh)) == 0) { char dev_name[30]; char dev_descr[50]; @@ -134,6 +132,7 @@ int canusb_findalldevs(pcap_if_t **alldevsp, char *err_str) if (pcap_add_if(alldevsp, dev_name, 0, dev_descr, err_str) < 0) { libusb_free_device_list(devs,1); + libusb_exit(fdctx); return -1; } } @@ -146,7 +145,6 @@ int canusb_findalldevs(pcap_if_t **alldevsp, char *err_str) static libusb_device_handle* canusb_opendevice(struct libusb_context *ctx, char* devserial) { - libusb_device_handle* dh; libusb_device** devs; unsigned char serial[65]; int cnt,i,n; @@ -170,7 +168,7 @@ static libusb_device_handle* canusb_opendevice(struct libusb_context *ctx, char* n = libusb_get_string_descriptor_ascii(dh,desc.iSerialNumber,serial,64); serial[n] = 0; - if ((devserial) && (strcmp(serial,devserial) != 0)) + if ((devserial) && (strcmp((char *)serial,devserial) != 0)) { libusb_close(dh); continue; @@ -211,8 +209,7 @@ canusb_create(const char *device, char *ebuf, int *is_ours) char *cpend; long devnum; pcap_t* p; - - libusb_init(&canusb.ctx); + struct pcap_canusb *canusb; /* Does this look like a DAG device? */ cp = strrchr(device, '/'); @@ -241,11 +238,15 @@ canusb_create(const char *device, char *ebuf, int *is_ours) /* OK, it's probably ours. */ *is_ours = 1; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_canusb)); if (p == NULL) return (NULL); - memset(&canusb, 0x00, sizeof(canusb)); + canusb = p->private; + canusb->ctx = NULL; + canusb->dev = NULL; + canusb->rdpipe = -1; + canusb->wrpipe = -1; p->activate_op = canusb_activate; @@ -253,65 +254,54 @@ canusb_create(const char *device, char *ebuf, int *is_ours) } -static void* canusb_capture_thread(struct canusb_t *canusb) +static void* canusb_capture_thread(void *arg) { - struct libusb_context *ctx; - libusb_device_handle *dev; - int i, n; + struct pcap_canusb *canusb = arg; + int i; struct { uint8_t rxsz, txsz; } status; - char *serial; - - libusb_init(&ctx); - - serial = canusb->serial; - dev = canusb_opendevice(ctx, serial); fcntl(canusb->wrpipe, F_SETFL, O_NONBLOCK); - while(*canusb->loop) + while(canusb->loop) { - int sz, ret; + int sz; struct CAN_Msg msg; - libusb_interrupt_transfer(dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100); + libusb_interrupt_transfer(canusb->dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100); //HACK!!!!! -> drop buffered data, read new one by reading twice. - ret = libusb_interrupt_transfer(dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100); + libusb_interrupt_transfer(canusb->dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100); for(i = 0; iwrpipe, &msg, sizeof(msg)); + libusb_bulk_transfer(canusb->dev, 0x85, (unsigned char*)&msg, sizeof(msg), &sz, 100); + write(canusb->wrpipe, &msg, sizeof(msg)); } } - libusb_close(dev); - libusb_exit(ctx); - return NULL; } -static int canusb_startcapture(struct canusb_t* this) +static int canusb_startcapture(struct pcap_canusb* this) { int pipefd[2]; if (pipe(pipefd) == -1) return -1; - canusb.rdpipe = pipefd[0]; - canusb.wrpipe = pipefd[1]; - canusb.loop = &loop; + this->rdpipe = pipefd[0]; + this->wrpipe = pipefd[1]; - loop = 1; - pthread_create(&this->worker, NULL, canusb_capture_thread, &canusb); + this->loop = 1; + pthread_create(&this->worker, NULL, canusb_capture_thread, this); - return canusb.rdpipe; + return this->rdpipe; } -static void canusb_clearbufs(struct canusb_t* this) +static void canusb_clearbufs(struct pcap_canusb* this) { unsigned char cmd[16]; int al; @@ -327,22 +317,38 @@ static void canusb_clearbufs(struct canusb_t* this) static void canusb_close(pcap_t* handle) { - loop = 0; - pthread_join(canusb.worker, NULL); + struct pcap_canusb *canusb = handle->private; + + canusb->loop = 0; + pthread_join(canusb->worker, NULL); - if (canusb.dev) + if (canusb->dev) { - libusb_close(canusb.dev); - canusb.dev = NULL; + libusb_close(canusb->dev); + canusb->dev = NULL; } + if (canusb->ctx) + { + libusb_exit(canusb->ctx); + canusb->ctx = NULL; + } } static int canusb_activate(pcap_t* handle) { + struct pcap_canusb *canusb = handle->private; char *serial; + if (libusb_init(&canusb->ctx) != 0) { + /* + * XXX - what causes this to fail? + */ + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "libusb_init() failed"); + return PCAP_ERROR; + } + handle->read_op = canusb_read_linux; handle->inject_op = canusb_inject_linux; @@ -360,18 +366,18 @@ static int canusb_activate(pcap_t* handle) handle->set_datalink_op = NULL; serial = handle->opt.source + strlen(CANUSB_IFACE); - canusb.serial = strdup(serial); - canusb.dev = canusb_opendevice(canusb.ctx,serial); - if (!canusb.dev) + canusb->dev = canusb_opendevice(canusb->ctx, serial); + if (!canusb->dev) { - snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't open USB Device:"); + libusb_exit(canusb->ctx); + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't open USB Device"); return PCAP_ERROR; } - canusb_clearbufs(&canusb); + canusb_clearbufs(canusb); - handle->fd = canusb_startcapture(&canusb); + handle->fd = canusb_startcapture(canusb); handle->selectable_fd = handle->fd; return 0; @@ -384,8 +390,6 @@ static int canusb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { static struct timeval firstpacket = { -1, -1}; - - int msgsent = 0; int i = 0; struct CAN_Msg msg; struct pcap_pkthdr pkth; diff --git a/pcap-dag.c b/pcap-dag.c index 847a556f..d006aa61 100644 --- a/pcap-dag.c +++ b/pcap-dag.c @@ -76,6 +76,27 @@ struct sunatm_hdr { unsigned short vci; /* VCI */ }; +/* + * Private data for capturing on DAG devices. + */ +struct pcap_dag { + struct pcap_stat stat; +#ifdef HAVE_DAG_STREAMS_API + u_char *dag_mem_bottom; /* DAG card current memory bottom pointer */ + u_char *dag_mem_top; /* DAG card current memory top pointer */ +#else /* HAVE_DAG_STREAMS_API */ + void *dag_mem_base; /* DAG card memory base address */ + u_int dag_mem_bottom; /* DAG card current memory bottom offset */ + u_int dag_mem_top; /* DAG card current memory top offset */ +#endif /* HAVE_DAG_STREAMS_API */ + int dag_fcs_bits; /* Number of checksum bits from link layer */ + int dag_offset_flags; /* Flags to pass to dag_offset(). */ + int dag_stream; /* DAG stream number */ + int dag_timeout; /* timeout specified to pcap_open_live. + * Same as in linux above, introduce + * generally? */ +}; + typedef struct pcap_dag_node { struct pcap_dag_node *next; pcap_t *p; @@ -124,13 +145,15 @@ delete_pcap_dag(pcap_t *p) static void dag_platform_cleanup(pcap_t *p) { - + struct pcap_dag *pd; + if (p != NULL) { + pd = p->private; #ifdef HAVE_DAG_STREAMS_API - if(dag_stop_stream(p->fd, p->md.dag_stream) < 0) + if(dag_stop_stream(p->fd, pd->dag_stream) < 0) fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno)); - if(dag_detach_stream(p->fd, p->md.dag_stream) < 0) + if(dag_detach_stream(p->fd, pd->dag_stream) < 0) fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno)); #else if(dag_stop(p->fd) < 0) @@ -222,13 +245,14 @@ dag_erf_ext_header_count(uint8_t * erf, size_t len) static int dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { + struct pcap_dag *pd = p->private; unsigned int processed = 0; - int flags = p->md.dag_offset_flags; + int flags = pd->dag_offset_flags; unsigned int nonblocking = flags & DAGF_NONBLOCK; unsigned int num_ext_hdr = 0; /* Get the next bufferful of packets (if necessary). */ - while (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size) { + while (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size) { /* * Has "pcap_breakloop()" been called? @@ -255,23 +279,23 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) * If non-block is specified it will return immediately. The user * is then responsible for efficiency. */ - if ( NULL == (p->md.dag_mem_top = dag_advance_stream(p->fd, p->md.dag_stream, &(p->md.dag_mem_bottom))) ) { + if ( NULL == (pd->dag_mem_top = dag_advance_stream(p->fd, pd->dag_stream, &(pd->dag_mem_bottom))) ) { return -1; } #else /* dag_offset does not support timeouts */ - p->md.dag_mem_top = dag_offset(p->fd, &(p->md.dag_mem_bottom), flags); + pd->dag_mem_top = dag_offset(p->fd, &(pd->dag_mem_bottom), flags); #endif /* HAVE_DAG_STREAMS_API */ - if (nonblocking && (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size)) + if (nonblocking && (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size)) { /* Pcap is configured to process only available packets, and there aren't any, return immediately. */ return 0; } if(!nonblocking && - p->md.dag_timeout && - (p->md.dag_mem_top - p->md.dag_mem_bottom < dag_record_size)) + pd->dag_timeout && + (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size)) { /* Blocking mode, but timeout set and no data has arrived, return anyway.*/ return 0; @@ -280,16 +304,16 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) } /* Process the packets. */ - while (p->md.dag_mem_top - p->md.dag_mem_bottom >= dag_record_size) { + while (pd->dag_mem_top - pd->dag_mem_bottom >= dag_record_size) { unsigned short packet_len = 0; int caplen = 0; struct pcap_pkthdr pcap_header; #ifdef HAVE_DAG_STREAMS_API - dag_record_t *header = (dag_record_t *)(p->md.dag_mem_bottom); + dag_record_t *header = (dag_record_t *)(pd->dag_mem_bottom); #else - dag_record_t *header = (dag_record_t *)(p->md.dag_mem_base + p->md.dag_mem_bottom); + dag_record_t *header = (dag_record_t *)(pd->dag_mem_base + pd->dag_mem_bottom); #endif /* HAVE_DAG_STREAMS_API */ u_char *dp = ((u_char *)header); /* + dag_record_size; */ @@ -314,7 +338,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE); return -1; } - p->md.dag_mem_bottom += rlen; + pd->dag_mem_bottom += rlen; /* Count lost packets. */ switch((header->type & 0x7f)) { @@ -330,10 +354,10 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) default: if (header->lctr) { - if (p->md.stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) { - p->md.stat.ps_drop = UINT_MAX; + if (pd->stat.ps_drop > (UINT_MAX - ntohs(header->lctr))) { + pd->stat.ps_drop = UINT_MAX; } else { - p->md.stat.ps_drop += ntohs(header->lctr); + pd->stat.ps_drop += ntohs(header->lctr); } } } @@ -441,7 +465,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) case TYPE_COLOR_ETH: case TYPE_ETH: packet_len = ntohs(header->wlen); - packet_len -= (p->md.dag_fcs_bits >> 3); + packet_len -= (pd->dag_fcs_bits >> 3); caplen = rlen - dag_record_size - 2; if (caplen > packet_len) { caplen = packet_len; @@ -454,7 +478,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) case TYPE_COLOR_HDLC_POS: case TYPE_HDLC_POS: packet_len = ntohs(header->wlen); - packet_len -= (p->md.dag_fcs_bits >> 3); + packet_len -= (pd->dag_fcs_bits >> 3); caplen = rlen - dag_record_size; if (caplen > packet_len) { caplen = packet_len; @@ -464,7 +488,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) case TYPE_COLOR_MC_HDLC_POS: case TYPE_MC_HDLC: packet_len = ntohs(header->wlen); - packet_len -= (p->md.dag_fcs_bits >> 3); + packet_len -= (pd->dag_fcs_bits >> 3); caplen = rlen - dag_record_size - 4; if (caplen > packet_len) { caplen = packet_len; @@ -545,7 +569,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) pcap_header.len = packet_len; /* Count the packet. */ - p->md.stat.ps_recv++; + pd->stat.ps_recv++; /* Call the user supplied callback function */ callback(user, &pcap_header, dp); @@ -584,6 +608,7 @@ dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_) */ static int dag_activate(pcap_t* handle) { + struct pcap_dag *handlep = handle->private; #if 0 char conf[30]; /* dag configure string */ #endif @@ -613,13 +638,13 @@ static int dag_activate(pcap_t* handle) } /* Parse input name to get dag device and stream number if provided */ - if (dag_parse_name(device, newDev, strlen(device) + 16, &handle->md.dag_stream) < 0) { + if (dag_parse_name(device, newDev, strlen(device) + 16, &handlep->dag_stream) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno)); goto fail; } device = newDev; - if (handle->md.dag_stream%2) { + if (handlep->dag_stream%2) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture\n"); goto fail; } @@ -644,7 +669,7 @@ static int dag_activate(pcap_t* handle) #ifdef HAVE_DAG_STREAMS_API /* Open requested stream. Can fail if already locked or on error */ - if (dag_attach_stream(handle->fd, handle->md.dag_stream, 0, 0) < 0) { + if (dag_attach_stream(handle->fd, handlep->dag_stream, 0, 0) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_attach_stream: %s\n", pcap_strerror(errno)); goto failclose; } @@ -652,7 +677,7 @@ static int dag_activate(pcap_t* handle) /* Set up default poll parameters for stream * Can be overridden by pcap_set_nonblock() */ - if (dag_get_stream_poll(handle->fd, handle->md.dag_stream, + if (dag_get_stream_poll(handle->fd, handlep->dag_stream, &mindata, &maxwait, &poll) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno)); goto faildetach; @@ -664,20 +689,20 @@ static int dag_activate(pcap_t* handle) */ mindata = 65536; - /* Obey md.timeout (was to_ms) if supplied. This is a good idea! + /* Obey opt.timeout (was to_ms) if supplied. This is a good idea! * Recommend 10-100ms. Calls will time out even if no data arrived. */ - maxwait.tv_sec = handle->md.timeout/1000; - maxwait.tv_usec = (handle->md.timeout%1000) * 1000; + maxwait.tv_sec = handle->opt.timeout/1000; + maxwait.tv_usec = (handle->opt.timeout%1000) * 1000; - if (dag_set_stream_poll(handle->fd, handle->md.dag_stream, + if (dag_set_stream_poll(handle->fd, handlep->dag_stream, mindata, &maxwait, &poll) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno)); goto faildetach; } #else - if((handle->md.dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) { + if((handlep->dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno)); goto failclose; } @@ -707,7 +732,7 @@ static int dag_activate(pcap_t* handle) #endif #ifdef HAVE_DAG_STREAMS_API - if(dag_start_stream(handle->fd, handle->md.dag_stream) < 0) { + if(dag_start_stream(handle->fd, handlep->dag_stream) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno)); goto faildetach; } @@ -723,8 +748,8 @@ static int dag_activate(pcap_t* handle) * initialized to zero on startup, it won't give you * a compiler warning if you make this mistake! */ - handle->md.dag_mem_bottom = 0; - handle->md.dag_mem_top = 0; + handlep->dag_mem_bottom = 0; + handlep->dag_mem_top = 0; /* * Find out how many FCS bits we should strip. @@ -733,7 +758,7 @@ static int dag_activate(pcap_t* handle) daginf = dag_info(handle->fd); if ((0x4200 == daginf->device_code) || (0x4230 == daginf->device_code)) { /* DAG 4.2S and 4.23S already strip the FCS. Stripping the final word again truncates the packet. */ - handle->md.dag_fcs_bits = 0; + handlep->dag_fcs_bits = 0; /* Note that no FCS will be supplied. */ handle->linktype_ext = LT_FCS_DATALINK_EXT(0); @@ -741,12 +766,12 @@ static int dag_activate(pcap_t* handle) /* * Start out assuming it's 32 bits. */ - handle->md.dag_fcs_bits = 32; + handlep->dag_fcs_bits = 32; /* Allow an environment variable to override. */ if ((s = getenv("ERF_FCS_BITS")) != NULL) { if ((n = atoi(s)) == 0 || n == 16 || n == 32) { - handle->md.dag_fcs_bits = n; + handlep->dag_fcs_bits = n; } else { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment\n", device, n); @@ -760,14 +785,14 @@ static int dag_activate(pcap_t* handle) if ((s = getenv("ERF_DONT_STRIP_FCS")) != NULL) { /* Yes. Note the number of bytes that will be supplied. */ - handle->linktype_ext = LT_FCS_DATALINK_EXT(handle->md.dag_fcs_bits/16); + handle->linktype_ext = LT_FCS_DATALINK_EXT(handlep->dag_fcs_bits/16); /* And don't strip them. */ - handle->md.dag_fcs_bits = 0; + handlep->dag_fcs_bits = 0; } } - handle->md.dag_timeout = handle->md.timeout; + handlep->dag_timeout = handle->opt.timeout; handle->linktype = -1; if (dag_get_datalink(handle) < 0) @@ -798,19 +823,19 @@ static int dag_activate(pcap_t* handle) handle->setnonblock_op = dag_setnonblock; handle->stats_op = dag_stats; handle->cleanup_op = dag_platform_cleanup; - handle->md.stat.ps_drop = 0; - handle->md.stat.ps_recv = 0; - handle->md.stat.ps_ifdrop = 0; + handlep->stat.ps_drop = 0; + handlep->stat.ps_recv = 0; + handlep->stat.ps_ifdrop = 0; return 0; #ifdef HAVE_DAG_STREAMS_API failstop: - if (dag_stop_stream(handle->fd, handle->md.dag_stream) < 0) { + if (dag_stop_stream(handle->fd, handlep->dag_stream) < 0) { fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno)); } faildetach: - if (dag_detach_stream(handle->fd, handle->md.dag_stream) < 0) + if (dag_detach_stream(handle->fd, handlep->dag_stream) < 0) fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno)); #else failstop: @@ -866,7 +891,7 @@ pcap_t *dag_create(const char *device, char *ebuf, int *is_ours) /* OK, it's probably ours. */ *is_ours = 1; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_dag)); if (p == NULL) return NULL; @@ -876,13 +901,15 @@ pcap_t *dag_create(const char *device, char *ebuf, int *is_ours) static int dag_stats(pcap_t *p, struct pcap_stat *ps) { + struct pcap_dag *pd = p->private; + /* This needs to be filled out correctly. Hopefully a dagapi call will provide all necessary information. */ - /*p->md.stat.ps_recv = 0;*/ - /*p->md.stat.ps_drop = 0;*/ + /*pd->stat.ps_recv = 0;*/ + /*pd->stat.ps_drop = 0;*/ - *ps = p->md.stat; + *ps = pd->stat; return 0; } @@ -972,8 +999,6 @@ dag_setfilter(pcap_t *p, struct bpf_program *fp) if (install_bpf_program(p, fp) < 0) return -1; - p->md.use_bpf = 0; - return (0); } @@ -988,11 +1013,13 @@ dag_set_datalink(pcap_t *p, int dlt) static int dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) { + struct pcap_dag *pd = p->private; + /* * Set non-blocking mode on the FD. * XXX - is that necessary? If not, don't bother calling it, * and have a "dag_getnonblock()" function that looks at - * "p->md.dag_offset_flags". + * "pd->dag_offset_flags". */ if (pcap_setnonblock_fd(p, nonblock, errbuf) < 0) return (-1); @@ -1002,7 +1029,7 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) struct timeval maxwait; struct timeval poll; - if (dag_get_stream_poll(p->fd, p->md.dag_stream, + if (dag_get_stream_poll(p->fd, pd->dag_stream, &mindata, &maxwait, &poll) < 0) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno)); return -1; @@ -1017,7 +1044,7 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) else mindata = 65536; - if (dag_set_stream_poll(p->fd, p->md.dag_stream, + if (dag_set_stream_poll(p->fd, pd->dag_stream, mindata, &maxwait, &poll) < 0) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno)); return -1; @@ -1025,9 +1052,9 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) } #endif /* HAVE_DAG_STREAMS_API */ if (nonblock) { - p->md.dag_offset_flags |= DAGF_NONBLOCK; + pd->dag_offset_flags |= DAGF_NONBLOCK; } else { - p->md.dag_offset_flags &= ~DAGF_NONBLOCK; + pd->dag_offset_flags &= ~DAGF_NONBLOCK; } return (0); } @@ -1035,6 +1062,7 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) static int dag_get_datalink(pcap_t *p) { + struct pcap_dag *pd = p->private; int index=0, dlt_index=0; uint8_t types[255]; @@ -1049,7 +1077,7 @@ dag_get_datalink(pcap_t *p) #ifdef HAVE_DAG_GET_STREAM_ERF_TYPES /* Get list of possible ERF types for this card */ - if (dag_get_stream_erf_types(p->fd, p->md.dag_stream, types, 255) < 0) { + if (dag_get_stream_erf_types(p->fd, pd->dag_stream, types, 255) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_stream_erf_types: %s", pcap_strerror(errno)); return (-1); } diff --git a/pcap-dbus.c b/pcap-dbus.c index 40ace7f9..3a54d444 100644 --- a/pcap-dbus.c +++ b/pcap-dbus.c @@ -42,10 +42,18 @@ #include "pcap-int.h" #include "pcap-dbus.h" +/* + * Private data for capturing on D-Bus. + */ +struct pcap_dbus { + DBusConnection *conn; + u_int packets_read; /* count of packets read */ +}; + static int dbus_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { - DBusConnection *conn = handle->md.priv; + struct pcap_dbus *handlep = handle->private; struct pcap_pkthdr pkth; DBusMessage *message; @@ -55,11 +63,11 @@ dbus_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) int count = 0; - message = dbus_connection_pop_message(conn); + message = dbus_connection_pop_message(handlep->conn); while (!message) { - // XXX p->md.timeout = timeout_ms; - if (!dbus_connection_read_write(conn, 100)) { + // XXX handle->opt.timeout = timeout_ms; + if (!dbus_connection_read_write(handlep->conn, 100)) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Connection closed"); return -1; } @@ -69,7 +77,7 @@ dbus_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) return -2; } - message = dbus_connection_pop_message(conn); + message = dbus_connection_pop_message(handlep->conn); } if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) { @@ -84,7 +92,7 @@ dbus_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) gettimeofday(&pkth.ts, NULL); if (handle->fcode.bf_insns == NULL || bpf_filter(handle->fcode.bf_insns, (u_char *)raw_msg, pkth.len, pkth.caplen)) { - handle->md.packets_read++; + handlep->packets_read++; callback(user, &pkth, (u_char *)raw_msg); count++; } @@ -98,7 +106,7 @@ static int dbus_write(pcap_t *handle, const void *buf, size_t size) { /* XXX, not tested */ - DBusConnection *conn = handle->md.priv; + struct pcap_dbus *handlep = handle->private; DBusError error = DBUS_ERROR_INIT; DBusMessage *msg; @@ -109,8 +117,8 @@ dbus_write(pcap_t *handle, const void *buf, size_t size) return -1; } - dbus_connection_send(conn, msg, NULL); - dbus_connection_flush(conn); + dbus_connection_send(handlep->conn, msg, NULL); + dbus_connection_flush(handlep->conn); dbus_message_unref(msg); return 0; @@ -119,7 +127,9 @@ dbus_write(pcap_t *handle, const void *buf, size_t size) static int dbus_stats(pcap_t *handle, struct pcap_stat *stats) { - stats->ps_recv = handle->md.packets_read; + struct pcap_dbus *handlep = handle->private; + + stats->ps_recv = handlep->packets_read; stats->ps_drop = 0; stats->ps_ifdrop = 0; return 0; @@ -128,10 +138,9 @@ dbus_stats(pcap_t *handle, struct pcap_stat *stats) static void dbus_cleanup(pcap_t *handle) { - DBusConnection *conn = handle->md.priv; + struct pcap_dbus *handlep = handle->private; - handle->md.priv = NULL; - dbus_connection_unref(conn); + dbus_connection_unref(handlep->conn); pcap_cleanup_live_common(handle); } @@ -150,21 +159,21 @@ dbus_activate(pcap_t *handle) #define N_RULES sizeof(rules)/sizeof(rules[0]) + struct pcap_dbus *handlep = handle->private; const char *dev = handle->opt.source; DBusError error = DBUS_ERROR_INIT; - DBusConnection *conn; int i; if (strcmp(dev, "dbus-system") == 0) { - if (!(conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) { + if (!(handlep->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get system bus: %s", error.message); dbus_error_free(&error); return PCAP_ERROR; } } else if (strcmp(dev, "dbus-session") == 0) { - if (!(conn = dbus_bus_get(DBUS_BUS_SESSION, &error))) { + if (!(handlep->conn = dbus_bus_get(DBUS_BUS_SESSION, &error))) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get session bus: %s", error.message); dbus_error_free(&error); return PCAP_ERROR; @@ -173,13 +182,13 @@ dbus_activate(pcap_t *handle) } else if (strncmp(dev, "dbus://", 7) == 0) { const char *addr = dev + 7; - if (!(conn = dbus_connection_open(addr, &error))) { + if (!(handlep->conn = dbus_connection_open(addr, &error))) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to open connection to: %s: %s", addr, error.message); dbus_error_free(&error); return PCAP_ERROR; } - if (!dbus_bus_register(conn, &error)) { + if (!dbus_bus_register(handlep->conn, &error)) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to register bus %s: %s\n", addr, error.message); dbus_error_free(&error); return PCAP_ERROR; @@ -204,7 +213,6 @@ dbus_activate(pcap_t *handle) handle->stats_op = dbus_stats; handle->selectable_fd = handle->fd = -1; - handle->md.priv = conn; if (handle->opt.rfmon) { /* @@ -214,17 +222,17 @@ dbus_activate(pcap_t *handle) return PCAP_ERROR_RFMON_NOTSUP; } - /* dbus_connection_set_max_message_size(conn, handle->snapshot); */ + /* dbus_connection_set_max_message_size(handlep->conn, handle->snapshot); */ if (handle->opt.buffer_size != 0) - dbus_connection_set_max_received_size(conn, handle->opt.buffer_size); + dbus_connection_set_max_received_size(handlep->conn, handle->opt.buffer_size); for (i = 0; i < N_RULES; i++) { - dbus_bus_add_match(conn, rules[i], &error); + dbus_bus_add_match(handlep->conn, rules[i], &error); if (dbus_error_is_set(&error)) { dbus_error_free(&error); /* try without eavesdrop */ - dbus_bus_add_match(conn, rules[i] + strlen(EAVESDROPPING_RULE), &error); + dbus_bus_add_match(handlep->conn, rules[i] + strlen(EAVESDROPPING_RULE), &error); if (dbus_error_is_set(&error)) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to add bus match: %s\n", error.message); dbus_error_free(&error); @@ -251,7 +259,7 @@ dbus_create(const char *device, char *ebuf, int *is_ours) } *is_ours = 1; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_dbus)); if (p == NULL) return (NULL); @@ -264,9 +272,9 @@ dbus_findalldevs(pcap_if_t **alldevsp, char *err_str) { pcap_if_t *found_dev = *alldevsp; - if (pcap_add_if(&found_dev, "dbus-system", 0, "D-BUS system bus", err_str) < 0) + if (pcap_add_if(&found_dev, "dbus-system", 0, "D-Bus system bus", err_str) < 0) return -1; - if (pcap_add_if(&found_dev, "dbus-session", 0, "D-BUS session bus", err_str) < 0) + if (pcap_add_if(&found_dev, "dbus-session", 0, "D-Bus session bus", err_str) < 0) return -1; return 0; } diff --git a/pcap-dlpi.c b/pcap-dlpi.c index 4b285f39..323fbad9 100644 --- a/pcap-dlpi.c +++ b/pcap-dlpi.c @@ -245,6 +245,9 @@ pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user) static int pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size) { +#ifdef DL_HP_RAWDLS + struct pcap_dlpi *pd = p->private; +#endif int ret; #if defined(DLIOCRAW) @@ -255,12 +258,12 @@ pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size) return (-1); } #elif defined(DL_HP_RAWDLS) - if (p->send_fd < 0) { + if (pd->send_fd < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: Output FD couldn't be opened"); return (-1); } - ret = dlrawdatareq(p->send_fd, buf, size); + ret = dlrawdatareq(pd->send_fd, buf, size); if (ret == -1) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", pcap_strerror(errno)); @@ -321,16 +324,23 @@ pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size) static void pcap_cleanup_dlpi(pcap_t *p) { - if (p->send_fd >= 0) { - close(p->send_fd); - p->send_fd = -1; +#ifdef DL_HP_RAWDLS + struct pcap_dlpi *pd = p->private; + + if (pd->send_fd >= 0) { + close(pd->send_fd); + pd->send_fd = -1; } +#endif pcap_cleanup_live_common(p); } static int pcap_activate_dlpi(pcap_t *p) { +#ifdef DL_HP_RAWDLS + struct pcap_dlpi *pd = p->private; +#endif register char *cp; int ppa; #ifdef HAVE_SOLARIS @@ -398,13 +408,13 @@ pcap_activate_dlpi(pcap_t *p) * receiving packets on the same descriptor - you need separate * descriptors for sending and receiving, bound to different SAPs. * - * If the open fails, we just leave -1 in "p->send_fd" and reject + * If the open fails, we just leave -1 in "pd->send_fd" and reject * attempts to send packets, just as if, in pcap-bpf.c, we fail * to open the BPF device for reading and writing, we just try * to open it for reading only and, if that succeeds, just let * the send attempts fail. */ - p->send_fd = open(cp, O_RDWR); + pd->send_fd = open(cp, O_RDWR); #endif /* @@ -513,8 +523,8 @@ pcap_activate_dlpi(pcap_t *p) if (status < 0) goto bad; #ifdef DL_HP_RAWDLS - if (p->send_fd >= 0) { - if (dl_doattach(p->send_fd, ppa, p->errbuf) < 0) + if (pd->send_fd >= 0) { + if (dl_doattach(pd->send_fd, ppa, p->errbuf) < 0) goto bad; } #endif @@ -570,13 +580,13 @@ pcap_activate_dlpi(pcap_t *p) */ if (dl_dohpuxbind(p->fd, p->errbuf) < 0) goto bad; - if (p->send_fd >= 0) { + if (pd->send_fd >= 0) { /* ** XXX - if this fails, just close send_fd and ** set it to -1, so that you can't send but can ** still receive? */ - if (dl_dohpuxbind(p->send_fd, p->errbuf) < 0) + if (dl_dohpuxbind(pd->send_fd, p->errbuf) < 0) goto bad; } #else /* neither AIX nor HP-UX */ @@ -669,13 +679,13 @@ pcap_activate_dlpi(pcap_t *p) ** binding it anyway, just to keep the HP-UX 9/10.20 or later ** code together. */ - if (p->send_fd >= 0) { + if (pd->send_fd >= 0) { /* ** XXX - if this fails, just close send_fd and ** set it to -1, so that you can't send but can ** still receive? */ - if (dl_dohpuxbind(p->send_fd, p->errbuf) < 0) + if (dl_dohpuxbind(pd->send_fd, p->errbuf) < 0) goto bad; } #endif @@ -729,7 +739,7 @@ pcap_activate_dlpi(pcap_t *p) #endif /* Push and configure bufmod. */ - if (pcap_conf_bufmod(p, ss, p->md.timeout) != 0) + if (pcap_conf_bufmod(p, ss, p->opt.timeout) != 0) goto bad; #endif @@ -1696,12 +1706,18 @@ pcap_t * pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; +#ifdef DL_HP_RAWDLS + struct pcap_dlpi *pd; +#endif - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_dlpi)); if (p == NULL) return (NULL); - p->send_fd = -1; /* it hasn't been opened yet */ +#ifdef DL_HP_RAWDLS + pd = p->private; + pd->send_fd = -1; /* it hasn't been opened yet */ +#endif p->activate_op = pcap_activate_dlpi; return (p); diff --git a/pcap-dos.c b/pcap-dos.c index 72e8fdec..3c24758e 100644 --- a/pcap-dos.c +++ b/pcap-dos.c @@ -143,11 +143,19 @@ static struct device *get_device (int fd) return handle_to_device [fd-1]; } +/* + * Private data for capturing on MS-DOS. + */ +struct pcap_dos { + void (*wait_proc)(void); /* call proc while waiting */ + struct pcap_stat stat; +}; + pcap_t *pcap_create_interface (const char *device, char *ebuf) { pcap_t *p; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_dos)); if (p == NULL) return (NULL); @@ -161,6 +169,8 @@ pcap_t *pcap_create_interface (const char *device, char *ebuf) */ static int pcap_activate_dos (pcap_t *pcap) { + struct pcap_dos *pcapd = pcap->private; + if (pcap->opt.rfmon) { /* * No monitor mode on DOS. @@ -210,15 +220,16 @@ static int pcap_activate_dos (pcap_t *pcap) static int pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data) { + struct pcap_dos *pd = p->private; struct pcap_pkthdr pcap; struct timeval now, expiry = { 0,0 }; BYTE *rx_buf; int rx_len = 0; - if (p->md.timeout > 0) + if (p->opt.timeout > 0) { gettimeofday2 (&now, NULL); - expiry.tv_usec = now.tv_usec + 1000UL * p->md.timeout; + expiry.tv_usec = now.tv_usec + 1000UL * p->opt.timeout; expiry.tv_sec = now.tv_sec; while (expiry.tv_usec >= 1000000L) { @@ -290,7 +301,7 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data) /* If not to wait for a packet or pcap_cleanup_dos() called from * e.g. SIGINT handler, exit loop now. */ - if (p->md.timeout <= 0 || (volatile int)p->fd <= 0) + if (p->opt.timeout <= 0 || (volatile int)p->fd <= 0) break; gettimeofday2 (&now, NULL); @@ -308,7 +319,7 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data) if (rx_len < 0) /* receive error */ { - p->md.stat.ps_drop++; + pd->stat.ps_drop++; #ifdef USE_32BIT_DRIVERS if (pcap_pkt_debug > 1) printk ("pkt-err %s\n", pktInfo.error); @@ -321,6 +332,7 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data) static int pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data) { + struct pcap_dos *pd = p->private; int rc, num = 0; while (num <= cnt || (cnt < 0)) @@ -343,6 +355,7 @@ pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data) static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps) { struct net_device_stats *stats; + struct pcap_dos *pd; struct device *dev = p ? get_device(p->fd) : NULL; if (!dev) @@ -359,12 +372,13 @@ static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps) FLUSHK(); - p->md.stat.ps_recv = stats->rx_packets; - p->md.stat.ps_drop += stats->rx_missed_errors; - p->md.stat.ps_ifdrop = stats->rx_dropped + /* queue full */ + pd = p->private; + pd->stat.ps_recv = stats->rx_packets; + pd->stat.ps_drop += stats->rx_missed_errors; + pd->stat.ps_ifdrop = stats->rx_dropped + /* queue full */ stats->rx_errors; /* HW errors */ if (ps) - *ps = p->md.stat; + *ps = pd->stat; return (0); } @@ -428,10 +442,13 @@ u_long pcap_filter_packets (void) */ static void pcap_cleanup_dos (pcap_t *p) { + struct pcap_dos *pd; + if (p && !exc_occured) { + pd = p->private; if (pcap_stats(p,NULL) < 0) - p->md.stat.ps_drop = 0; + pd->stat.ps_drop = 0; if (!get_device(p->fd)) return; @@ -590,10 +607,12 @@ void pcap_assert (const char *what, const char *file, unsigned line) */ void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait) { + struct pcap_dos *pd; if (p) { - p->wait_proc = yield; - p->md.timeout = wait; + pd = p->private; + pd->wait_proc = yield; + p->opt.timeout = wait; } } diff --git a/pcap-int.h b/pcap-int.h index 28b80fb4..3527ca34 100644 --- a/pcap-int.h +++ b/pcap-int.h @@ -42,10 +42,6 @@ extern "C" { #endif -#ifdef HAVE_LIBDLPI -#include -#endif - #ifdef WIN32 #include extern CRITICAL_SECTION g_PcapCompileCriticalSection; @@ -56,10 +52,6 @@ extern CRITICAL_SECTION g_PcapCompileCriticalSection; #include #endif -#ifdef HAVE_SNF_API -#include -#endif - #if (defined(_MSC_VER) && (_MSC_VER <= 1200)) /* we are compiling with Visual Studio 6, that doesn't support the LL suffix*/ /* @@ -92,124 +84,8 @@ extern CRITICAL_SECTION g_PcapCompileCriticalSection; #endif /* _MSC_VER */ -/* - * Savefile - */ -typedef enum { - NOT_SWAPPED, - SWAPPED, - MAYBE_SWAPPED -} swapped_type_t; - -/* - * Used when reading a savefile. - */ -struct pcap_sf { - FILE *rfile; - int (*next_packet_op)(pcap_t *, struct pcap_pkthdr *, u_char **); - int swapped; - size_t hdrsize; - swapped_type_t lengths_swapped; - int version_major; - int version_minor; - bpf_u_int32 ifcount; /* number of interfaces seen in this capture */ - u_int tsresol; /* time stamp resolution */ - u_int tsscale; /* scaling factor for resolution -> microseconds */ - u_int64_t tsoffset; /* time stamp offset */ -}; - -/* - * Used when doing a live capture. - */ -struct pcap_md { - struct pcap_stat stat; - /*XXX*/ - int use_bpf; /* using kernel filter */ - u_long TotPkts; /* can't oflow for 79 hrs on ether */ - u_long TotAccepted; /* count accepted by filter */ - u_long TotDrops; /* count of dropped packets */ - long TotMissed; /* missed by i/f during this run */ - long OrigMissed; /* missed by i/f before this run */ - char *device; /* device name */ - int timeout; /* timeout for buffering */ - int must_do_on_close; /* stuff we must do when we close */ - struct pcap *next; /* list of open pcaps that need stuff cleared on close */ -#if defined(linux) || defined(PCAP_SUPPORT_DBUS) - u_int packets_read; /* count of packets read with recvfrom() */ -#endif -#ifdef linux - int sock_packet; /* using Linux 2.0 compatible interface */ - int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */ - int ifindex; /* interface index of device we're bound to */ - int lo_ifindex; /* interface index of the loopback device */ - bpf_u_int32 oldmode; /* mode to restore when turning monitor mode off */ - char *mondevice; /* mac80211 monitor device we created */ - u_char *mmapbuf; /* memory-mapped region pointer */ - size_t mmapbuflen; /* size of region */ - int vlan_offset; /* offset at which to insert vlan tags; if -1, don't insert */ - u_int tp_version; /* version of tpacket_hdr for mmaped ring */ - u_int tp_hdrlen; /* hdrlen of tpacket_hdr for mmaped ring */ - u_char *oneshot_buffer; /* buffer for copy of packet */ - long proc_dropped; /* packets reported dropped by /proc/net/dev */ -#endif /* linux */ - -#ifdef HAVE_DAG_API -#ifdef HAVE_DAG_STREAMS_API - u_char *dag_mem_bottom; /* DAG card current memory bottom pointer */ - u_char *dag_mem_top; /* DAG card current memory top pointer */ -#else /* HAVE_DAG_STREAMS_API */ - void *dag_mem_base; /* DAG card memory base address */ - u_int dag_mem_bottom; /* DAG card current memory bottom offset */ - u_int dag_mem_top; /* DAG card current memory top offset */ -#endif /* HAVE_DAG_STREAMS_API */ - int dag_fcs_bits; /* Number of checksum bits from link layer */ - int dag_offset_flags; /* Flags to pass to dag_offset(). */ - int dag_stream; /* DAG stream number */ - int dag_timeout; /* timeout specified to pcap_open_live. - * Same as in linux above, introduce - * generally? */ -#endif /* HAVE_DAG_API */ -#ifdef HAVE_SNF_API - snf_handle_t snf_handle; /* opaque device handle */ - snf_ring_t snf_ring; /* opaque device ring handle */ - int snf_timeout; - int snf_boardnum; -#endif /*HAVE_SNF_API*/ - -#ifdef HAVE_ZEROCOPY_BPF - /* - * Zero-copy read buffer -- for zero-copy BPF. 'buffer' above will - * alternative between these two actual mmap'd buffers as required. - * As there is a header on the front size of the mmap'd buffer, only - * some of the buffer is exposed to libpcap as a whole via bufsize; - * zbufsize is the true size. zbuffer tracks the current zbuf - * assocated with buffer so that it can be used to decide which the - * next buffer to read will be. - */ - u_char *zbuf1, *zbuf2, *zbuffer; - u_int zbufsize; - u_int zerocopy; - u_int interrupted; - struct timespec firstsel; - /* - * If there's currently a buffer being actively processed, then it is - * referenced here; 'buffer' is also pointed at it, but offset by the - * size of the header. - */ - struct bpf_zbuf_header *bzh; -#endif /* HAVE_ZEROCOPY_BPF */ - - void *priv; -}; - -/* - * Stuff to do when we close. - */ -#define MUST_CLEAR_PROMISC 0x00000001 /* clear promiscuous mode */ -#define MUST_CLEAR_RFMON 0x00000002 /* clear rfmon (monitor) mode */ -#define MUST_DELETE_MONIF 0x00000004 /* delete monitor-mode interface */ - struct pcap_opt { + int timeout; /* timeout for buffering */ int buffer_size; char *source; int promisc; @@ -217,19 +93,6 @@ struct pcap_opt { int tstamp_type; }; -/* - * Ultrix, DEC OSF/1^H^H^H^H^H^H^H^H^HDigital UNIX^H^H^H^H^H^H^H^H^H^H^H^H - * Tru64 UNIX, and some versions of NetBSD pad FDDI packets to make everything - * line up on a nice boundary. - */ -#ifdef __NetBSD__ -#include /* needed to declare __NetBSD_Version__ */ -#endif - -#if defined(ultrix) || defined(__osf__) || (defined(__NetBSD__) && __NetBSD_Version__ > 106000000) -#define PCAP_FDDIPAD 3 -#endif - typedef int (*activate_op_t)(pcap_t *); typedef int (*can_set_rfmon_op_t)(pcap_t *); typedef int (*read_op_t)(pcap_t *, int cnt, pcap_handler, u_char *); @@ -247,7 +110,21 @@ typedef int (*setmintocopy_op_t)(pcap_t *, int); #endif typedef void (*cleanup_op_t)(pcap_t *); +/* + * We put all the stuff used in the read code path at the beginning, + * to try to keep it together in the same cache line or lines. + */ struct pcap { + /* + * Method to call to read packets on a live capture. + */ + read_op_t read_op; + + /* + * Method to call to read to read packets from a savefile. + */ + int (*next_packet_op)(pcap_t *, struct pcap_pkthdr *, u_char **); + #ifdef WIN32 ADAPTER *adapter; LPPACKET Packet; @@ -255,12 +132,34 @@ struct pcap { #else int fd; int selectable_fd; - int send_fd; #endif /* WIN32 */ -#ifdef HAVE_LIBDLPI - dlpi_handle_t dlpi_hd; -#endif + /* + * Read buffer. + */ + int bufsize; + u_char *buffer; + u_char *bp; + int cc; + + int break_loop; /* flag set to force break from packet-reading loop */ + + void *private; /* private data for methods */ + + int swapped; + FILE *rfile; /* null if live capture, non-null if savefile */ + int fddipad; + struct pcap *next; /* list of open pcaps that need stuff cleared on close */ + + /* + * File version number; meaningful only for a savefile, but we + * keep it here so that apps that (mistakenly) ask for the + * version numbers will get the same zero values that they + * always did. + */ + int version_major; + int version_minor; + int snapshot; int linktype; /* Network linktype */ int linktype_ext; /* Extended information stored in the linktype field of a file */ @@ -269,28 +168,8 @@ struct pcap { int activated; /* true if the capture is really started */ int oldstyle; /* if we're opening with pcap_open_live() */ - int break_loop; /* flag set to force break from packet-reading loop */ - -#ifdef PCAP_FDDIPAD - int fddipad; -#endif - -#ifdef MSDOS - void (*wait_proc)(void); /* call proc while waiting */ -#endif - - struct pcap_sf sf; - struct pcap_md md; struct pcap_opt opt; - /* - * Read buffer. - */ - int bufsize; - u_char *buffer; - u_char *bp; - int cc; - /* * Place holder for pcap_next(). */ @@ -300,11 +179,23 @@ struct pcap { pcap_direction_t direction; /* - * Methods. + * Placeholder for filter code if bpf not in kernel. + */ + struct bpf_program fcode; + + char errbuf[PCAP_ERRBUF_SIZE + 1]; + int dlt_count; + u_int *dlt_list; + int tstamp_type_count; + u_int *tstamp_type_list; + + struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */ + + /* + * More methods. */ activate_op_t activate_op; can_set_rfmon_op_t can_set_rfmon_op; - read_op_t read_op; inject_op_t inject_op; setfilter_op_t setfilter_op; setdirection_op_t setdirection_op; @@ -328,19 +219,6 @@ struct pcap { setmintocopy_op_t setmintocopy_op; #endif cleanup_op_t cleanup_op; - - /* - * Placeholder for filter code if bpf not in kernel. - */ - struct bpf_program fcode; - - char errbuf[PCAP_ERRBUF_SIZE + 1]; - int dlt_count; - u_int *dlt_list; - int tstamp_type_count; - u_int *tstamp_type_list; - - struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */ }; /* @@ -472,7 +350,7 @@ int pcap_setnonblock_fd(pcap_t *p, int, char *); * by pcap_create routines. */ pcap_t *pcap_create_interface(const char *, char *); -pcap_t *pcap_create_common(const char *, char *); +pcap_t *pcap_create_common(const char *, char *, size_t); int pcap_do_addexit(pcap_t *); void pcap_add_to_pcaps_to_close(pcap_t *); void pcap_remove_from_pcaps_to_close(pcap_t *); @@ -502,6 +380,14 @@ struct sockaddr *dup_sockaddr(struct sockaddr *, size_t); int add_or_find_if(pcap_if_t **, pcap_if_t **, const char *, u_int, const char *, char *); +/* + * Internal interfaces for "pcap_open_offline()". + * + * "pcap_open_offline_common()" allocates and fills in a pcap_t, for use + * by pcap_open_offline routines. + */ +pcap_t *pcap_open_offline_common(char *ebuf, size_t size); + #ifdef WIN32 char *pcap_win32strerror(void); #endif diff --git a/pcap-libdlpi.c b/pcap-libdlpi.c index acaa400d..351e9846 100644 --- a/pcap-libdlpi.c +++ b/pcap-libdlpi.c @@ -100,6 +100,7 @@ list_interfaces(const char *linkname, void *arg) static int pcap_activate_libdlpi(pcap_t *p) { + struct pcap_dlpi *pd = p->private; int retv; dlpi_handle_t dh; dlpi_info_t dlinfo; @@ -121,7 +122,7 @@ pcap_activate_libdlpi(pcap_t *p) p->errbuf); return (err); } - p->dlpi_hd = dh; + pd->dlpi_hd = dh; if (p->opt.rfmon) { /* @@ -133,7 +134,7 @@ pcap_activate_libdlpi(pcap_t *p) } /* Bind with DLPI_ANY_SAP. */ - if ((retv = dlpi_bind(p->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) { + if ((retv = dlpi_bind(pd->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) { pcap_libdlpi_err(p->opt.source, "dlpi_bind", retv, p->errbuf); goto bad; } @@ -180,7 +181,7 @@ pcap_activate_libdlpi(pcap_t *p) } /* Determine link type. */ - if ((retv = dlpi_info(p->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) { + if ((retv = dlpi_info(pd->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) { pcap_libdlpi_err(p->opt.source, "dlpi_info", retv, p->errbuf); goto bad; } @@ -188,10 +189,10 @@ pcap_activate_libdlpi(pcap_t *p) if (pcap_process_mactype(p, dlinfo.di_mactype) != 0) goto bad; - p->fd = dlpi_fd(p->dlpi_hd); + p->fd = dlpi_fd(pd->dlpi_hd); /* Push and configure bufmod. */ - if (pcap_conf_bufmod(p, p->snapshot, p->md.timeout) != 0) + if (pcap_conf_bufmod(p, p->snapshot, p->opt.timeout) != 0) goto bad; /* @@ -234,10 +235,11 @@ bad: static int dlpromiscon(pcap_t *p, bpf_u_int32 level) { + struct pcap_dlpi *pd = p->private; int retv; int err; - retv = dlpi_promiscon(p->dlpi_hd, level); + retv = dlpi_promiscon(pd->dlpi_hd, level); if (retv != DLPI_SUCCESS) { if (retv == DL_SYSERR && (errno == EPERM || errno == EACCES)) @@ -299,6 +301,7 @@ done: static int pcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user) { + struct pcap_dlpi *pd = p->private; int len; u_char *bufp; size_t msglen; @@ -324,7 +327,7 @@ pcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user) msglen = p->bufsize; bufp = p->buffer + p->offset; - retv = dlpi_recv(p->dlpi_hd, NULL, NULL, bufp, + retv = dlpi_recv(pd->dlpi_hd, NULL, NULL, bufp, &msglen, -1, NULL); if (retv != DLPI_SUCCESS) { /* @@ -336,7 +339,7 @@ pcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user) len = 0; continue; } - pcap_libdlpi_err(dlpi_linkname(p->dlpi_hd), + pcap_libdlpi_err(dlpi_linkname(pd->dlpi_hd), "dlpi_recv", retv, p->errbuf); return (-1); } @@ -350,11 +353,12 @@ process_pkts: static int pcap_inject_libdlpi(pcap_t *p, const void *buf, size_t size) { + struct pcap_dlpi *pd = p->private; int retv; - retv = dlpi_send(p->dlpi_hd, NULL, 0, buf, size, NULL); + retv = dlpi_send(pd->dlpi_hd, NULL, 0, buf, size, NULL); if (retv != DLPI_SUCCESS) { - pcap_libdlpi_err(dlpi_linkname(p->dlpi_hd), "dlpi_send", retv, + pcap_libdlpi_err(dlpi_linkname(pd->dlpi_hd), "dlpi_send", retv, p->errbuf); return (-1); } @@ -372,9 +376,11 @@ pcap_inject_libdlpi(pcap_t *p, const void *buf, size_t size) static void pcap_cleanup_libdlpi(pcap_t *p) { - if (p->dlpi_hd != NULL) { - dlpi_close(p->dlpi_hd); - p->dlpi_hd = NULL; + struct pcap_dlpi *pd = p->private; + + if (pd->dlpi_hd != NULL) { + dlpi_close(pd->dlpi_hd); + pd->dlpi_hd = NULL; p->fd = -1; } pcap_cleanup_live_common(p); @@ -395,7 +401,7 @@ pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_dlpi)); if (p == NULL) return (NULL); diff --git a/pcap-linux.c b/pcap-linux.c index 201f2aad..e49af804 100644 --- a/pcap-linux.c +++ b/pcap-linux.c @@ -283,6 +283,39 @@ typedef int socklen_t; */ #define BIGGER_THAN_ALL_MTUS (64*1024) +/* + * Private data for capturing on Linux SOCK_PACKET or PF_PACKET sockets. + */ +struct pcap_linux { + u_int packets_read; /* count of packets read with recvfrom() */ + long proc_dropped; /* packets reported dropped by /proc/net/dev */ + struct pcap_stat stat; + + char *device; /* device name */ + int filtering_in_kernel; /* using kernel filter */ + int must_do_on_close; /* stuff we must do when we close */ + int timeout; /* timeout for buffering */ + int sock_packet; /* using Linux 2.0 compatible interface */ + int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */ + int ifindex; /* interface index of device we're bound to */ + int lo_ifindex; /* interface index of the loopback device */ + bpf_u_int32 oldmode; /* mode to restore when turning monitor mode off */ + char *mondevice; /* mac80211 monitor device we created */ + u_char *mmapbuf; /* memory-mapped region pointer */ + size_t mmapbuflen; /* size of region */ + int vlan_offset; /* offset at which to insert vlan tags; if -1, don't insert */ + u_int tp_version; /* version of tpacket_hdr for mmaped ring */ + u_int tp_hdrlen; /* hdrlen of tpacket_hdr for mmaped ring */ + u_char *oneshot_buffer; /* buffer for copy of packet */ +}; + +/* + * Stuff to do when we close. + */ +#define MUST_CLEAR_PROMISC 0x00000001 /* clear promiscuous mode */ +#define MUST_CLEAR_RFMON 0x00000002 /* clear rfmon (monitor) mode */ +#define MUST_DELETE_MONIF 0x00000004 /* delete monitor-mode interface */ + /* * Prototypes for internal functions and methods. */ @@ -362,7 +395,7 @@ pcap_create_interface(const char *device, char *ebuf) { pcap_t *handle; - handle = pcap_create_common(device, ebuf); + handle = pcap_create_common(device, ebuf, sizeof (struct pcap_linux)); if (handle == NULL) return NULL; @@ -721,6 +754,7 @@ nla_put_failure: static int enter_rfmon_mode_mac80211(pcap_t *handle, int sock_fd, const char *device) { + struct pcap_linux *handlep = handle->private; int ret; char phydev_path[PATH_MAX+1]; struct nl80211_state nlstate; @@ -758,7 +792,7 @@ enter_rfmon_mode_mac80211(pcap_t *handle, int sock_fd, const char *device) snprintf(mondevice, sizeof mondevice, "mon%u", n); ret = add_mon_if(handle, sock_fd, &nlstate, device, mondevice); if (ret == 1) { - handle->md.mondevice = strdup(mondevice); + handlep->mondevice = strdup(mondevice); goto added; } if (ret < 0) { @@ -803,13 +837,13 @@ added: * Now configure the monitor interface up. */ memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, handle->md.mondevice, sizeof(ifr.ifr_name)); + strncpy(ifr.ifr_name, handlep->mondevice, sizeof(ifr.ifr_name)); if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: Can't get flags for %s: %s", device, - handle->md.mondevice, strerror(errno)); + handlep->mondevice, strerror(errno)); del_mon_if(handle, sock_fd, &nlstate, device, - handle->md.mondevice); + handlep->mondevice); nl80211_cleanup(&nlstate); return PCAP_ERROR; } @@ -817,9 +851,9 @@ added: if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "%s: Can't set flags for %s: %s", device, - handle->md.mondevice, strerror(errno)); + handlep->mondevice, strerror(errno)); del_mon_if(handle, sock_fd, &nlstate, device, - handle->md.mondevice); + handlep->mondevice); nl80211_cleanup(&nlstate); return PCAP_ERROR; } @@ -833,7 +867,7 @@ added: * Note that we have to delete the monitor device when we close * the handle. */ - handle->md.must_do_on_close |= MUST_DELETE_MONIF; + handlep->must_do_on_close |= MUST_DELETE_MONIF; /* * Add this to the list of pcaps to close when we exit. @@ -1002,6 +1036,7 @@ linux_if_drops(const char * if_name) static void pcap_cleanup_linux( pcap_t *handle ) { + struct pcap_linux *handlep = handle->private; struct ifreq ifr; #ifdef HAVE_LIBNL struct nl80211_state nlstate; @@ -1012,12 +1047,12 @@ static void pcap_cleanup_linux( pcap_t *handle ) struct iwreq ireq; #endif /* IW_MODE_MONITOR */ - if (handle->md.must_do_on_close != 0) { + if (handlep->must_do_on_close != 0) { /* * There's something we have to do when closing this * pcap_t. */ - if (handle->md.must_do_on_close & MUST_CLEAR_PROMISC) { + if (handlep->must_do_on_close & MUST_CLEAR_PROMISC) { /* * We put the interface into promiscuous mode; * take it out of promiscuous mode. @@ -1028,14 +1063,14 @@ static void pcap_cleanup_linux( pcap_t *handle ) * in 2.0[.x] kernels. */ memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, handle->md.device, + strncpy(ifr.ifr_name, handlep->device, sizeof(ifr.ifr_name)); if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) { fprintf(stderr, "Can't restore interface %s flags (SIOCGIFFLAGS failed: %s).\n" "Please adjust manually.\n" "Hint: This can't happen with Linux >= 2.2.0.\n", - handle->md.device, strerror(errno)); + handlep->device, strerror(errno)); } else { if (ifr.ifr_flags & IFF_PROMISC) { /* @@ -1049,7 +1084,7 @@ static void pcap_cleanup_linux( pcap_t *handle ) "Can't restore interface %s flags (SIOCSIFFLAGS failed: %s).\n" "Please adjust manually.\n" "Hint: This can't happen with Linux >= 2.2.0.\n", - handle->md.device, + handlep->device, strerror(errno)); } } @@ -1057,24 +1092,24 @@ static void pcap_cleanup_linux( pcap_t *handle ) } #ifdef HAVE_LIBNL - if (handle->md.must_do_on_close & MUST_DELETE_MONIF) { - ret = nl80211_init(handle, &nlstate, handle->md.device); + if (handlep->must_do_on_close & MUST_DELETE_MONIF) { + ret = nl80211_init(handle, &nlstate, handlep->device); if (ret >= 0) { ret = del_mon_if(handle, handle->fd, &nlstate, - handle->md.device, handle->md.mondevice); + handlep->device, handlep->mondevice); nl80211_cleanup(&nlstate); } if (ret < 0) { fprintf(stderr, "Can't delete monitor interface %s (%s).\n" "Please delete manually.\n", - handle->md.mondevice, handle->errbuf); + handlep->mondevice, handle->errbuf); } } #endif /* HAVE_LIBNL */ #ifdef IW_MODE_MONITOR - if (handle->md.must_do_on_close & MUST_CLEAR_RFMON) { + if (handlep->must_do_on_close & MUST_CLEAR_RFMON) { /* * We put the interface into rfmon mode; * take it out of rfmon mode. @@ -1092,7 +1127,7 @@ static void pcap_cleanup_linux( pcap_t *handle ) */ oldflags = 0; memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, handle->md.device, + strncpy(ifr.ifr_name, handlep->device, sizeof(ifr.ifr_name)); if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) != -1) { if (ifr.ifr_flags & IFF_UP) { @@ -1106,11 +1141,11 @@ static void pcap_cleanup_linux( pcap_t *handle ) /* * Now restore the mode. */ - strncpy(ireq.ifr_ifrn.ifrn_name, handle->md.device, + strncpy(ireq.ifr_ifrn.ifrn_name, handlep->device, sizeof ireq.ifr_ifrn.ifrn_name); ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0; - ireq.u.mode = handle->md.oldmode; + ireq.u.mode = handlep->oldmode; if (ioctl(handle->fd, SIOCSIWMODE, &ireq) == -1) { /* * Scientist, you've failed. @@ -1118,7 +1153,7 @@ static void pcap_cleanup_linux( pcap_t *handle ) fprintf(stderr, "Can't restore interface %s wireless mode (SIOCSIWMODE failed: %s).\n" "Please adjust manually.\n", - handle->md.device, strerror(errno)); + handlep->device, strerror(errno)); } /* @@ -1131,7 +1166,7 @@ static void pcap_cleanup_linux( pcap_t *handle ) fprintf(stderr, "Can't bring interface %s back up (SIOCSIFFLAGS failed: %s).\n" "Please adjust manually.\n", - handle->md.device, strerror(errno)); + handlep->device, strerror(errno)); } } } @@ -1144,13 +1179,13 @@ static void pcap_cleanup_linux( pcap_t *handle ) pcap_remove_from_pcaps_to_close(handle); } - if (handle->md.mondevice != NULL) { - free(handle->md.mondevice); - handle->md.mondevice = NULL; + if (handlep->mondevice != NULL) { + free(handlep->mondevice); + handlep->mondevice = NULL; } - if (handle->md.device != NULL) { - free(handle->md.device); - handle->md.device = NULL; + if (handlep->device != NULL) { + free(handlep->device); + handlep->device = NULL; } pcap_cleanup_live_common(handle); } @@ -1166,6 +1201,7 @@ static void pcap_cleanup_linux( pcap_t *handle ) static int pcap_activate_linux(pcap_t *handle) { + struct pcap_linux *handlep = handle->private; const char *device; int status = 0; @@ -1196,20 +1232,23 @@ pcap_activate_linux(pcap_t *handle) } } - handle->md.device = strdup(device); - if (handle->md.device == NULL) { + handlep->device = strdup(device); + if (handlep->device == NULL) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s", pcap_strerror(errno) ); return PCAP_ERROR; } + /* copy timeout value */ + handlep->timeout = handle->opt.timeout; + /* * If we're in promiscuous mode, then we probably want * to see when the interface drops packets too, so get an * initial count from /proc/net/dev */ if (handle->opt.promisc) - handle->md.proc_dropped = linux_if_drops(handle->md.device); + handlep->proc_dropped = linux_if_drops(handlep->device); /* * Current Linux kernels use the protocol family PF_PACKET to @@ -1346,6 +1385,7 @@ pcap_set_datalink_linux(pcap_t *handle, int dlt) static int pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) { + struct pcap_linux *handlep = handle->private; u_char *bp; int offset; #ifdef HAVE_PF_PACKET_SOCKETS @@ -1373,7 +1413,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) * If this is a cooked device, leave extra room for a * fake packet header. */ - if (handle->md.cooked) + if (handlep->cooked) offset = SLL_HDR_LEN; else offset = 0; @@ -1468,7 +1508,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) } #ifdef HAVE_PF_PACKET_SOCKETS - if (!handle->md.sock_packet) { + if (!handlep->sock_packet) { /* * Unfortunately, there is a window between socket() and * bind() where the kernel may queue packets from any @@ -1481,8 +1521,8 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) * filter support, and it's a bit more complicated. * It would save some instructions per packet, however.) */ - if (handle->md.ifindex != -1 && - from.sll_ifindex != handle->md.ifindex) + if (handlep->ifindex != -1 && + from.sll_ifindex != handlep->ifindex) return 0; /* @@ -1498,7 +1538,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) * we'll see the packet as an incoming packet as well, * and we don't want to see it twice. */ - if (from.sll_ifindex == handle->md.lo_ifindex) + if (from.sll_ifindex == handlep->lo_ifindex) return 0; /* @@ -1521,7 +1561,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) /* * If this is a cooked device, fill in the fake packet header. */ - if (handle->md.cooked) { + if (handlep->cooked) { /* * Add the length of the fake header to the length * of packet data we read. @@ -1540,7 +1580,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) } #if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) - if (handle->md.vlan_offset != -1) { + if (handlep->vlan_offset != -1) { for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { struct tpacket_auxdata *aux; unsigned int len; @@ -1562,13 +1602,13 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) continue; len = packet_len > iov.iov_len ? iov.iov_len : packet_len; - if (len < (unsigned int) handle->md.vlan_offset) + if (len < (unsigned int) handlep->vlan_offset) break; bp -= VLAN_TAG_LEN; - memmove(bp, bp + VLAN_TAG_LEN, handle->md.vlan_offset); + memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset); - tag = (struct vlan_tag *)(bp + handle->md.vlan_offset); + tag = (struct vlan_tag *)(bp + handlep->vlan_offset); tag->vlan_tpid = htons(ETH_P_8021Q); tag->vlan_tci = htons(aux->tp_vlan_tci); @@ -1615,7 +1655,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) caplen = handle->snapshot; /* Run the packet filter if not using kernel filter */ - if (!handle->md.use_bpf && handle->fcode.bf_insns) { + if (!handlep->filtering_in_kernel && handle->fcode.bf_insns) { if (bpf_filter(handle->fcode.bf_insns, bp, packet_len, caplen) == 0) { @@ -1667,17 +1707,18 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) * the count is more expensive than always testing a flag * in memory. * - * We keep the count in "md.packets_read", and use that for - * "ps_recv" if we can't get the statistics from the kernel. + * We keep the count in "handlep->packets_read", and use that + * for "ps_recv" if we can't get the statistics from the kernel. * We do that because, if we *can* get the statistics from - * the kernel, we use "md.stat.ps_recv" and "md.stat.ps_drop" - * as running counts, as reading the statistics from the - * kernel resets the kernel statistics, and if we directly - * increment "md.stat.ps_recv" here, that means it will - * count packets *twice* on systems where we can get kernel - * statistics - once here, and once in pcap_stats_linux(). + * the kernel, we use "handlep->stat.ps_recv" and + * "handlep->stat.ps_drop" as running counts, as reading the + * statistics from the kernel resets the kernel statistics, + * and if we directly increment "handlep->stat.ps_recv" here, + * that means it will count packets *twice* on systems where + * we can get kernel statistics - once here, and once in + * pcap_stats_linux(). */ - handle->md.packets_read++; + handlep->packets_read++; /* Call the user supplied callback function */ callback(userdata, &pcap_header, bp); @@ -1688,12 +1729,13 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) static int pcap_inject_linux(pcap_t *handle, const void *buf, size_t size) { + struct pcap_linux *handlep = handle->private; int ret; #ifdef HAVE_PF_PACKET_SOCKETS - if (!handle->md.sock_packet) { + if (!handlep->sock_packet) { /* PF_PACKET socket */ - if (handle->md.ifindex == -1) { + if (handlep->ifindex == -1) { /* * We don't support sending on the "any" device. */ @@ -1703,7 +1745,7 @@ pcap_inject_linux(pcap_t *handle, const void *buf, size_t size) return (-1); } - if (handle->md.cooked) { + if (handlep->cooked) { /* * We don't support sending on the "any" device. * @@ -1739,6 +1781,7 @@ pcap_inject_linux(pcap_t *handle, const void *buf, size_t size) static int pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats) { + struct pcap_linux *handlep = handle->private; #ifdef HAVE_TPACKET_STATS struct tpacket_stats kstats; socklen_t len = sizeof (struct tpacket_stats); @@ -1751,9 +1794,9 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats) */ if (handle->opt.promisc) { - if_dropped = handle->md.proc_dropped; - handle->md.proc_dropped = linux_if_drops(handle->md.device); - handle->md.stat.ps_ifdrop += (handle->md.proc_dropped - if_dropped); + if_dropped = handlep->proc_dropped; + handlep->proc_dropped = linux_if_drops(handlep->device); + handlep->stat.ps_ifdrop += (handlep->proc_dropped - if_dropped); } #ifdef HAVE_TPACKET_STATS @@ -1809,9 +1852,9 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats) * getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS, .... * resets the counters to zero. */ - handle->md.stat.ps_recv += kstats.tp_packets; - handle->md.stat.ps_drop += kstats.tp_drops; - *stats = handle->md.stat; + handlep->stat.ps_recv += kstats.tp_packets; + handlep->stat.ps_drop += kstats.tp_drops; + *stats = handlep->stat; return 0; } else @@ -1849,15 +1892,15 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats) * the kernel by libpcap. * * We maintain the count of packets processed by libpcap in - * "md.packets_read", for reasons described in the comment + * "handlep->packets_read", for reasons described in the comment * at the end of pcap_read_packet(). We have no idea how many * packets were dropped by the kernel buffers -- but we know * how many the interface dropped, so we can return that. */ - stats->ps_recv = handle->md.packets_read; + stats->ps_recv = handlep->packets_read; stats->ps_drop = 0; - stats->ps_ifdrop = handle->md.stat.ps_ifdrop; + stats->ps_ifdrop = handlep->stat.ps_ifdrop; return 0; } @@ -2238,6 +2281,7 @@ static int pcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter, int is_mmapped) { + struct pcap_linux *handlep; #ifdef SO_ATTACH_FILTER struct sock_fprog fcode; int can_filter_in_kernel; @@ -2252,6 +2296,8 @@ pcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter, return -1; } + handlep = handle->private; + /* Make our private copy of the filter */ if (install_bpf_program(handle, filter) < 0) @@ -2262,7 +2308,7 @@ pcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter, * Run user level packet filter by default. Will be overriden if * installing a kernel filter succeeds. */ - handle->md.use_bpf = 0; + handlep->filtering_in_kernel = 0; /* Install kernel level filter if possible */ @@ -2351,7 +2397,7 @@ pcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter, if ((err = set_kernel_filter(handle, &fcode)) == 0) { /* Installation succeded - using kernel filter. */ - handle->md.use_bpf = 1; + handlep->filtering_in_kernel = 1; } else if (err == -1) /* Non-fatal error */ { @@ -2376,7 +2422,7 @@ pcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter, * calling "pcap_setfilter()". Otherwise, the kernel filter may * filter out packets that would pass the new userland filter. */ - if (!handle->md.use_bpf) + if (!handlep->filtering_in_kernel) reset_kernel_filter(handle); /* @@ -2408,7 +2454,9 @@ static int pcap_setdirection_linux(pcap_t *handle, pcap_direction_t d) { #ifdef HAVE_PF_PACKET_SOCKETS - if (!handle->md.sock_packet) { + struct pcap_linux *handlep = handle->private; + + if (!handlep->sock_packet) { handle->direction = d; return 0; } @@ -2814,7 +2862,7 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok) handle->linktype = DLT_LINUX_IRDA; /* We need to save packet direction for IrDA decoding, * so let's use "Linux-cooked" mode. Jean II */ - //handle->md.cooked = 1; + //handlep->cooked = 1; break; /* ARPHRD_LAPD is unofficial and randomly allocated, if reallocation @@ -2864,6 +2912,7 @@ static int activate_new(pcap_t *handle) { #ifdef HAVE_PF_PACKET_SOCKETS + struct pcap_linux *handlep = handle->private; const char *device = handle->opt.source; int is_any_device = (strcmp(device, "any") == 0); int sock_fd = -1, arptype; @@ -2909,12 +2958,12 @@ activate_new(pcap_t *handle) } /* It seems the kernel supports the new interface. */ - handle->md.sock_packet = 0; + handlep->sock_packet = 0; /* * Get the interface index of the loopback device. * If the attempt fails, don't fail, just set the - * "md.lo_ifindex" to -1. + * "handlep->lo_ifindex" to -1. * * XXX - can there be more than one device that loops * packets back, i.e. devices other than "lo"? If so, @@ -2922,7 +2971,7 @@ activate_new(pcap_t *handle) * indices for them, and check all of them in * "pcap_read_packet()". */ - handle->md.lo_ifindex = iface_get_id(sock_fd, "lo", handle->errbuf); + handlep->lo_ifindex = iface_get_id(sock_fd, "lo", handle->errbuf); /* * Default value for offset to align link-layer payload @@ -2937,7 +2986,7 @@ activate_new(pcap_t *handle) */ if (!is_any_device) { /* Assume for now we don't need cooked mode. */ - handle->md.cooked = 0; + handlep->cooked = 0; if (handle->opt.rfmon) { /* @@ -2967,8 +3016,8 @@ activate_new(pcap_t *handle) * device to open for monitor mode. If we've * been given a different device, use it. */ - if (handle->md.mondevice != NULL) - device = handle->md.mondevice; + if (handlep->mondevice != NULL) + device = handlep->mondevice; } arptype = iface_get_arptype(sock_fd, device, handle->errbuf); if (arptype < 0) { @@ -3015,7 +3064,7 @@ activate_new(pcap_t *handle) return PCAP_ERROR; } } - handle->md.cooked = 1; + handlep->cooked = 1; /* * Get rid of any link-layer type list @@ -3053,14 +3102,14 @@ activate_new(pcap_t *handle) handle->linktype = DLT_LINUX_SLL; } - handle->md.ifindex = iface_get_id(sock_fd, device, + handlep->ifindex = iface_get_id(sock_fd, device, handle->errbuf); - if (handle->md.ifindex == -1) { + if (handlep->ifindex == -1) { close(sock_fd); return PCAP_ERROR; } - if ((err = iface_bind(sock_fd, handle->md.ifindex, + if ((err = iface_bind(sock_fd, handlep->ifindex, handle->errbuf)) != 1) { close(sock_fd); if (err < 0) @@ -3082,7 +3131,7 @@ activate_new(pcap_t *handle) /* * It uses cooked mode. */ - handle->md.cooked = 1; + handlep->cooked = 1; handle->linktype = DLT_LINUX_SLL; /* @@ -3092,7 +3141,7 @@ activate_new(pcap_t *handle) * if we figure out how to transmit in cooked * mode. */ - handle->md.ifindex = -1; + handlep->ifindex = -1; } /* @@ -3119,7 +3168,7 @@ activate_new(pcap_t *handle) if (!is_any_device && handle->opt.promisc) { memset(&mr, 0, sizeof(mr)); - mr.mr_ifindex = handle->md.ifindex; + mr.mr_ifindex = handlep->ifindex; mr.mr_type = PACKET_MR_PROMISC; if (setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1) { @@ -3158,7 +3207,7 @@ activate_new(pcap_t *handle) * 1 byte of packet data (so we don't pass a byte * count of 0 to "recvfrom()"). */ - if (handle->md.cooked) { + if (handlep->cooked) { if (handle->snapshot < SLL_HDR_LEN + 1) handle->snapshot = SLL_HDR_LEN + 1; } @@ -3170,15 +3219,15 @@ activate_new(pcap_t *handle) switch (handle->linktype) { case DLT_EN10MB: - handle->md.vlan_offset = 2 * ETH_ALEN; + handlep->vlan_offset = 2 * ETH_ALEN; break; case DLT_LINUX_SLL: - handle->md.vlan_offset = 14; + handlep->vlan_offset = 14; break; default: - handle->md.vlan_offset = -1; /* unknown */ + handlep->vlan_offset = -1; /* unknown */ break; } @@ -3210,14 +3259,15 @@ activate_new(pcap_t *handle) static int activate_mmap(pcap_t *handle, int *status) { + struct pcap_linux *handlep = handle->private; int ret; /* * Attempt to allocate a buffer to hold the contents of one * packet, for use by the oneshot callback. */ - handle->md.oneshot_buffer = malloc(handle->snapshot); - if (handle->md.oneshot_buffer == NULL) { + handlep->oneshot_buffer = malloc(handle->snapshot); + if (handlep->oneshot_buffer == NULL) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't allocate oneshot buffer: %s", pcap_strerror(errno)); @@ -3231,7 +3281,7 @@ activate_mmap(pcap_t *handle, int *status) } ret = prepare_tpacket_socket(handle); if (ret == -1) { - free(handle->md.oneshot_buffer); + free(handlep->oneshot_buffer); *status = PCAP_ERROR; return ret; } @@ -3241,7 +3291,7 @@ activate_mmap(pcap_t *handle, int *status) * We don't support memory-mapped capture; our caller * will fall back on reading from the socket. */ - free(handle->md.oneshot_buffer); + free(handlep->oneshot_buffer); return 0; } if (ret == -1) { @@ -3249,7 +3299,7 @@ activate_mmap(pcap_t *handle, int *status) * Error attempting to enable memory-mapped capture; * fail. create_ring() has set *status. */ - free(handle->md.oneshot_buffer); + free(handlep->oneshot_buffer); return -1; } @@ -3288,13 +3338,14 @@ activate_mmap(pcap_t *handle _U_, int *status _U_) static int prepare_tpacket_socket(pcap_t *handle) { + struct pcap_linux *handlep = handle->private; #ifdef HAVE_TPACKET2 socklen_t len; int val; #endif - handle->md.tp_version = TPACKET_V1; - handle->md.tp_hdrlen = sizeof(struct tpacket_hdr); + handlep->tp_version = TPACKET_V1; + handlep->tp_hdrlen = sizeof(struct tpacket_hdr); #ifdef HAVE_TPACKET2 /* Probe whether kernel supports TPACKET_V2 */ @@ -3310,7 +3361,7 @@ prepare_tpacket_socket(pcap_t *handle) pcap_strerror(errno)); return -1; } - handle->md.tp_hdrlen = val; + handlep->tp_hdrlen = val; val = TPACKET_V2; if (setsockopt(handle->fd, SOL_PACKET, PACKET_VERSION, &val, @@ -3320,7 +3371,7 @@ prepare_tpacket_socket(pcap_t *handle) pcap_strerror(errno)); return -1; } - handle->md.tp_version = TPACKET_V2; + handlep->tp_version = TPACKET_V2; /* Reserve space for VLAN tag reconstruction */ val = VLAN_TAG_LEN; @@ -3351,6 +3402,7 @@ prepare_tpacket_socket(pcap_t *handle) static int create_ring(pcap_t *handle, int *status) { + struct pcap_linux *handlep = handle->private; unsigned i, j, frames_per_block; struct tpacket_req req; socklen_t len; @@ -3455,7 +3507,7 @@ create_ring(pcap_t *handle, int *status) * let's use it.. maybe is it even large enough to directly * replace macoff.. */ - tp_hdrlen = TPACKET_ALIGN(handle->md.tp_hdrlen) + sizeof(struct sockaddr_ll) ; + tp_hdrlen = TPACKET_ALIGN(handlep->tp_hdrlen) + sizeof(struct sockaddr_ll) ; netoff = TPACKET_ALIGN(tp_hdrlen + (maclen < 16 ? 16 : maclen)) + tp_reserve; /* NOTE: AFAICS tp_reserve may break the TPACKET_ALIGN of * netoff, which contradicts @@ -3624,10 +3676,10 @@ retry: } /* memory map the rx ring */ - handle->md.mmapbuflen = req.tp_block_nr * req.tp_block_size; - handle->md.mmapbuf = mmap(0, handle->md.mmapbuflen, + handlep->mmapbuflen = req.tp_block_nr * req.tp_block_size; + handlep->mmapbuf = mmap(0, handlep->mmapbuflen, PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); - if (handle->md.mmapbuf == MAP_FAILED) { + if (handlep->mmapbuf == MAP_FAILED) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "can't mmap rx ring: %s", pcap_strerror(errno)); @@ -3653,7 +3705,7 @@ retry: /* fill the header ring with proper frame ptr*/ handle->offset = 0; for (i=0; imd.mmapbuf[i*req.tp_block_size]; + void *base = &handlep->mmapbuf[i*req.tp_block_size]; for (j=0; joffset) { RING_GET_FRAME(handle) = base; base += req.tp_frame_size; @@ -3669,6 +3721,8 @@ retry: static void destroy_ring(pcap_t *handle) { + struct pcap_linux *handlep = handle->private; + /* tell the kernel to destroy the ring*/ struct tpacket_req req; memset(&req, 0, sizeof(req)); @@ -3676,10 +3730,10 @@ destroy_ring(pcap_t *handle) (void *) &req, sizeof(req)); /* if ring is mapped, unmap it*/ - if (handle->md.mmapbuf) { + if (handlep->mmapbuf) { /* do not test for mmap failure, as we can't recover from any error */ - munmap(handle->md.mmapbuf, handle->md.mmapbuflen); - handle->md.mmapbuf = NULL; + munmap(handlep->mmapbuf, handlep->mmapbuflen); + handlep->mmapbuf = NULL; } } @@ -3705,19 +3759,23 @@ pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes) { struct oneshot_userdata *sp = (struct oneshot_userdata *)user; + pcap_t *handle = sp->pd; + struct pcap_linux *handlep = handle->private; *sp->hdr = *h; - memcpy(sp->pd->md.oneshot_buffer, bytes, h->caplen); - *sp->pkt = sp->pd->md.oneshot_buffer; + memcpy(handlep->oneshot_buffer, bytes, h->caplen); + *sp->pkt = handlep->oneshot_buffer; } static void pcap_cleanup_linux_mmap( pcap_t *handle ) { + struct pcap_linux *handlep = handle->private; + destroy_ring(handle); - if (handle->md.oneshot_buffer != NULL) { - free(handle->md.oneshot_buffer); - handle->md.oneshot_buffer = NULL; + if (handlep->oneshot_buffer != NULL) { + free(handlep->oneshot_buffer); + handlep->oneshot_buffer = NULL; } pcap_cleanup_linux(handle); } @@ -3726,28 +3784,32 @@ pcap_cleanup_linux_mmap( pcap_t *handle ) static int pcap_getnonblock_mmap(pcap_t *p, char *errbuf) { + struct pcap_linux *handlep = p->private; + /* use negative value of timeout to indicate non blocking ops */ - return (p->md.timeout<0); + return (handlep->timeout<0); } static int pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf) { + struct pcap_linux *handlep = p->private; + /* * Map each value to their corresponding negation to * preserve the timeout value provided with pcap_set_timeout. */ if (nonblock) { - if (p->md.timeout >= 0) { + if (handlep->timeout >= 0) { /* * Indicate that we're switching to * non-blocking mode. */ - p->md.timeout = ~p->md.timeout; + handlep->timeout = ~handlep->timeout; } } else { - if (p->md.timeout < 0) { - p->md.timeout = ~p->md.timeout; + if (handlep->timeout < 0) { + handlep->timeout = ~handlep->timeout; } } return 0; @@ -3756,10 +3818,11 @@ pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf) static inline union thdr * pcap_get_ring_frame(pcap_t *handle, int status) { + struct pcap_linux *handlep = handle->private; union thdr h; h.raw = RING_GET_FRAME(handle); - switch (handle->md.tp_version) { + switch (handlep->tp_version) { case TPACKET_V1: if (status != (h.h1->tp_status ? TP_STATUS_USER : TP_STATUS_KERNEL)) @@ -3784,6 +3847,7 @@ static int pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { + struct pcap_linux *handlep = handle->private; int timeout; int pkts = 0; char c; @@ -3796,10 +3860,10 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, pollinfo.fd = handle->fd; pollinfo.events = POLLIN; - if (handle->md.timeout == 0) + if (handlep->timeout == 0) timeout = -1; /* block forever */ - else if (handle->md.timeout > 0) - timeout = handle->md.timeout; /* block for that amount of time */ + else if (handlep->timeout > 0) + timeout = handlep->timeout; /* block for that amount of time */ else timeout = 0; /* non-blocking mode - poll to pick up errors */ do { @@ -3887,7 +3951,7 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, if (!h.raw) break; - switch (handle->md.tp_version) { + switch (handlep->tp_version) { case TPACKET_V1: tp_len = h.h1->tp_len; tp_mac = h.h1->tp_mac; @@ -3907,7 +3971,7 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, default: snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "unsupported tpacket version %d", - handle->md.tp_version); + handlep->tp_version); return -1; } /* perform sanity check on internal offset. */ @@ -3923,14 +3987,14 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, * If the kernel filtering is enabled we need to run the * filter until all the frames present into the ring * at filter creation time are processed. - * In such case md.use_bpf is used as a counter for the + * In such case filtering_in_kernel is used as a counter for the * packet we need to filter. * Note: alternatively it could be possible to stop applying * the filter when the ring became empty, but it can possibly * happen a lot later... */ bp = (unsigned char*)h.raw + tp_mac; - run_bpf = (!handle->md.use_bpf) || - ((handle->md.use_bpf>1) && handle->md.use_bpf--); + run_bpf = (!handlep->filtering_in_kernel) || + ((handlep->filtering_in_kernel>1) && handlep->filtering_in_kernel--); if (run_bpf && handle->fcode.bf_insns && (bpf_filter(handle->fcode.bf_insns, bp, tp_len, tp_snaplen) == 0)) @@ -3939,7 +4003,7 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, /* * Do checks based on packet direction. */ - sll = (void *)h.raw + TPACKET_ALIGN(handle->md.tp_hdrlen); + sll = (void *)h.raw + TPACKET_ALIGN(handlep->tp_hdrlen); if (sll->sll_pkttype == PACKET_OUTGOING) { /* * Outgoing packet. @@ -3947,7 +4011,7 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, * we'll see the packet as an incoming packet as well, * and we don't want to see it twice. */ - if (sll->sll_ifindex == handle->md.lo_ifindex) + if (sll->sll_ifindex == handlep->lo_ifindex) goto skip; /* @@ -3971,7 +4035,7 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, pcaphdr.len = tp_len; /* if required build in place the sll header*/ - if (handle->md.cooked) { + if (handlep->cooked) { struct sll_header *hdrp; /* @@ -3991,7 +4055,7 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, * the sll header. */ if (bp < (u_char *)h.raw + - TPACKET_ALIGN(handle->md.tp_hdrlen) + + TPACKET_ALIGN(handlep->tp_hdrlen) + sizeof(struct sockaddr_ll)) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "cooked-mode frame doesn't have room for sll header"); @@ -4015,20 +4079,20 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, } #ifdef HAVE_TPACKET2 - if ((handle->md.tp_version == TPACKET_V2) && + if ((handlep->tp_version == TPACKET_V2) && #if defined(TP_STATUS_VLAN_VALID) (h.h2->tp_vlan_tci || (h.h2->tp_status & TP_STATUS_VLAN_VALID)) && #else h.h2->tp_vlan_tci && #endif - handle->md.vlan_offset != -1 && - tp_snaplen >= (unsigned int) handle->md.vlan_offset) { + handlep->vlan_offset != -1 && + tp_snaplen >= (unsigned int) handlep->vlan_offset) { struct vlan_tag *tag; bp -= VLAN_TAG_LEN; - memmove(bp, bp + VLAN_TAG_LEN, handle->md.vlan_offset); + memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset); - tag = (struct vlan_tag *)(bp + handle->md.vlan_offset); + tag = (struct vlan_tag *)(bp + handlep->vlan_offset); tag->vlan_tpid = htons(ETH_P_8021Q); tag->vlan_tci = htons(h.h2->tp_vlan_tci); @@ -4052,11 +4116,11 @@ pcap_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, /* pass the packet to the user */ pkts++; callback(user, &pcaphdr, bp); - handle->md.packets_read++; + handlep->packets_read++; skip: /* next packet */ - switch (handle->md.tp_version) { + switch (handlep->tp_version) { case TPACKET_V1: h.h1->tp_status = TP_STATUS_KERNEL; break; @@ -4081,6 +4145,7 @@ skip: static int pcap_setfilter_linux_mmap(pcap_t *handle, struct bpf_program *filter) { + struct pcap_linux *handlep = handle->private; int n, offset; int ret; @@ -4097,7 +4162,7 @@ pcap_setfilter_linux_mmap(pcap_t *handle, struct bpf_program *filter) /* if the kernel filter is enabled, we need to apply the filter on * all packets present into the ring. Get an upper bound of their number */ - if (!handle->md.use_bpf) + if (!handlep->filtering_in_kernel) return ret; /* walk the ring backward and count the free slot */ @@ -4115,7 +4180,7 @@ pcap_setfilter_linux_mmap(pcap_t *handle, struct bpf_program *filter) handle->offset = offset; /* store the number of packets currently present in the ring */ - handle->md.use_bpf = 1 + (handle->cc - n); + handlep->filtering_in_kernel = 1 + (handle->cc - n); return ret; } @@ -4317,6 +4382,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device) * value of -ENFILE. (Return values are negative errnos.) We * could probably use that to find an unused device. */ + struct pcap_linux *handlep = handle->private; int err; struct iwreq ireq; struct iw_priv_args *priv; @@ -4597,7 +4663,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device) /* * Save the old mode. */ - handle->md.oldmode = ireq.u.mode; + handlep->oldmode = ireq.u.mode; /* * Put the adapter in rfmon mode. How we do this depends @@ -4624,7 +4690,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device) * Note that we have to put the old mode back * when we close the device. */ - handle->md.must_do_on_close |= MUST_CLEAR_RFMON; + handlep->must_do_on_close |= MUST_CLEAR_RFMON; /* * Add this to the list of pcaps to close @@ -4871,7 +4937,7 @@ enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device) * Note that we have to put the old mode back when we * close the device. */ - handle->md.must_do_on_close |= MUST_CLEAR_RFMON; + handlep->must_do_on_close |= MUST_CLEAR_RFMON; /* * Add this to the list of pcaps to close when we exit. @@ -5034,6 +5100,7 @@ iface_get_offload(pcap_t *handle _U_) static int activate_old(pcap_t *handle) { + struct pcap_linux *handlep = handle->private; int arptype; struct ifreq ifr; const char *device = handle->opt.source; @@ -5061,10 +5128,10 @@ activate_old(pcap_t *handle) } /* It worked - we are using the old interface */ - handle->md.sock_packet = 1; + handlep->sock_packet = 1; /* ...which means we get the link-layer header. */ - handle->md.cooked = 0; + handlep->cooked = 0; /* Bind to the given device */ @@ -5133,7 +5200,7 @@ activate_old(pcap_t *handle) pcap_strerror(errno)); return PCAP_ERROR; } - handle->md.must_do_on_close |= MUST_CLEAR_PROMISC; + handlep->must_do_on_close |= MUST_CLEAR_PROMISC; /* * Add this to the list of pcaps @@ -5219,7 +5286,7 @@ activate_old(pcap_t *handle) * SOCK_PACKET sockets don't supply information from * stripped VLAN tags. */ - handle->md.vlan_offset = -1; /* unknown */ + handlep->vlan_offset = -1; /* unknown */ return 1; } @@ -5316,6 +5383,7 @@ iface_get_arptype(int fd, const char *device, char *ebuf) static int fix_program(pcap_t *handle, struct sock_fprog *fcode, int is_mmapped) { + struct pcap_linux *handlep = handle->private; size_t prog_size; register int i; register struct bpf_insn *p; @@ -5391,7 +5459,7 @@ fix_program(pcap_t *handle, struct sock_fprog *fcode, int is_mmapped) /* * Yes; are we in cooked mode? */ - if (handle->md.cooked) { + if (handlep->cooked) { /* * Yes, so we need to fix this * instruction. diff --git a/pcap-netfilter-linux.c b/pcap-netfilter-linux.c index 48f29b02..35c677bc 100644 --- a/pcap-netfilter-linux.c +++ b/pcap-netfilter-linux.c @@ -74,11 +74,19 @@ typedef enum { OTHER = -1, NFLOG, NFQUEUE } nftype_t; +/* + * Private data for capturing on Linux netfilter sockets. + */ +struct pcap_netfilter { + u_int packets_read; /* count of packets read with recvfrom() */ +}; + static int nfqueue_send_verdict(const pcap_t *handle, u_int16_t group_id, u_int32_t id, u_int32_t verdict); static int netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { + struct pcap_netfilter *handlep = handle->private; const unsigned char *buf; int count = 0; int len; @@ -179,7 +187,7 @@ netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_c if (handle->fcode.bf_insns == NULL || bpf_filter(handle->fcode.bf_insns, payload, pkth.len, pkth.caplen)) { - handle->md.packets_read++; + handlep->packets_read++; callback(user, &pkth, payload); count++; } @@ -211,7 +219,9 @@ netfilter_set_datalink(pcap_t *handle, int dlt) static int netfilter_stats_linux(pcap_t *handle, struct pcap_stat *stats) { - stats->ps_recv = handle->md.packets_read; + struct pcap_netfilter *handlep = handle->private; + + stats->ps_recv = handlep->packets_read; stats->ps_drop = 0; stats->ps_ifdrop = 0; return 0; @@ -471,7 +481,6 @@ netfilter_activate(pcap_t* handle) handle->inject_op = netfilter_inject_linux; handle->setfilter_op = install_bpf_program; /* no kernel filtering */ handle->setdirection_op = NULL; - handle->set_datalink_op = NULL; handle->set_datalink_op = netfilter_set_datalink; handle->getnonblock_op = pcap_getnonblock_fd; handle->setnonblock_op = pcap_setnonblock_fd; @@ -612,7 +621,7 @@ netfilter_create(const char *device, char *ebuf, int *is_ours) /* OK, it's probably ours. */ *is_ours = 1; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_netfilter)); if (p == NULL) return (NULL); diff --git a/pcap-nit.c b/pcap-nit.c index 85b32f2a..8e357211 100644 --- a/pcap-nit.c +++ b/pcap-nit.c @@ -71,9 +71,17 @@ static const char rcsid[] _U_ = /* Forwards */ static int nit_setflags(int, int, int, char *); +/* + * Private data for capturing on NIT devices. + */ +struct pcap_nit { + struct pcap_stat stat; +}; + static int pcap_stats_nit(pcap_t *p, struct pcap_stat *ps) { + struct pcap_nit *pn = p->private; /* * "ps_recv" counts packets handed to the filter, not packets @@ -91,13 +99,14 @@ pcap_stats_nit(pcap_t *p, struct pcap_stat *ps) * kernel by libpcap or packets not yet read from libpcap by the * application. */ - *ps = p->md.stat; + *ps = pn->stat; return (0); } static int pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { + struct pcap_nit *pn = p->private; register int cc, n; register u_char *bp, *cp, *ep; register struct nit_hdr *nh; @@ -156,7 +165,7 @@ pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user) case NIT_NOMBUF: case NIT_NOCLUSTER: case NIT_NOSPACE: - p->md.stat.ps_drop = nh->nh_dropped; + pn->stat.ps_drop = nh->nh_dropped; continue; case NIT_SEQNO: @@ -167,7 +176,7 @@ pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user) "bad nit state %d", nh->nh_state); return (-1); } - ++p->md.stat.ps_recv; + ++pn->stat.ps_recv; bp += ((sizeof(struct nit_hdr) + nh->nh_datalen + sizeof(int) - 1) & ~(sizeof(int) - 1)); @@ -273,7 +282,7 @@ pcap_activate_nit(pcap_t *p) "bind: %s: %s", snit.snit_ifname, pcap_strerror(errno)); goto bad; } - nit_setflags(p->fd, p->opt.promisc, p->md.timeout, p->errbuf); + nit_setflags(p->fd, p->opt.promisc, p->opt.timeout, p->errbuf); /* * NIT supports only ethernets. @@ -332,7 +341,7 @@ pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_nit)); if (p == NULL) return (NULL); diff --git a/pcap-pf.c b/pcap-pf.c index 84c6d547..eb06e7b5 100644 --- a/pcap-pf.c +++ b/pcap-pf.c @@ -74,6 +74,24 @@ struct rtentry; #include "os-proto.h" #endif +/* + * FDDI packets are padded to make everything line up on a nice boundary. + */ +#define PCAP_FDDIPAD 3 + +/* + * Private data for capturing on Ultrix and DEC OSF/1^WDigital UNIX^W^W + * Tru64 UNIX packetfilter devices. + */ +struct pcap_pf { + int filtering_in_kernel; /* using kernel filter */ + u_long TotPkts; /* can't oflow for 79 hrs on ether */ + u_long TotAccepted; /* count accepted by filter */ + u_long TotDrops; /* count of dropped packets */ + long TotMissed; /* missed by i/f during this run */ + long OrigMissed; /* missed by i/f before this run */ +}; + static int pcap_setfilter_pf(pcap_t *, struct bpf_program *); /* @@ -87,15 +105,14 @@ static int pcap_setfilter_pf(pcap_t *, struct bpf_program *); static int pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user) { + struct pcap_pf *pf = pc->private; register u_char *p, *bp; register int cc, n, buflen, inc; register struct enstamp *sp; #ifdef LBL_ALIGN struct enstamp stamp; #endif -#ifdef PCAP_FDDIPAD register int pad; -#endif again: cc = pc->cc; @@ -126,9 +143,7 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user) * Loop through each packet. */ n = 0; -#ifdef PCAP_FDDIPAD pad = pc->fddipad; -#endif while (cc > 0) { /* * Has "pcap_breakloop()" been called? @@ -177,39 +192,31 @@ pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user) inc = ENALIGN(buflen + sp->ens_stamplen); cc -= inc; bp += inc; - pc->md.TotPkts++; - pc->md.TotDrops += sp->ens_dropped; - pc->md.TotMissed = sp->ens_ifoverflows; - if (pc->md.OrigMissed < 0) - pc->md.OrigMissed = pc->md.TotMissed; + pf->TotPkts++; + pf->TotDrops += sp->ens_dropped; + pf->TotMissed = sp->ens_ifoverflows; + if (pf->OrigMissed < 0) + pf->OrigMissed = pf->TotMissed; /* * Short-circuit evaluation: if using BPF filter * in kernel, no need to do it now - we already know * the packet passed the filter. * -#ifdef PCAP_FDDIPAD * Note: the filter code was generated assuming * that pc->fddipad was the amount of padding * before the header, as that's what's required * in the kernel, so we run the filter before * skipping that padding. -#endif */ - if (pc->md.use_bpf || + if (pf->filtering_in_kernel || bpf_filter(pc->fcode.bf_insns, p, sp->ens_count, buflen)) { struct pcap_pkthdr h; - pc->md.TotAccepted++; + pf->TotAccepted++; h.ts = sp->ens_tstamp; -#ifdef PCAP_FDDIPAD h.len = sp->ens_count - pad; -#else - h.len = sp->ens_count; -#endif -#ifdef PCAP_FDDIPAD p += pad; buflen -= pad; -#endif h.caplen = buflen; (*callback)(user, &h, p); if (++n >= cnt && cnt > 0) { @@ -240,6 +247,7 @@ pcap_inject_pf(pcap_t *p, const void *buf, size_t size) static int pcap_stats_pf(pcap_t *p, struct pcap_stat *ps) { + struct pcap_pf *pf = p->private; /* * If packet filtering is being done in the kernel: @@ -277,9 +285,9 @@ pcap_stats_pf(pcap_t *p, struct pcap_stat *ps) * the kernel by libpcap, but they may include packets not * yet read from libpcap by the application. */ - ps->ps_recv = p->md.TotAccepted; - ps->ps_drop = p->md.TotDrops; - ps->ps_ifdrop = p->md.TotMissed - p->md.OrigMissed; + ps->ps_recv = pf->TotAccepted; + ps->ps_drop = pf->TotDrops; + ps->ps_ifdrop = pf->TotMissed - pf->OrigMissed; return (0); } @@ -294,6 +302,7 @@ pcap_stats_pf(pcap_t *p, struct pcap_stat *ps) static int pcap_activate_pf(pcap_t *p) { + struct pcap_pf *pf = p->private; short enmode; int backlog = -1; /* request the most */ struct enfilter Filter; @@ -327,7 +336,7 @@ your system may not be properly configured; see the packetfilter(4) man page\n", p->opt.source, pcap_strerror(errno)); goto bad; } - p->md.OrigMissed = -1; + pf->OrigMissed = -1; enmode = ENTSTAMP|ENBATCH|ENNONEXCL; if (p->opt.promisc) enmode |= ENPROMISC; @@ -436,7 +445,6 @@ your system may not be properly configured; see the packetfilter(4) man page\n", goto bad; } /* set truncation */ -#ifdef PCAP_FDDIPAD if (p->linktype == DLT_FDDI) { p->fddipad = PCAP_FDDIPAD; @@ -444,7 +452,6 @@ your system may not be properly configured; see the packetfilter(4) man page\n", p->snapshot += PCAP_FDDIPAD; } else p->fddipad = 0; -#endif if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&p->snapshot) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s", pcap_strerror(errno)); @@ -460,10 +467,10 @@ your system may not be properly configured; see the packetfilter(4) man page\n", goto bad; } - if (p->md.timeout != 0) { + if (p->opt.timeout != 0) { struct timeval timeout; - timeout.tv_sec = p->md.timeout / 1000; - timeout.tv_usec = (p->md.timeout * 1000) % 1000000; + timeout.tv_sec = p->opt.timeout / 1000; + timeout.tv_usec = (p->opt.timeout * 1000) % 1000000; if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s", pcap_strerror(errno)); @@ -503,7 +510,7 @@ pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_pf)); if (p == NULL) return (NULL); @@ -520,6 +527,7 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) static int pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp) { + struct pcap_pf *pf = p->private; struct bpf_version bv; /* @@ -561,7 +569,7 @@ pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp) * a window to annoy the user. */ fprintf(stderr, "tcpdump: Using kernel BPF filter\n"); - p->md.use_bpf = 1; + pf->filtering_in_kernel = 1; /* * Discard any previously-received packets, @@ -599,6 +607,6 @@ pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp) * a warning of some sort. */ fprintf(stderr, "tcpdump: Filtering in user process\n"); - p->md.use_bpf = 0; + pf->filtering_in_kernel = 0; return (0); } diff --git a/pcap-septel.c b/pcap-septel.c index e0be766f..1210b7ce 100644 --- a/pcap-septel.c +++ b/pcap-septel.c @@ -50,6 +50,13 @@ static int septel_setfilter(pcap_t *p, struct bpf_program *fp); static int septel_stats(pcap_t *p, struct pcap_stat *ps); static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf); +/* + * Private data for capturing on Septel devices. + */ +struct pcap_septel { + struct pcap_stat stat; +} + /* * Read at most max_packets from the capture queue and call the callback * for each of them. Returns the number of packets handled, -1 if an @@ -57,6 +64,7 @@ static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf); */ static int septel_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { + struct pcap_septel *ps = p->private; HDR *h; MSG *m; int processed = 0 ; @@ -154,7 +162,7 @@ loop: pcap_header.len = packet_len; /* Count the packet. */ - p->md.stat.ps_recv++; + ps->stat.ps_recv++; /* Call the user supplied callback function */ callback(user, &pcap_header, dp); @@ -229,7 +237,7 @@ pcap_t *septel_create(const char *device, char *ebuf, int *is_ours) { /* OK, it's probably ours. */ *is_ours = 1; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_septel)); if (p == NULL) return NULL; @@ -238,10 +246,11 @@ pcap_t *septel_create(const char *device, char *ebuf, int *is_ours) { } static int septel_stats(pcap_t *p, struct pcap_stat *ps) { - /*p->md.stat.ps_recv = 0;*/ - /*p->md.stat.ps_drop = 0;*/ + struct pcap_septel *handlep = p->private; + /*handlep->stat.ps_recv = 0;*/ + /*handlep->stat.ps_drop = 0;*/ - *ps = p->md.stat; + *ps = handlep->stat; return 0; } @@ -282,8 +291,6 @@ static int septel_setfilter(pcap_t *p, struct bpf_program *fp) { return -1; } - p->md.use_bpf = 0; - return (0); } @@ -291,5 +298,6 @@ static int septel_setfilter(pcap_t *p, struct bpf_program *fp) { static int septel_setnonblock(pcap_t *p, int nonblock, char *errbuf) { - return (0); + fprintf(errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices"); + return (-1); } diff --git a/pcap-sita.c b/pcap-sita.c index 19219993..7ab801ec 100644 --- a/pcap-sita.c +++ b/pcap-sita.c @@ -55,40 +55,37 @@ #define LIVE 1 typedef struct iface { - struct iface *next; /* a pointer to the next interface */ - char *name; /* this interface's name on Wireshark */ - char *IOPname; /* this interface's name on an IOP */ - uint32_t iftype; /* the type of interface (DLT values) */ + struct iface *next; /* a pointer to the next interface */ + char *name; /* this interface's name */ + char *IOPname; /* this interface's name on an IOP */ + uint32_t iftype; /* the type of interface (DLT values) */ } iface_t; typedef struct unit { - char *ip; /* this unit's IP address (as extracted from /etc/hosts) */ - int fd; /* the connection to this unit (if it exists) */ - int find_fd; /* a big kludge to avoid my programming limitations since I could have this unit open for findalldevs purposes */ - int first_time; /* 0 = just opened via acn_open_live(), ie. the first time, NZ = nth time */ - struct sockaddr_in *serv_addr; /* the address control block for comms to this unit */ - int chassis; - int geoslot; - iface_t *iface; /* a pointer to a linked list of interface structures */ - char *imsg; /* a pointer to an inbound message */ - int len; /* the current size of the inbound message */ + char *ip; /* this unit's IP address (as extracted from /etc/hosts) */ + int fd; /* the connection to this unit (if it exists) */ + int find_fd; /* a big kludge to avoid my programming limitations since I could have this unit open for findalldevs purposes */ + int first_time; /* 0 = just opened via acn_open_live(), ie. the first time, NZ = nth time */ + struct sockaddr_in *serv_addr; /* the address control block for comms to this unit */ + int chassis; + int geoslot; + iface_t *iface; /* a pointer to a linked list of interface structures */ + char *imsg; /* a pointer to an inbound message */ + int len; /* the current size of the inbound message */ } unit_t; -static char *errorString; static unit_t units[MAX_CHASSIS+1][MAX_GEOSLOT+1]; /* we use indexes of 1 through 8, but we reserve/waste index 0 */ -static fd_set readfds; /* a place to store the file descriptors for the connections to the IOPs */ -static fd_set working_set; -static int max_fs; -static char static_buf[32]; +static fd_set readfds; /* a place to store the file descriptors for the connections to the IOPs */ +static int max_fs; -pcap_if_t *acn_if_list; /* pcap's list of available interfaces */ +pcap_if_t *acn_if_list; /* pcap's list of available interfaces */ static void dump_interface_list(void) { pcap_if_t *iff; pcap_addr_t *addr; - int longest_name_len = 0; + int longest_name_len = 0; char *n, *d, *f; - int if_number = 0; + int if_number = 0; iff = acn_if_list; while (iff) { @@ -405,18 +402,16 @@ static void acn_freealldevs(void) { } } -static char *nonUnified_port_num(unit_t *u, int IOPportnum) { +static void nonUnified_IOP_port_name(char *buf, size_t bufsize, const char *proto, unit_t *u) { - sprintf(static_buf, "%d_%d", u->chassis, u->geoslot); - return static_buf; + snprintf(buf, bufsize, "%s_%d_%d", proto, u->chassis, u->geoslot); } -static char *unified_port_num(unit_t *u, int IOPportnum) { +static void unified_IOP_port_name(char *buf, size_t bufsize, const char *proto, unit_t *u, int IOPportnum) { int portnum; portnum = ((u->chassis - 1) * 64) + ((u->geoslot - 1) * 8) + IOPportnum + 1; - sprintf(static_buf, "%d", portnum); - return static_buf; + snprintf(buf, bufsize, "%s_%d", proto, portnum); } static char *translate_IOP_to_pcap_name(unit_t *u, char *IOPname, bpf_u_int32 iftype) { @@ -448,24 +443,38 @@ static char *translate_IOP_to_pcap_name(unit_t *u, char *IOPname, bpf_u_int32 if if (strncmp(IOPname, "lo", 2) == 0) { IOPportnum = atoi(&IOPname[2]); switch (iftype) { - case DLT_EN10MB: proto = "lo"; port = nonUnified_port_num(u, IOPportnum); break; - default: proto = "???"; port = unified_port_num(u, IOPportnum); break; + case DLT_EN10MB: + nonUnified_IOP_port_name(buf, sizeof buf, "lo", u); + break; + default: + unified_IOP_port_name(buf, sizeof buf, "???", u, IOPportnum); + break; } } else if (strncmp(IOPname, "eth", 3) == 0) { IOPportnum = atoi(&IOPname[3]); switch (iftype) { - case DLT_EN10MB: proto = "eth"; port = nonUnified_port_num(u, IOPportnum); break; - default: proto = "???"; port = unified_port_num(u, IOPportnum); break; + case DLT_EN10MB: + nonUnified_IOP_port_name(buf, sizeof buf, "eth", u); + break; + default: + unified_IOP_port_name(buf, sizeof buf, "???", u, IOPportnum); + break; } } else if (strncmp(IOPname, "wan", 3) == 0) { IOPportnum = atoi(&IOPname[3]); switch (iftype) { - case DLT_SITA: proto = "wan"; port = unified_port_num(u, IOPportnum); break; - default: proto = "???"; port = unified_port_num(u, IOPportnum); break; + case DLT_SITA: + unified_IOP_port_name(buf, sizeof buf, "wan", u, IOPportnum); + break; + default: + unified_IOP_port_name(buf, sizeof buf, "???", u, IOPportnum); + break; } + } else { + fprintf(stderr, "Error... invalid IOP name %s\n", IOPname); + return NULL; } - sprintf(buf, "%s_%s", proto, port); /* compose the user's name for that IOP port name */ name = malloc(strlen(buf) + 1); /* get memory for that name */ if (name == NULL) { /* oops, we didn't get the memory requested */ fprintf(stderr, "Error...couldn't allocate memory for IOP port name...value of errno is: %d\n", errno); @@ -714,6 +723,8 @@ static void wait_for_all_answers(void) { while (1) { int flag = 0; + fd_set working_set; + for (fd = 0; fd <= max_fs; fd++) { /* scan the list of descriptors we may be listening to */ if (FD_ISSET(fd, &readfds)) flag = 1; /* and see if there are any still set */ } @@ -931,7 +942,7 @@ static int pcap_read_acn(pcap_t *handle, int max_packets, pcap_handler callback, struct pcap_pkthdr pcap_header; //printf("pcap_read_acn()\n"); // fulko - acn_start_monitor(handle->fd, handle->snapshot, handle->md.timeout, handle->md.clear_promisc, handle->direction); /* maybe tell him to start monitoring */ + acn_start_monitor(handle->fd, handle->snapshot, handle->opt.timeout, handle->opt.promisc, handle->direction); /* maybe tell him to start monitoring */ //printf("pcap_read_acn() after start monitor\n"); // fulko handle->bp = packet_header; @@ -976,7 +987,6 @@ static int pcap_activate_sita(pcap_t *handle) { &handle->linktype); if (fd == -1) return PCAP_ERROR; - handle->md.clear_promisc = handle->md.promisc; handle->fd = fd; handle->bufsize = handle->snapshot; @@ -1002,7 +1012,7 @@ static int pcap_activate_sita(pcap_t *handle) { pcap_t *pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, 0); if (p == NULL) return (NULL); diff --git a/pcap-snf.c b/pcap-snf.c index f09952f9..6d215ea1 100644 --- a/pcap-snf.c +++ b/pcap-snf.c @@ -15,9 +15,21 @@ #include #include +#include + #include "pcap-int.h" #include "pcap-snf.h" +/* + * Private data for capturing on SNF devices. + */ +struct pcap_snf { + snf_handle_t snf_handle; /* opaque device handle */ + snf_ring_t snf_ring; /* opaque device ring handle */ + int snf_timeout; + int snf_boardnum; +}; + static int snf_set_datalink(pcap_t *p, int dlt) { @@ -31,7 +43,7 @@ snf_pcap_stats(pcap_t *p, struct pcap_stat *ps) struct snf_ring_stats stats; int rc; - if ((rc = snf_ring_getstats(p->md.snf_ring, &stats))) { + if ((rc = snf_ring_getstats(ps->snf_ring, &stats))) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_get_stats: %s", pcap_strerror(rc)); return -1; @@ -45,30 +57,36 @@ snf_pcap_stats(pcap_t *p, struct pcap_stat *ps) static void snf_platform_cleanup(pcap_t *p) { + struct pcap_snf *ps = p->private; + if (p == NULL) return; - snf_ring_close(p->md.snf_ring); - snf_close(p->md.snf_handle); + snf_ring_close(ps->snf_ring); + snf_close(ps->snf_handle); pcap_cleanup_live_common(p); } static int snf_getnonblock(pcap_t *p, char *errbuf) { - return (p->md.snf_timeout == 0); + struct pcap_snf *ps = p->private; + + return (ps->snf_timeout == 0); } static int snf_setnonblock(pcap_t *p, int nonblock, char *errbuf) { + struct pcap_snf *ps = p->private; + if (nonblock) - p->md.snf_timeout = 0; + ps->snf_timeout = 0; else { - if (p->md.timeout <= 0) - p->md.snf_timeout = -1; /* forever */ + if (p->opt.timeout <= 0) + ps->snf_timeout = -1; /* forever */ else - p->md.snf_timeout = p->md.timeout; + ps->snf_timeout = p->opt.timeout; } return (0); } @@ -91,6 +109,7 @@ snf_timestamp_to_timeval(const int64_t ts_nanosec) static int snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { + struct pcap_snf *ps = p->private; struct pcap_pkthdr hdr; int i, flags, err, caplen, n; struct snf_recv_req req; @@ -112,7 +131,7 @@ snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) } } - err = snf_ring_recv(p->md.snf_ring, p->md.snf_timeout, &req); + err = snf_ring_recv(ps->snf_ring, ps->snf_timeout, &req); if (err) { if (err == EBUSY || err == EAGAIN) @@ -158,8 +177,6 @@ snf_setfilter(pcap_t *p, struct bpf_program *fp) if (install_bpf_program(p, fp) < 0) return -1; - p->md.use_bpf = 0; - return (0); } @@ -174,6 +191,7 @@ snf_inject(pcap_t *p, const void *buf _U_, size_t size _U_) static int snf_activate(pcap_t* p) { + struct pcap_snf *ps = p->private; char *device = p->opt.source; const char *nr = NULL; int err; @@ -192,31 +210,31 @@ snf_activate(pcap_t* p) else nr = NULL; - err = snf_open(p->md.snf_boardnum, + err = snf_open(ps->snf_boardnum, 0, /* let SNF API parse SNF_NUM_RINGS, if set */ NULL, /* default RSS, or use SNF_RSS_FLAGS env */ 0, /* default to SNF_DATARING_SIZE from env */ flags, /* may want pshared */ - &p->md.snf_handle); + &ps->snf_handle); if (err != 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_open failed: %s", pcap_strerror(err)); return -1; } - err = snf_ring_open(p->md.snf_handle, &p->md.snf_ring); + err = snf_ring_open(ps->snf_handle, &ps->snf_ring); if (err != 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_ring_open failed: %s", pcap_strerror(err)); return -1; } - if (p->md.timeout <= 0) - p->md.snf_timeout = -1; + if (p->opt.timeout <= 0) + ps->snf_timeout = -1; else - p->md.snf_timeout = p->md.timeout; + ps->snf_timeout = p->opt.timeout; - err = snf_start(p->md.snf_handle); + err = snf_start(ps->snf_handle); if (err != 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_start failed: %s", pcap_strerror(err)); @@ -237,9 +255,6 @@ snf_activate(pcap_t* p) p->setnonblock_op = snf_setnonblock; p->stats_op = snf_pcap_stats; p->cleanup_op = snf_platform_cleanup; - p->md.stat.ps_recv = 0; - p->md.stat.ps_drop = 0; - p->md.stat.ps_ifdrop = 0; return 0; } @@ -260,6 +275,7 @@ snf_create(const char *device, char *ebuf, int *is_ours) int boardnum = -1; struct snf_ifaddrs *ifaddrs, *ifa; size_t devlen; + struct pcap_snf *ps; if (snf_init(SNF_VERSION_API)) { /* Can't initialize the API, so no SNF devices */ @@ -303,11 +319,12 @@ snf_create(const char *device, char *ebuf, int *is_ours) /* OK, it's probably ours. */ *is_ours = 1; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_snf)); if (p == NULL) return NULL; + ps = p->private; p->activate_op = snf_activate; - p->md.snf_boardnum = boardnum; + ps->snf_boardnum = boardnum; return p; } diff --git a/pcap-snit.c b/pcap-snit.c index b22b737f..c910c8b3 100644 --- a/pcap-snit.c +++ b/pcap-snit.c @@ -84,9 +84,17 @@ static const char rcsid[] _U_ = /* Forwards */ static int nit_setflags(int, int, int, char *); +/* + * Private data for capturing on STREAMS NIT devices. + */ +struct pcap_snit { + struct pcap_stat stat; +}; + static int pcap_stats_snit(pcap_t *p, struct pcap_stat *ps) { + struct pcap_snit *psn = p->private; /* * "ps_recv" counts packets handed to the filter, not packets @@ -105,13 +113,14 @@ pcap_stats_snit(pcap_t *p, struct pcap_stat *ps) * kernel by libpcap or packets not yet read from libpcap by the * application. */ - *ps = p->md.stat; + *ps = psn->stat; return (0); } static int pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { + struct pcap_snit *psn = p->private; register int cc, n; register u_char *bp, *cp, *ep; register struct nit_bufhdr *hdrp; @@ -160,7 +169,7 @@ pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user) } } - ++p->md.stat.ps_recv; + ++psn->stat.ps_recv; cp = bp; /* get past NIT buffer */ @@ -172,7 +181,7 @@ pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user) cp += sizeof(*ntp); ndp = (struct nit_ifdrops *)cp; - p->md.stat.ps_drop = ndp->nh_drops; + psn->stat.ps_drop = ndp->nh_drops; cp += sizeof *ndp; /* get past packet len */ @@ -349,7 +358,7 @@ pcap_activate_snit(pcap_t *p) pcap_strerror(errno)); goto bad; } - if (nit_setflags(p->fd, p->opt.promisc, p->md.timeout, p->errbuf) < 0) + if (nit_setflags(p->fd, p->opt.promisc, p->opt.timeout, p->errbuf) < 0) goto bad; (void)ioctl(fd, I_FLUSH, (char *)FLUSHR); @@ -411,7 +420,7 @@ pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_snit)); if (p == NULL) return (NULL); diff --git a/pcap-snoop.c b/pcap-snoop.c index 9314b8ce..7d0db139 100644 --- a/pcap-snoop.c +++ b/pcap-snoop.c @@ -58,9 +58,17 @@ static const char rcsid[] _U_ = #include "os-proto.h" #endif +/* + * Private data for capturing on snoop devices. + */ +struct pcap_snoop { + struct pcap_stat stat; +}; + static int pcap_read_snoop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { + struct pcap_snoop *psn = p->private; int cc; register struct snoopheader *sh; register u_int datalen; @@ -124,7 +132,7 @@ again: if (p->fcode.bf_insns == NULL || bpf_filter(p->fcode.bf_insns, cp, datalen, caplen)) { struct pcap_pkthdr h; - ++p->md.stat.ps_recv; + ++psn->stat.ps_recv; h.ts.tv_sec = sh->snoop_timestamp.tv_sec; h.ts.tv_usec = sh->snoop_timestamp.tv_usec; h.len = datalen; @@ -156,6 +164,7 @@ pcap_inject_snoop(pcap_t *p, const void *buf, size_t size) static int pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps) { + struct pcap_snoop *psn = p->private; register struct rawstats *rs; struct rawstats rawstats; @@ -180,7 +189,7 @@ pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps) * rather than just this socket? If not, why does it have * both Snoop and Drain statistics? */ - p->md.stat.ps_drop = + psn->stat.ps_drop = rs->rs_snoop.ss_ifdrops + rs->rs_snoop.ss_sbdrops + rs->rs_drain.ds_ifdrops + rs->rs_drain.ds_sbdrops; @@ -189,7 +198,7 @@ pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps) * As filtering is done in userland, this does not include * packets dropped because we ran out of buffer space. */ - *ps = p->md.stat; + *ps = psn->stat; return (0); } @@ -398,7 +407,7 @@ pcap_create_interface(const char *device, char *ebuf) { pcap_t *p; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_snoop)); if (p == NULL) return (NULL); diff --git a/pcap-usb-linux.c b/pcap-usb-linux.c index 26f61897..ff04baae 100644 --- a/pcap-usb-linux.c +++ b/pcap-usb-linux.c @@ -121,6 +121,16 @@ struct mon_bin_mfetch { #define MON_BIN_DATA_ZERO 0x4 /* data buffer is not available */ #define MON_BIN_ERROR 0x8 +/* + * Private data for capturing on Linux USB. + */ +struct pcap_usb_linux { + u_char *mmapbuf; /* memory-mapped region pointer */ + size_t mmapbuflen; /* size of region */ + int bus_index; + u_int packets_read; +}; + /* forward declaration */ static int usb_activate(pcap_t *); static int usb_stats_linux(pcap_t *, struct pcap_stat *); @@ -204,14 +214,15 @@ usb_findalldevs(pcap_if_t **alldevsp, char *err_str) static int usb_mmap(pcap_t* handle) { + struct pcap_usb_linux *handlep = handle->private; int len = ioctl(handle->fd, MON_IOCQ_RING_SIZE); if (len < 0) return 0; - handle->md.mmapbuflen = len; - handle->md.mmapbuf = mmap(0, handle->md.mmapbuflen, PROT_READ, + handlep->mmapbuflen = len; + handlep->mmapbuf = mmap(0, handlep->mmapbuflen, PROT_READ, MAP_SHARED, handle->fd, 0); - return handle->md.mmapbuf != MAP_FAILED; + return handlep->mmapbuf != MAP_FAILED; } #define CTRL_TIMEOUT (5*1000) /* milliseconds */ @@ -318,7 +329,7 @@ usb_create(const char *device, char *ebuf, int *is_ours) /* OK, it's probably ours. */ *is_ours = 1; - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_usb_linux)); if (p == NULL) return (NULL); @@ -329,6 +340,7 @@ usb_create(const char *device, char *ebuf, int *is_ours) static int usb_activate(pcap_t* handle) { + struct pcap_usb_linux *handlep = handle->private; char full_path[USB_LINE_LEN]; /* Initialize some components of the pcap structure. */ @@ -344,7 +356,7 @@ usb_activate(pcap_t* handle) handle->setnonblock_op = pcap_setnonblock_fd; /*get usb bus index from device name */ - if (sscanf(handle->opt.source, USB_IFACE"%d", &handle->md.ifindex) != 1) + if (sscanf(handle->opt.source, USB_IFACE"%d", &handlep->bus_index) != 1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get USB bus index from %s", handle->opt.source); @@ -352,7 +364,7 @@ usb_activate(pcap_t* handle) } /*now select the read method: try to open binary interface */ - snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handle->md.ifindex); + snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handlep->bus_index); handle->fd = open(full_path, O_RDONLY, 0); if (handle->fd >= 0) { @@ -370,7 +382,7 @@ usb_activate(pcap_t* handle) handle->stats_op = usb_stats_linux_bin; handle->read_op = usb_read_linux_mmap; handle->cleanup_op = usb_cleanup_linux_mmap; - probe_devices(handle->md.ifindex); + probe_devices(handlep->bus_index); /* * "handle->fd" is a real file, so "select()" and @@ -383,11 +395,11 @@ usb_activate(pcap_t* handle) /* can't mmap, use plain binary interface access */ handle->stats_op = usb_stats_linux_bin; handle->read_op = usb_read_linux_bin; - probe_devices(handle->md.ifindex); + probe_devices(handlep->bus_index); } else { /*Binary interface not available, try open text interface */ - snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handle->md.ifindex); + snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handlep->bus_index); handle->fd = open(full_path, O_RDONLY, 0); if (handle->fd < 0) { @@ -397,7 +409,7 @@ usb_activate(pcap_t* handle) * Not found at the new location; try * the old location. */ - snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handle->md.ifindex); + snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handlep->bus_index); handle->fd = open(full_path, O_RDONLY, 0); } if (handle->fd < 0) { @@ -456,6 +468,7 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u * /usr/src/linux/Documentation/usb/usbmon.txt * for message format */ + struct pcap_usb_linux *handlep = handle->private; unsigned timestamp; int tag, cnt, ep_num, dev_addr, dummy, ret, urb_len, data_len; char etype, pipeid1, pipeid2, status[16], urb_tag, line[USB_LINE_LEN]; @@ -500,7 +513,7 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u } uhdr->id = tag; uhdr->device_address = dev_addr; - uhdr->bus_id = handle->md.ifindex; + uhdr->bus_id = handlep->bus_index; uhdr->status = 0; string += cnt; @@ -639,7 +652,7 @@ got: if (handle->fcode.bf_insns == NULL || bpf_filter(handle->fcode.bf_insns, handle->buffer, pkth.len, pkth.caplen)) { - handle->md.packets_read++; + handlep->packets_read++; callback(user, &pkth, handle->buffer); return 1; } @@ -657,13 +670,14 @@ usb_inject_linux(pcap_t *handle, const void *buf, size_t size) static int usb_stats_linux(pcap_t *handle, struct pcap_stat *stats) { + struct pcap_usb_linux *handlep = handle->private; int dummy, ret, consumed, cnt; char string[USB_LINE_LEN]; char token[USB_LINE_LEN]; char * ptr = string; int fd; - snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handle->md.ifindex); + snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handlep->bus_index); fd = open(string, O_RDONLY, 0); if (fd < 0) { @@ -673,7 +687,7 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats) * Not found at the new location; try the old * location. */ - snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handle->md.ifindex); + snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handlep->bus_index); fd = open(string, O_RDONLY, 0); } if (fd < 0) { @@ -724,7 +738,7 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats) ptr += cnt; } - stats->ps_recv = handle->md.packets_read; + stats->ps_recv = handlep->packets_read; stats->ps_ifdrop = 0; return 0; } @@ -740,6 +754,7 @@ usb_setdirection_linux(pcap_t *p, pcap_direction_t d) static int usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats) { + struct pcap_usb_linux *handlep = handle->private; int ret; struct mon_bin_stats st; ret = ioctl(handle->fd, MON_IOCG_STATS, &st); @@ -750,7 +765,7 @@ usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats) return -1; } - stats->ps_recv = handle->md.packets_read + st.queued; + stats->ps_recv = handlep->packets_read + st.queued; stats->ps_drop = st.dropped; stats->ps_ifdrop = 0; return 0; @@ -763,6 +778,7 @@ usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats) static int usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { + struct pcap_usb_linux *handlep = handle->private; struct mon_bin_get info; int ret; struct pcap_pkthdr pkth; @@ -805,7 +821,7 @@ usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_cha if (handle->fcode.bf_insns == NULL || bpf_filter(handle->fcode.bf_insns, handle->buffer, pkth.len, pkth.caplen)) { - handle->md.packets_read++; + handlep->packets_read++; callback(user, &pkth, handle->buffer); return 1; } @@ -821,6 +837,7 @@ usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_cha static int usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { + struct pcap_usb_linux *handlep = handle->private; struct mon_bin_mfetch fetch; int32_t vec[VEC_SIZE]; struct pcap_pkthdr pkth; @@ -866,7 +883,7 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch nflush = fetch.nfetch; for (i=0; imd.mmapbuf[vec[i]]; + hdr = (pcap_usb_header*) &handlep->mmapbuf[vec[i]]; if (hdr->event_type == '@') continue; @@ -885,7 +902,7 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch if (handle->fcode.bf_insns == NULL || bpf_filter(handle->fcode.bf_insns, (u_char*) hdr, pkth.len, pkth.caplen)) { - handle->md.packets_read++; + handlep->packets_read++; callback(user, &pkth, (u_char*) hdr); packets++; } @@ -904,10 +921,12 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch static void usb_cleanup_linux_mmap(pcap_t* handle) { + struct pcap_usb_linux *handlep = handle->private; + /* if we have a memory-mapped buffer, unmap it */ - if (handle->md.mmapbuf != NULL) { - munmap(handle->md.mmapbuf, handle->md.mmapbuflen); - handle->md.mmapbuf = NULL; + if (handlep->mmapbuf != NULL) { + munmap(handlep->mmapbuf, handlep->mmapbuflen); + handlep->mmapbuf = NULL; } pcap_cleanup_live_common(handle); } diff --git a/pcap-win32.c b/pcap-win32.c index 130a4429..a490d0b2 100644 --- a/pcap-win32.c +++ b/pcap-win32.c @@ -71,6 +71,17 @@ static int pcap_setnonblock_win32(pcap_t *, int, char *); /* Equivalent to ntohs(), but a lot faster under Windows */ #define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8) +/* + * Private data for capturing on WinPcap devices. + */ +struct pcap_win { + int nonblock; + +#ifdef HAVE_DAG_API + int dag_fcs_bits; /* Number of checksum bits from link layer */ +#endif +}; + /* * Header that the WinPcap driver associates to the packets. * Once was in bpf.h @@ -253,6 +264,7 @@ pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) static int pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { + struct pcap_win *pw = p->private; u_char *dp = NULL; int packet_len = 0, caplen = 0; struct pcap_pkthdr pcap_header; @@ -295,7 +307,7 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) break; /* Increase the number of captured packets */ - p->md.stat.ps_recv++; + pw->stat.ps_recv++; /* Find the beginning of the packet */ dp = ((u_char *)header) + dag_record_size; @@ -312,7 +324,7 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) case TYPE_ETH: swt = SWAPS(header->wlen); - packet_len = swt - (p->md.dag_fcs_bits); + packet_len = swt - (pw->dag_fcs_bits); caplen = erf_record_len - dag_record_size - 2; if (caplen > packet_len) { @@ -324,7 +336,7 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) case TYPE_HDLC_POS: swt = SWAPS(header->wlen); - packet_len = swt - (p->md.dag_fcs_bits); + packet_len = swt - (pw->dag_fcs_bits); caplen = erf_record_len - dag_record_size; if (caplen > packet_len) { @@ -457,6 +469,7 @@ pcap_cleanup_win32(pcap_t *p) static int pcap_activate_win32(pcap_t *p) { + struct pcap_win *pw = p->private; NetType type; if (p->opt.rfmon) { @@ -672,13 +685,13 @@ pcap_activate_win32(pcap_t *p) /* Set the length of the FCS associated to any packet. This value * will be subtracted to the packet length */ - p->md.dag_fcs_bits = p->adapter->DagFcsLen; + pw->dag_fcs_bits = p->adapter->DagFcsLen; } #else goto bad; #endif /* HAVE_DAG_API */ - PacketSetReadTimeout(p->adapter, p->md.timeout); + PacketSetReadTimeout(p->adapter, p->opt.timeout); #ifdef HAVE_DAG_API if(p->adapter->Flags & INFO_FLAG_DAG_CARD) @@ -743,12 +756,12 @@ pcap_create_interface(const char *device, char *ebuf) } snprintf(deviceAscii, length + 1, "%ws", (wchar_t*)device); - p = pcap_create_common(deviceAscii, ebuf); + p = pcap_create_common(deviceAscii, ebuf, sizeof (struct pcap_win)); free(deviceAscii); } else { - p = pcap_create_common(device, ebuf); + p = pcap_create_common(device, ebuf, sizeof (struct pcap_win)); } if (p == NULL) @@ -801,25 +814,26 @@ pcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) { return -1; } - p->md.use_bpf = 0; - return (0); } static int pcap_getnonblock_win32(pcap_t *p, char *errbuf) { + struct pcap_win *pw = p->private; + /* * XXX - if there were a PacketGetReadTimeout() call, we * would use it, and return 1 if the timeout is -1 * and 0 otherwise. */ - return (p->nonblock); + return (pw->nonblock); } static int pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf) { + struct pcap_win *pw = p->private; int newtimeout; if (nonblock) { @@ -833,14 +847,14 @@ pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf) * (Note that this may be -1, in which case we're not * really leaving non-blocking mode.) */ - newtimeout = p->md.timeout; + newtimeout = p->opt.timeout; } if (!PacketSetReadTimeout(p->adapter, newtimeout)) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "PacketSetReadTimeout: %s", pcap_win32strerror()); return (-1); } - p->nonblock = (newtimeout == -1); + pw->nonblock = (newtimeout == -1); return (0); } diff --git a/pcap.c b/pcap.c index 0bf845db..b69e9ed9 100644 --- a/pcap.c +++ b/pcap.c @@ -226,7 +226,7 @@ pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, /* Saves a pointer to the packet headers */ *pkt_header= &p->pcap_header; - if (p->sf.rfile != NULL) { + if (p->rfile != NULL) { int status; /* We are on an offline capture */ @@ -469,24 +469,59 @@ initialize_ops(pcap_t *p) p->oneshot_callback = pcap_oneshot; } -pcap_t * -pcap_create_common(const char *source, char *ebuf) +static pcap_t * +pcap_alloc_pcap_t(char *ebuf, size_t size) { + char *chunk; pcap_t *p; - p = malloc(sizeof(*p)); - if (p == NULL) { + /* + * Allocate a chunk of memory big enough for a pcap_t + * plus a structure following it of size "size". The + * structure following it is a private data structure + * for the routines that handle this pcap_t. + */ + chunk = malloc(sizeof (pcap_t) + size); + if (chunk == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return (NULL); } - memset(p, 0, sizeof(*p)); + memset(chunk, 0, sizeof (pcap_t) + size); + + /* + * Get a pointer to the pcap_t at the beginning. + */ + p = (pcap_t *)chunk; + #ifndef WIN32 p->fd = -1; /* not opened yet */ p->selectable_fd = -1; - p->send_fd = -1; #endif + if (size == 0) { + /* No private data was requested. */ + p->private = NULL; + } else { + /* + * Set the pointer to the private data; that's the structure + * of size "size" following the pcap_t. + */ + p->private = (void *)(chunk + sizeof (pcap_t)); + } + + return (p); +} + +pcap_t * +pcap_create_common(const char *source, char *ebuf, size_t size) +{ + pcap_t *p; + + p = pcap_alloc_pcap_t(ebuf, size); + if (p == NULL) + return (NULL); + p->opt.source = strdup(source); if (p->opt.source == NULL) { snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", @@ -557,7 +592,7 @@ pcap_set_timeout(pcap_t *p, int timeout_ms) { if (pcap_check_activated(p)) return (PCAP_ERROR_ACTIVATED); - p->md.timeout = timeout_ms; + p->opt.timeout = timeout_ms; return (0); } @@ -692,6 +727,26 @@ fail: return (NULL); } +pcap_t * +pcap_open_offline_common(char *ebuf, size_t size) +{ + pcap_t *p; + + p = pcap_alloc_pcap_t(ebuf, size); + if (p == NULL) + return (NULL); + + p->opt.source = strdup("(savefile)"); + if (p->opt.source == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", + pcap_strerror(errno)); + free(p); + return (NULL); + } + + return (p); +} + int pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { @@ -714,7 +769,7 @@ pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) register int n; for (;;) { - if (p->sf.rfile != NULL) { + if (p->rfile != NULL) { /* * 0 means EOF, so don't loop if we get 0. */ @@ -1168,25 +1223,25 @@ pcap_snapshot(pcap_t *p) int pcap_is_swapped(pcap_t *p) { - return (p->sf.swapped); + return (p->swapped); } int pcap_major_version(pcap_t *p) { - return (p->sf.version_major); + return (p->version_major); } int pcap_minor_version(pcap_t *p) { - return (p->sf.version_minor); + return (p->version_minor); } FILE * pcap_file(pcap_t *p) { - return (p->sf.rfile); + return (p->rfile); } int @@ -1561,7 +1616,7 @@ pcap_do_addexit(pcap_t *p) void pcap_add_to_pcaps_to_close(pcap_t *p) { - p->md.next = pcaps_to_close; + p->next = pcaps_to_close; pcaps_to_close = p; } @@ -1571,7 +1626,7 @@ pcap_remove_from_pcaps_to_close(pcap_t *p) pcap_t *pc, *prevpc; for (pc = pcaps_to_close, prevpc = NULL; pc != NULL; - prevpc = pc, pc = pc->md.next) { + prevpc = pc, pc = pc->next) { if (pc == p) { /* * Found it. Remove it from the list. @@ -1580,12 +1635,12 @@ pcap_remove_from_pcaps_to_close(pcap_t *p) /* * It was at the head of the list. */ - pcaps_to_close = pc->md.next; + pcaps_to_close = pc->next; } else { /* * It was in the middle of the list. */ - prevpc->md.next = pc->md.next; + prevpc->next = pc->next; } break; } @@ -1616,7 +1671,6 @@ pcap_cleanup_live_common(pcap_t *p) p->fd = -1; } p->selectable_fd = -1; - p->send_fd = -1; #endif } diff --git a/savefile.c b/savefile.c index 8115749b..ad3f6bda 100644 --- a/savefile.c +++ b/savefile.c @@ -163,8 +163,8 @@ sf_setdirection(pcap_t *p, pcap_direction_t d) static void sf_cleanup(pcap_t *p) { - if (p->sf.rfile != stdin) - (void)fclose(p->sf.rfile); + if (p->rfile != stdin) + (void)fclose(p->rfile); if (p->buffer != NULL) free(p->buffer); pcap_freecode(&p->fcode); @@ -231,7 +231,7 @@ pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf) } #endif -static int (*check_headers[])(pcap_t *, bpf_u_int32, FILE *, char *) = { +static pcap_t *(*check_headers[])(bpf_u_int32, FILE *, char *, int *) = { pcap_check_header, pcap_ng_check_header }; @@ -248,10 +248,7 @@ pcap_fopen_offline(FILE *fp, char *errbuf) bpf_u_int32 magic; size_t amt_read; u_int i; - - p = pcap_create_common("(savefile)", errbuf); - if (p == NULL) - return (NULL); + int err; /* * Read the first 4 bytes of the file; the network analyzer dump @@ -272,26 +269,23 @@ pcap_fopen_offline(FILE *fp, char *errbuf) (unsigned long)sizeof(magic), (unsigned long)amt_read); } - goto bad; + return (NULL); } /* * Try all file types. */ for (i = 0; i < N_FILE_TYPES; i++) { - switch ((*check_headers[i])(p, magic, fp, errbuf)) { - - case -1: + p = (*check_headers[i])(magic, fp, errbuf, &err); + if (p != NULL) { + /* Yup, that's it. */ + goto found; + } + if (err) { /* * Error trying to read the header. */ - goto bad; - - case 1: - /* - * Yup, that's it. - */ - goto found; + return (NULL); } } @@ -299,15 +293,13 @@ pcap_fopen_offline(FILE *fp, char *errbuf) * Well, who knows what this mess is.... */ snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format"); - goto bad; + return (NULL); found: - p->sf.rfile = fp; + p->rfile = fp; -#ifdef PCAP_FDDIPAD /* Padding only needed for live capture fcode */ p->fddipad = 0; -#endif #if !defined(WIN32) && !defined(MSDOS) /* @@ -337,9 +329,6 @@ found: p->activated = 1; return (p); - bad: - free(p); - return (NULL); } /* @@ -375,7 +364,7 @@ pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) return (n); } - status = p->sf.next_packet_op(p, &h, &data); + status = p->next_packet_op(p, &h, &data); if (status) { if (status == 1) return (0); diff --git a/sf-pcap-ng.c b/sf-pcap-ng.c index 7eb6db76..a34cf317 100644 --- a/sf-pcap-ng.c +++ b/sf-pcap-ng.c @@ -201,6 +201,13 @@ struct block_cursor { bpf_u_int32 block_type; }; +struct pcap_ng_sf { + bpf_u_int32 ifcount; /* number of interfaces seen in this capture */ + u_int tsresol; /* time stamp resolution */ + u_int tsscale; /* scaling factor for resolution -> microseconds */ + u_int64_t tsoffset; /* time stamp offset */ +}; + static int pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data); @@ -239,7 +246,7 @@ read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf) if (status <= 0) return (status); /* error or EOF */ - if (p->sf.swapped) { + if (p->swapped) { bhdr.block_type = SWAPLONG(bhdr.block_type); bhdr.total_length = SWAPLONG(bhdr.total_length); } @@ -346,7 +353,7 @@ get_opthdr_from_block_data(pcap_t *p, struct block_cursor *cursor, char *errbuf) /* * Byte-swap it if necessary. */ - if (p->sf.swapped) { + if (p->swapped) { opthdr->option_code = SWAPSHORT(opthdr->option_code); opthdr->option_length = SWAPSHORT(opthdr->option_length); } @@ -481,7 +488,7 @@ process_idb_options(pcap_t *p, struct block_cursor *cursor, u_int *tsresol, } saw_tsoffset = 1; memcpy(tsoffset, optvalue, sizeof(*tsoffset)); - if (p->sf.swapped) + if (p->swapped) *tsoffset = SWAPLL(*tsoffset); break; @@ -498,18 +505,26 @@ done: * Check whether this is a pcap-ng savefile and, if it is, extract the * relevant information from the header. */ -int -pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) +pcap_t * +pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, char *errbuf, int *err) { size_t amt_read; bpf_u_int32 total_length; bpf_u_int32 byte_order_magic; struct block_header *bhdrp; struct section_header_block *shbp; + pcap_t *p; + int swapped = 0; + struct pcap_ng_sf *ps; int status; struct block_cursor cursor; struct interface_description_block *idbp; + /* + * Assume no read errors. + */ + *err = 0; + /* * Check whether the first 4 bytes of the file are the block * type for a pcap-ng savefile. @@ -524,7 +539,7 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) * this as possibly being a pcap-ng file transferred * between UN*X and Windows in text file format? */ - return (0); /* nope */ + return (NULL); /* nope */ } /* @@ -544,14 +559,15 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) snprintf(errbuf, PCAP_ERRBUF_SIZE, "error reading dump file: %s", pcap_strerror(errno)); - return (-1); /* fail */ + *err = 1; + return (NULL); /* fail */ } /* * Possibly a weird short text file, so just say * "not pcap-ng". */ - return (0); + return (NULL); } amt_read = fread(&byte_order_magic, 1, sizeof(byte_order_magic), fp); if (amt_read < sizeof(byte_order_magic)) { @@ -559,14 +575,15 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) snprintf(errbuf, PCAP_ERRBUF_SIZE, "error reading dump file: %s", pcap_strerror(errno)); - return (-1); /* fail */ + *err = 1; + return (NULL); /* fail */ } /* * Possibly a weird short text file, so just say * "not pcap-ng". */ - return (0); + return (NULL); } if (byte_order_magic != BYTE_ORDER_MAGIC) { byte_order_magic = SWAPLONG(byte_order_magic); @@ -574,9 +591,9 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) /* * Not a pcap-ng file. */ - return (0); + return (NULL); } - p->sf.swapped = 1; + swapped = 1; total_length = SWAPLONG(total_length); } @@ -588,9 +605,23 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) "Section Header Block in pcap-ng dump file has a length of %u < %lu", total_length, (unsigned long)(sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer))); - return (-1); + *err = 1; + return (NULL); } + /* + * OK, this is a good pcap-ng file. + * Allocate a pcap_t for it. + */ + p = pcap_open_offline_common(errbuf, sizeof (struct pcap_ng_sf)); + if (p == NULL) { + /* Allocation failed. */ + *err = 1; + return (NULL); + } + p->swapped = swapped; + ps = p->private; + /* * Allocate a buffer into which to read blocks. We default to * the maximum of: @@ -609,7 +640,9 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) p->buffer = malloc(p->bufsize); if (p->buffer == NULL) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory"); - return (-1); + free(p); + *err = 1; + return (NULL); } /* @@ -627,7 +660,7 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) 1, errbuf) == -1) goto fail; - if (p->sf.swapped) { + if (p->swapped) { /* * Byte-swap the fields we've read. */ @@ -644,15 +677,15 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) shbp->major_version); goto fail; } - p->sf.version_major = shbp->major_version; - p->sf.version_minor = shbp->minor_version; + p->version_major = shbp->major_version; + p->version_minor = shbp->minor_version; /* * Set the default time stamp resolution and offset. */ - p->sf.tsresol = 1000000; /* microsecond resolution */ - p->sf.tsscale = 1; /* multiply by 1 to scale to microseconds */ - p->sf.tsoffset = 0; /* absolute timestamps */ + ps->tsresol = 1000000; /* microsecond resolution */ + ps->tsscale = 1; /* multiply by 1 to scale to microseconds */ + ps->tsoffset = 0; /* absolute timestamps */ /* * Now start looking for an Interface Description Block. @@ -685,7 +718,7 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) /* * Byte-swap it if necessary. */ - if (p->sf.swapped) { + if (p->swapped) { idbp->linktype = SWAPSHORT(idbp->linktype); idbp->snaplen = SWAPLONG(idbp->snaplen); } @@ -693,14 +726,14 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) /* * Count this interface. */ - p->sf.ifcount++; + ps->ifcount++; /* * Now look for various time stamp options, so * we know how to interpret the time stamps. */ - if (process_idb_options(p, &cursor, &p->sf.tsresol, - &p->sf.tsoffset, errbuf) == -1) + if (process_idb_options(p, &cursor, &ps->tsresol, + &ps->tsoffset, errbuf) == -1) goto fail; /* @@ -708,18 +741,18 @@ pcap_ng_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) * sub-second part of the time stamp to * microseconds. */ - if (p->sf.tsresol > 1000000) { + if (ps->tsresol > 1000000) { /* * Higher than microsecond resolution; * scale down to microseconds. */ - p->sf.tsscale = (p->sf.tsresol / 1000000); + ps->tsscale = (ps->tsresol / 1000000); } else { /* * Lower than microsecond resolution; * scale up to microseconds. */ - p->sf.tsscale = (1000000 / p->sf.tsresol); + ps->tsscale = (1000000 / ps->tsresol); } goto done; @@ -749,13 +782,15 @@ done: p->linktype = linktype_to_dlt(idbp->linktype); p->linktype_ext = 0; - p->sf.next_packet_op = pcap_ng_next_packet; + p->next_packet_op = pcap_ng_next_packet; - return (1); + return (p); fail: free(p->buffer); - return (-1); + free(p); + *err = 1; + return (NULL); } /* @@ -766,6 +801,7 @@ fail: static int pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) { + struct pcap_ng_sf *ps = p->private; struct block_cursor cursor; int status; struct enhanced_packet_block *epbp; @@ -774,7 +810,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) bpf_u_int32 interface_id = 0xFFFFFFFF; struct interface_description_block *idbp; struct section_header_block *shbp; - FILE *fp = p->sf.rfile; + FILE *fp = p->rfile; u_int tsresol; u_int64_t tsoffset; u_int64_t t, sec, frac; @@ -808,7 +844,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) /* * Byte-swap it if necessary. */ - if (p->sf.swapped) { + if (p->swapped) { /* these were written in opposite byte order */ interface_id = SWAPLONG(epbp->interface_id); hdr->caplen = SWAPLONG(epbp->caplen); @@ -843,7 +879,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) /* * Byte-swap it if necessary. */ - if (p->sf.swapped) { + if (p->swapped) { /* these were written in opposite byte order */ hdr->len = SWAPLONG(spbp->len); } else @@ -873,7 +909,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) /* * Byte-swap it if necessary. */ - if (p->sf.swapped) { + if (p->swapped) { /* these were written in opposite byte order */ interface_id = SWAPSHORT(pbp->interface_id); hdr->caplen = SWAPLONG(pbp->caplen); @@ -902,7 +938,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) /* * Byte-swap it if necessary. */ - if (p->sf.swapped) { + if (p->swapped) { idbp->linktype = SWAPSHORT(idbp->linktype); idbp->snaplen = SWAPLONG(idbp->snaplen); } @@ -931,7 +967,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) /* * Count this interface. */ - p->sf.ifcount++; + ps->ifcount++; /* * Set the default time stamp resolution and offset. @@ -950,12 +986,12 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) if (process_idb_options(p, &cursor, &tsresol, &tsoffset, p->errbuf) == -1) return (-1); - if (tsresol != p->sf.tsresol) { + if (tsresol != ps->tsresol) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "an interface has a time stamp resolution different from the time stamp resolution of the first interface"); return (-1); } - if (tsoffset != p->sf.tsoffset) { + if (tsoffset != ps->tsoffset) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "an interface has a time stamp offset different from the time stamp offset of the first interface"); return (-1); @@ -977,7 +1013,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) * the same as that of the previous section. * We'll check for that later. */ - if (p->sf.swapped) { + if (p->swapped) { shbp->byte_order_magic = SWAPLONG(shbp->byte_order_magic); shbp->major_version = @@ -1034,7 +1070,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) * any IDBs, we'll fail when we see a packet * block.) */ - p->sf.ifcount = 0; + ps->ifcount = 0; break; default: @@ -1049,7 +1085,7 @@ found: /* * Is the interface ID an interface we know? */ - if (interface_id >= p->sf.ifcount) { + if (interface_id >= ps->ifcount) { /* * Yes. Fail. */ @@ -1062,20 +1098,20 @@ found: /* * Convert the time stamp to a struct timeval. */ - sec = t / p->sf.tsresol + p->sf.tsoffset; - frac = t % p->sf.tsresol; - if (p->sf.tsresol > 1000000) { + sec = t / ps->tsresol + ps->tsoffset; + frac = t % ps->tsresol; + if (ps->tsresol > 1000000) { /* * Higher than microsecond resolution; scale down to * microseconds. */ - frac /= p->sf.tsscale; + frac /= ps->tsscale; } else { /* * Lower than microsecond resolution; scale up to * microseconds. */ - frac *= p->sf.tsscale; + frac *= ps->tsscale; } hdr->ts.tv_sec = sec; hdr->ts.tv_usec = frac; @@ -1087,7 +1123,7 @@ found: if (*data == NULL) return (-1); - if (p->sf.swapped) { + if (p->swapped) { /* * Convert pseudo-headers from the byte order of * the host on which the file was saved to our diff --git a/sf-pcap-ng.h b/sf-pcap-ng.h index cc551824..abeb0181 100644 --- a/sf-pcap-ng.h +++ b/sf-pcap-ng.h @@ -26,6 +26,7 @@ #ifndef sf_pcap_ng_h #define sf_pcap_ng_h -extern int pcap_ng_check_header(pcap_t *, bpf_u_int32, FILE *, char *); +extern pcap_t *pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, char *errbuf, + int *err); #endif diff --git a/sf-pcap.c b/sf-pcap.c index 2b31a2b7..3344a2f3 100644 --- a/sf-pcap.c +++ b/sf-pcap.c @@ -122,15 +122,37 @@ static const char rcsid[] _U_ = static int pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **datap); +/* + * Private data for reading pcap savefiles. + */ +typedef enum { + NOT_SWAPPED, + SWAPPED, + MAYBE_SWAPPED +} swapped_type_t; + +struct pcap_sf { + size_t hdrsize; + swapped_type_t lengths_swapped; +}; + /* * Check whether this is a pcap savefile and, if it is, extract the * relevant information from the header. */ -int -pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) +pcap_t * +pcap_check_header(bpf_u_int32 magic, FILE *fp, char *errbuf, int *err) { struct pcap_file_header hdr; size_t amt_read; + pcap_t *p; + int swapped = 0; + struct pcap_sf *ps; + + /* + * Assume no read errors. + */ + *err = 0; /* * Check whether the first 4 bytes of the file are the magic @@ -140,8 +162,8 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC) { magic = SWAPLONG(magic); if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC) - return (0); /* nope */ - p->sf.swapped = 1; + return (NULL); /* nope */ + swapped = 1; } /* @@ -162,13 +184,14 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) (unsigned long)sizeof(hdr), (unsigned long)amt_read); } - return (-1); + *err = 1; + return (NULL); } /* * If it's a byte-swapped capture file, byte-swap the header. */ - if (p->sf.swapped) { + if (swapped) { hdr.version_major = SWAPSHORT(hdr.version_major); hdr.version_minor = SWAPSHORT(hdr.version_minor); hdr.thiszone = SWAPLONG(hdr.thiszone); @@ -180,16 +203,31 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) if (hdr.version_major < PCAP_VERSION_MAJOR) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "archaic pcap savefile format"); - return (-1); + *err = 1; + return (NULL); + } + + /* + * OK, this is a good pcap file. + * Allocate a pcap_t for it. + */ + p = pcap_open_offline_common(errbuf, sizeof (struct pcap_sf)); + if (p == NULL) { + /* Allocation failed. */ + *err = 1; + return (NULL); } - p->sf.version_major = hdr.version_major; - p->sf.version_minor = hdr.version_minor; + p->swapped = swapped; + p->version_major = hdr.version_major; + p->version_minor = hdr.version_minor; p->tzoff = hdr.thiszone; p->snapshot = hdr.snaplen; p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype)); p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype); - p->sf.next_packet_op = pcap_next_packet; + p->next_packet_op = pcap_next_packet; + + ps = p->private; /* * We interchanged the caplen and len fields at version 2.3, @@ -205,19 +243,19 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) case 2: if (hdr.version_minor < 3) - p->sf.lengths_swapped = SWAPPED; + ps->lengths_swapped = SWAPPED; else if (hdr.version_minor == 3) - p->sf.lengths_swapped = MAYBE_SWAPPED; + ps->lengths_swapped = MAYBE_SWAPPED; else - p->sf.lengths_swapped = NOT_SWAPPED; + ps->lengths_swapped = NOT_SWAPPED; break; case 543: - p->sf.lengths_swapped = SWAPPED; + ps->lengths_swapped = SWAPPED; break; default: - p->sf.lengths_swapped = NOT_SWAPPED; + ps->lengths_swapped = NOT_SWAPPED; break; } @@ -239,7 +277,7 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) * data ourselves and read from that buffer in order to * make that work. */ - p->sf.hdrsize = sizeof(struct pcap_sf_patched_pkthdr); + ps->hdrsize = sizeof(struct pcap_sf_patched_pkthdr); if (p->linktype == DLT_EN10MB) { /* @@ -265,7 +303,7 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) p->snapshot += 14; } } else - p->sf.hdrsize = sizeof(struct pcap_sf_pkthdr); + ps->hdrsize = sizeof(struct pcap_sf_pkthdr); /* * Allocate a buffer for the packet data. @@ -280,10 +318,12 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) p->buffer = malloc(p->bufsize); if (p->buffer == NULL) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory"); - return (-1); + free(p); + *err = 1; + return (NULL); } - return (1); + return (p); } /* @@ -294,8 +334,9 @@ pcap_check_header(pcap_t *p, bpf_u_int32 magic, FILE *fp, char *errbuf) static int pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) { + struct pcap_sf *ps = p->private; struct pcap_sf_patched_pkthdr sf_hdr; - FILE *fp = p->sf.rfile; + FILE *fp = p->rfile; size_t amt_read; bpf_u_int32 t; @@ -306,8 +347,8 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) * unpatched libpcap we only read as many bytes as the regular * header has. */ - amt_read = fread(&sf_hdr, 1, p->sf.hdrsize, fp); - if (amt_read != p->sf.hdrsize) { + amt_read = fread(&sf_hdr, 1, ps->hdrsize, fp); + if (amt_read != ps->hdrsize) { if (ferror(fp)) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "error reading dump file: %s", @@ -317,7 +358,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) if (amt_read != 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "truncated dump file; tried to read %lu header bytes, only got %lu", - (unsigned long)p->sf.hdrsize, + (unsigned long)ps->hdrsize, (unsigned long)amt_read); return (-1); } @@ -326,7 +367,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) } } - if (p->sf.swapped) { + if (p->swapped) { /* these were written in opposite byte order */ hdr->caplen = SWAPLONG(sf_hdr.caplen); hdr->len = SWAPLONG(sf_hdr.len); @@ -339,7 +380,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) hdr->ts.tv_usec = sf_hdr.ts.tv_usec; } /* Swap the caplen and len fields, if necessary. */ - switch (p->sf.lengths_swapped) { + switch (ps->lengths_swapped) { case NOT_SWAPPED: break; @@ -430,7 +471,7 @@ pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) } *data = p->buffer; - if (p->sf.swapped) { + if (p->swapped) { /* * Convert pseudo-headers from the byte order of * the host on which the file was saved to our diff --git a/sf-pcap.h b/sf-pcap.h index 3b3fbe89..fce6ee58 100644 --- a/sf-pcap.h +++ b/sf-pcap.h @@ -31,6 +31,7 @@ #ifndef sf_pcap_h #define sf_pcap_h -extern int pcap_check_header(pcap_t *, bpf_u_int32, FILE *, char *); +extern pcap_t *pcap_check_header(bpf_u_int32 magic, FILE *fp, char *errbuf, + int *err); #endif