diff options
-rw-r--r-- | dlpisubs.c | 10 | ||||
-rw-r--r-- | dlpisubs.h | 16 | ||||
-rw-r--r-- | gencode.c | 21 | ||||
-rw-r--r-- | pcap-bpf.c | 212 | ||||
-rw-r--r-- | pcap-bt-linux.c | 19 | ||||
-rw-r--r-- | pcap-can-linux.c | 18 | ||||
-rw-r--r-- | pcap-canusb-linux.c | 114 | ||||
-rw-r--r-- | pcap-dag.c | 140 | ||||
-rw-r--r-- | pcap-dbus.c | 60 | ||||
-rw-r--r-- | pcap-dlpi.c | 48 | ||||
-rw-r--r-- | pcap-dos.c | 43 | ||||
-rw-r--r-- | pcap-int.h | 242 | ||||
-rw-r--r-- | pcap-libdlpi.c | 34 | ||||
-rw-r--r-- | pcap-linux.c | 354 | ||||
-rw-r--r-- | pcap-netfilter-linux.c | 17 | ||||
-rw-r--r-- | pcap-nit.c | 19 | ||||
-rw-r--r-- | pcap-pf.c | 70 | ||||
-rw-r--r-- | pcap-septel.c | 24 | ||||
-rw-r--r-- | pcap-sita.c | 86 | ||||
-rw-r--r-- | pcap-snf.c | 63 | ||||
-rw-r--r-- | pcap-snit.c | 19 | ||||
-rw-r--r-- | pcap-snoop.c | 17 | ||||
-rw-r--r-- | pcap-usb-linux.c | 63 | ||||
-rw-r--r-- | pcap-win32.c | 38 | ||||
-rw-r--r-- | pcap.c | 90 | ||||
-rw-r--r-- | savefile.c | 41 | ||||
-rw-r--r-- | sf-pcap-ng.c | 130 | ||||
-rw-r--r-- | sf-pcap-ng.h | 3 | ||||
-rw-r--r-- | sf-pcap.c | 93 | ||||
-rw-r--r-- | sf-pcap.h | 3 |
30 files changed, 1232 insertions, 875 deletions
@@ -66,6 +66,8 @@ static const char rcsid[] _U_ = #include <stropts.h> #include <unistd.h> +#include <libdlpi.h> + #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; @@ -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); @@ -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); @@ -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 <unistd.h> #include <fcntl.h> #include <string.h> +#include <pthread.h> #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; i<status.rxsz; i++) { - libusb_bulk_transfer(dev, 0x85, (unsigned char*)&msg, sizeof(msg), &sz, 100); - n = write(canusb->wrpipe, &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; @@ -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); @@ -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; } } @@ -42,10 +42,6 @@ extern "C" { #endif -#ifdef HAVE_LIBDLPI -#include <libdlpi.h> -#endif - #ifdef WIN32 #include <Packet32.h> extern CRITICAL_SECTION g_PcapCompileCriticalSection; @@ -56,10 +52,6 @@ extern CRITICAL_SECTION g_PcapCompileCriticalSection; #include <io.h> #endif -#ifdef HAVE_SNF_API -#include <snf.h> -#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 <sys/param.h> /* 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,29 +168,9 @@ 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(). */ u_char *pkt; @@ -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 @@ -284,6 +284,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. */ static void map_arphrd_to_dlt(pcap_t *, int, int); @@ -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; i<req.tp_block_nr; ++i) { - void *base = &handle->md.mmapbuf[i*req.tp_block_size]; + void *base = &handlep->mmapbuf[i*req.tp_block_size]; for (j=0; j<frames_per_block; ++j, ++handle->offset) { 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); @@ -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); @@ -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 @@ -51,12 +51,20 @@ 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 * error occured, or -2 if we were told to break out of the loop. */ 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); @@ -15,9 +15,21 @@ #include <sys/types.h> #include <unistd.h> +#include <snf.h> + #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; i<fetch.nfetch; ++i) { /* discard filler */ - hdr = (pcap_usb_header*) &handle->md.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 @@ -72,6 +72,17 @@ static int pcap_setnonblock_win32(pcap_t *, int, char *); #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); } @@ -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 } @@ -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,19 +505,27 @@ 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,10 +605,24 @@ 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 @@ -123,14 +123,36 @@ 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 @@ -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 |