summaryrefslogtreecommitdiffstats
path: root/freebsd/contrib/libpcap/pcap-bpf.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/contrib/libpcap/pcap-bpf.c')
-rw-r--r--freebsd/contrib/libpcap/pcap-bpf.c931
1 files changed, 671 insertions, 260 deletions
diff --git a/freebsd/contrib/libpcap/pcap-bpf.c b/freebsd/contrib/libpcap/pcap-bpf.c
index 8375308f..60111cf5 100644
--- a/freebsd/contrib/libpcap/pcap-bpf.c
+++ b/freebsd/contrib/libpcap/pcap-bpf.c
@@ -22,10 +22,6 @@
*
* $FreeBSD$
*/
-#ifndef lint
-static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.116 2008-09-16 18:42:29 guy Exp $ (LBL)";
-#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -56,6 +52,15 @@ static const char rcsid[] _U_ =
#endif
#include <sys/utsname.h>
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+/*
+ * Add support for capturing on FreeBSD usbusN interfaces.
+ */
+static const char usbus_prefix[] = "usbus";
+#define USBUS_PREFIX_LEN (sizeof(usbus_prefix) - 1)
+#include <dirent.h>
+#endif
+
#ifdef HAVE_ZEROCOPY_BPF
#include <machine/atomic.h>
#endif
@@ -130,9 +135,68 @@ 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 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;
+ int nonblock; /* true if in nonblocking mode */
+#endif /* HAVE_ZEROCOPY_BPF */
+
+ char *device; /* device name */
+ int filtering_in_kernel; /* using kernel filter */
+ 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 */
+#define MUST_DESTROY_USBUS 0x00000002 /* destroy usbusN interface */
+
#ifdef BIOCGDLTLIST
# if (defined(HAVE_NET_IF_MEDIA_H) && defined(IFM_IEEE80211)) && !defined(__APPLE__)
#define HAVE_BSD_IEEE80211
+
+/*
+ * The ifm_ulist member of a struct ifmediareq is an int * on most systems,
+ * but it's a uint64_t on newer versions of OpenBSD.
+ *
+ * We check this by checking whether IFM_GMASK is defined and > 2^32-1.
+ */
+# if defined(IFM_GMASK) && IFM_GMASK > 0xFFFFFFFF
+# define IFM_ULIST_TYPE uint64_t
+# else
+# define IFM_ULIST_TYPE int
+# endif
# endif
# if defined(__APPLE__) || defined(HAVE_BSD_IEEE80211)
@@ -188,49 +252,29 @@ 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-
- * 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.
+ * pb->nonblock so we don't call select(2) if the pcap handle is in non-
+ * blocking mode.
*/
static int
pcap_getnonblock_bpf(pcap_t *p, char *errbuf)
-{
+{
#ifdef HAVE_ZEROCOPY_BPF
- if (p->md.zerocopy) {
- /*
- * Use a negative value for the timeout to represent that the
- * pcap handle is in non-blocking mode.
- */
- return (p->md.timeout < 0);
- }
+ struct pcap_bpf *pb = p->priv;
+
+ if (pb->zerocopy)
+ return (pb->nonblock);
#endif
return (pcap_getnonblock_fd(p, errbuf));
}
static int
pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf)
-{
+{
#ifdef HAVE_ZEROCOPY_BPF
- if (p->md.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) {
- /*
- * Indicate that we're switching to
- * non-blocking mode.
- */
- p->md.timeout = ~p->md.timeout;
- }
- } else {
- if (p->md.timeout < 0) {
- p->md.timeout = ~p->md.timeout;
- }
- }
+ struct pcap_bpf *pb = p->priv;
+
+ if (pb->zerocopy) {
+ pb->nonblock = nonblock;
return (0);
}
#endif
@@ -250,25 +294,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->priv;
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);
}
@@ -287,6 +332,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->priv;
struct bpf_zbuf bz;
struct timeval tv;
struct timespec cur;
@@ -310,20 +356,20 @@ 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 = p->opt.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 && p->opt.timeout) {
+ expire = TSTOMILLI(&pb->firstsel) + p->opt.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);
if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
- (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ (void) pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCROTZBUF: %s", strerror(errno));
return (PCAP_ERROR);
}
@@ -335,7 +381,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->nonblock) {
FD_ZERO(&r_set);
FD_SET(p->fd, &r_set);
if (tmout != 0) {
@@ -343,20 +389,20 @@ 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);
+ p->opt.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 && p->opt.timeout) {
+ pb->interrupted = 1;
+ pb->firstsel = cur;
}
return (0);
} else if (r < 0) {
- (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ (void) pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"select: %s", strerror(errno));
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"
@@ -370,7 +416,7 @@ pcap_next_zbuf(pcap_t *p, int *cc)
* data.
*/
if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
- (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ (void) pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCROTZBUF: %s", strerror(errno));
return (PCAP_ERROR);
}
@@ -384,26 +430,43 @@ pcap_next_zbuf(pcap_t *p, int *cc)
static int
pcap_ack_zbuf(pcap_t *p)
{
+ struct pcap_bpf *pb = p->priv;
- 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);
}
#endif /* HAVE_ZEROCOPY_BPF */
pcap_t *
-pcap_create_interface(const char *device, char *ebuf)
+pcap_create_interface(const char *device _U_, char *ebuf)
{
pcap_t *p;
- p = pcap_create_common(device, ebuf);
+ p = pcap_create_common(ebuf, sizeof (struct pcap_bpf));
if (p == NULL)
return (NULL);
p->activate_op = pcap_activate_bpf;
p->can_set_rfmon_op = pcap_can_set_rfmon_bpf;
+#ifdef BIOCSTSTAMP
+ /*
+ * We claim that we support microsecond and nanosecond time
+ * stamps.
+ */
+ p->tstamp_precision_count = 2;
+ p->tstamp_precision_list = malloc(2 * sizeof(u_int));
+ if (p->tstamp_precision_list == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ free(p);
+ return (NULL);
+ }
+ p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
+ p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
+#endif /* BIOCSTSTAMP */
return (p);
}
@@ -412,7 +475,7 @@ pcap_create_interface(const char *device, char *ebuf)
* On failure, returns a PCAP_ERROR_ value, and sets p->errbuf.
*/
static int
-bpf_open(pcap_t *p)
+bpf_open(char *errbuf)
{
int fd;
#ifdef HAVE_CLONING_BPF
@@ -428,7 +491,7 @@ bpf_open(pcap_t *p)
* and create the BPF device entries, if they don't
* already exist.
*/
- if (bpf_load(p->errbuf) == PCAP_ERROR)
+ if (bpf_load(errbuf) == PCAP_ERROR)
return (PCAP_ERROR);
#endif
@@ -439,7 +502,7 @@ bpf_open(pcap_t *p)
fd = PCAP_ERROR_PERM_DENIED;
else
fd = PCAP_ERROR;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"(cannot open device) %s: %s", device, pcap_strerror(errno));
}
#else
@@ -447,7 +510,7 @@ bpf_open(pcap_t *p)
* Go through all the minors and find one that isn't in use.
*/
do {
- (void)snprintf(device, sizeof(device), "/dev/bpf%d", n++);
+ (void)pcap_snprintf(device, sizeof(device), "/dev/bpf%d", n++);
/*
* Initially try a read/write open (to allow the inject
* method to work). If that fails due to permission
@@ -481,7 +544,7 @@ bpf_open(pcap_t *p)
* means we probably have no BPF
* devices.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"(there are no BPF devices)");
} else {
/*
@@ -490,7 +553,7 @@ bpf_open(pcap_t *p)
* devices, but all the ones
* that exist are busy.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"(all BPF devices are busy)");
}
break;
@@ -502,7 +565,7 @@ bpf_open(pcap_t *p)
* if any.
*/
fd = PCAP_ERROR_PERM_DENIED;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"(cannot open BPF device) %s: %s", device,
pcap_strerror(errno));
break;
@@ -512,7 +575,7 @@ bpf_open(pcap_t *p)
* Some other problem.
*/
fd = PCAP_ERROR;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"(cannot open BPF device) %s: %s", device,
pcap_strerror(errno));
break;
@@ -523,6 +586,66 @@ bpf_open(pcap_t *p)
return (fd);
}
+/*
+ * Open and bind to a device; used if we're not actually going to use
+ * the device, but are just testing whether it can be opened, or opening
+ * it to get information about it.
+ *
+ * Returns an error code on failure (always negative), and an FD for
+ * the now-bound BPF device on success (always non-negative).
+ */
+static int
+bpf_open_and_bind(const char *name, char *errbuf)
+{
+ int fd;
+ struct ifreq ifr;
+
+ /*
+ * First, open a BPF device.
+ */
+ fd = bpf_open(errbuf);
+ if (fd < 0)
+ return (fd); /* fd is the appropriate error code */
+
+ /*
+ * Now bind to the device.
+ */
+ (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
+ switch (errno) {
+
+ case ENXIO:
+ /*
+ * There's no such device.
+ */
+ close(fd);
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+
+ case ENETDOWN:
+ /*
+ * Return a "network down" indication, so that
+ * the application can report that rather than
+ * saying we had a mysterious failure and
+ * suggest that they report a problem to the
+ * libpcap developers.
+ */
+ close(fd);
+ return (PCAP_ERROR_IFACE_NOT_UP);
+
+ default:
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "BIOCSETIF: %s: %s", name, pcap_strerror(errno));
+ close(fd);
+ return (PCAP_ERROR);
+ }
+ }
+
+ /*
+ * Success.
+ */
+ return (fd);
+}
+
#ifdef BIOCGDLTLIST
static int
get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf)
@@ -534,13 +657,13 @@ get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf)
bdlp->bfl_list = (u_int *) malloc(sizeof(u_int) * (bdlp->bfl_len + 1));
if (bdlp->bfl_list == NULL) {
- (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ (void)pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
return (PCAP_ERROR);
}
if (ioctl(fd, BIOCGDLTLIST, (caddr_t)bdlp) < 0) {
- (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"BIOCGDLTLIST: %s", pcap_strerror(errno));
free(bdlp->bfl_list);
return (PCAP_ERROR);
@@ -595,7 +718,7 @@ get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf)
* this device"; don't treat it as an error.
*/
if (errno != EINVAL) {
- (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
"BIOCGDLTLIST: %s", pcap_strerror(errno));
return (PCAP_ERROR);
}
@@ -654,7 +777,7 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
* 10.4 (Darwin 8.x). s/en/wlt/, and check
* whether the device exists.
*/
- if (strncmp(p->opt.source, "en", 2) != 0) {
+ if (strncmp(p->opt.device, "en", 2) != 0) {
/*
* Not an enN device; no monitor mode.
*/
@@ -662,12 +785,12 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
}
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1) {
- (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"socket: %s", pcap_strerror(errno));
return (PCAP_ERROR);
}
strlcpy(ifr.ifr_name, "wlt", sizeof(ifr.ifr_name));
- strlcat(ifr.ifr_name, p->opt.source + 2, sizeof(ifr.ifr_name));
+ strlcat(ifr.ifr_name, p->opt.device + 2, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
/*
* No such device?
@@ -687,14 +810,14 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
*
* First, open a BPF device.
*/
- fd = bpf_open(p);
+ fd = bpf_open(p->errbuf);
if (fd < 0)
return (fd); /* fd is the appropriate error code */
/*
* Now bind to the device.
*/
- (void)strncpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
+ (void)strncpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
switch (errno) {
@@ -717,9 +840,9 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
return (PCAP_ERROR_IFACE_NOT_UP);
default:
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSETIF: %s: %s",
- p->opt.source, pcap_strerror(errno));
+ p->opt.device, pcap_strerror(errno));
close(fd);
return (PCAP_ERROR);
}
@@ -745,6 +868,7 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
return (1);
}
free(bdl.bfl_list);
+ close(fd);
#endif /* BIOCGDLTLIST */
return (0);
#elif defined(HAVE_BSD_IEEE80211)
@@ -780,7 +904,7 @@ pcap_stats_bpf(pcap_t *p, struct pcap_stat *ps)
* by libpcap, and thus not yet seen by the application.
*/
if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s",
pcap_strerror(errno));
return (PCAP_ERROR);
}
@@ -794,12 +918,13 @@ 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->priv;
int cc;
int n = 0;
register u_char *bp, *ep;
u_char *datap;
#ifdef PCAP_FDDIPAD
- register int pad;
+ register u_int pad;
#endif
#ifdef HAVE_ZEROCOPY_BPF
int i;
@@ -829,7 +954,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);
@@ -840,7 +965,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
} else
#endif
{
- cc = read(p->fd, (char *)p->buffer, p->bufsize);
+ cc = read(p->fd, p->buffer, p->bufsize);
}
if (cc < 0) {
/* Don't choke when we get ptraced */
@@ -888,7 +1013,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
* pcap_dispatch() etc. aren't
* defined to retur that.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"The interface went down");
return (PCAP_ERROR);
@@ -907,24 +1032,28 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
/* fall through */
#endif
}
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",
pcap_strerror(errno));
return (PCAP_ERROR);
}
- bp = p->buffer;
+ bp = (u_char *)p->buffer;
} else
bp = p->bp;
/*
* Loop through each packet.
*/
+#ifdef BIOCSTSTAMP
+#define bhp ((struct bpf_xhdr *)bp)
+#else
#define bhp ((struct bpf_hdr *)bp)
+#endif
ep = bp + cc;
#ifdef PCAP_FDDIPAD
pad = p->fddipad;
#endif
while (bp < ep) {
- register int caplen, hdrlen;
+ register u_int caplen, hdrlen;
/*
* Has "pcap_breakloop()" been called?
@@ -977,10 +1106,28 @@ 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;
+#ifdef BIOCSTSTAMP
+ struct bintime bt;
+ bt.sec = bhp->bh_tstamp.bt_sec;
+ bt.frac = bhp->bh_tstamp.bt_frac;
+ if (p->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
+ struct timespec ts;
+
+ bintime2timespec(&bt, &ts);
+ pkthdr.ts.tv_sec = ts.tv_sec;
+ pkthdr.ts.tv_usec = ts.tv_nsec;
+ } else {
+ struct timeval tv;
+
+ bintime2timeval(&bt, &tv);
+ pkthdr.ts.tv_sec = tv.tv_sec;
+ pkthdr.ts.tv_usec = tv.tv_usec;
+ }
+#else
pkthdr.ts.tv_sec = bhp->bh_tstamp.tv_sec;
#ifdef _AIX
/*
@@ -991,6 +1138,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
#else
pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec;
#endif
+#endif /* BIOCSTSTAMP */
#ifdef PCAP_FDDIPAD
if (caplen > pad)
pkthdr.caplen = caplen - pad;
@@ -1007,7 +1155,7 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
#endif
(*callback)(user, &pkthdr, datap);
bp += BPF_WORDALIGN(caplen + hdrlen);
- if (++n >= cnt && cnt > 0) {
+ if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
p->bp = bp;
p->cc = ep - bp;
/*
@@ -1058,7 +1206,7 @@ pcap_inject_bpf(pcap_t *p, const void *buf, size_t size)
u_int spoof_eth_src = 0;
if (ioctl(p->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
- (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"send: can't turn off BIOCSHDRCMPLT: %s",
pcap_strerror(errno));
return (PCAP_ERROR);
@@ -1071,7 +1219,7 @@ pcap_inject_bpf(pcap_t *p, const void *buf, size_t size)
}
#endif /* __APPLE__ */
if (ret == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
pcap_strerror(errno));
return (PCAP_ERROR);
}
@@ -1087,7 +1235,7 @@ bpf_odminit(char *errbuf)
if (odm_initialize() == -1) {
if (odm_err_msg(odmerrno, &errstr) == -1)
errstr = "Unknown error";
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: odm_initialize failed: %s",
errstr);
return (PCAP_ERROR);
@@ -1096,7 +1244,7 @@ bpf_odminit(char *errbuf)
if ((odmlockid = odm_lock("/etc/objrepos/config_lock", ODM_WAIT)) == -1) {
if (odm_err_msg(odmerrno, &errstr) == -1)
errstr = "Unknown error";
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: odm_lock of /etc/objrepos/config_lock failed: %s",
errstr);
(void)odm_terminate();
@@ -1115,7 +1263,7 @@ bpf_odmcleanup(char *errbuf)
if (errbuf != NULL) {
if (odm_err_msg(odmerrno, &errstr) == -1)
errstr = "Unknown error";
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: odm_unlock failed: %s",
errstr);
}
@@ -1126,7 +1274,7 @@ bpf_odmcleanup(char *errbuf)
if (errbuf != NULL) {
if (odm_err_msg(odmerrno, &errstr) == -1)
errstr = "Unknown error";
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: odm_terminate failed: %s",
errstr);
}
@@ -1160,7 +1308,7 @@ bpf_load(char *errbuf)
major = genmajor(BPF_NAME);
if (major == -1) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: genmajor failed: %s", pcap_strerror(errno));
(void)bpf_odmcleanup(NULL);
return (PCAP_ERROR);
@@ -1170,7 +1318,7 @@ bpf_load(char *errbuf)
if (!minors) {
minors = genminor("bpf", major, 0, BPF_MINORS, 1, 1);
if (!minors) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: genminor failed: %s",
pcap_strerror(errno));
(void)bpf_odmcleanup(NULL);
@@ -1183,7 +1331,7 @@ bpf_load(char *errbuf)
rc = stat(BPF_NODE "0", &sbuf);
if (rc == -1 && errno != ENOENT) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: can't stat %s: %s",
BPF_NODE "0", pcap_strerror(errno));
return (PCAP_ERROR);
@@ -1194,7 +1342,7 @@ bpf_load(char *errbuf)
sprintf(buf, "%s%d", BPF_NODE, i);
unlink(buf);
if (mknod(buf, S_IRUSR | S_IFCHR, domakedev(major, i)) == -1) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: can't mknod %s: %s",
buf, pcap_strerror(errno));
return (PCAP_ERROR);
@@ -1210,7 +1358,7 @@ bpf_load(char *errbuf)
(cfg_ld.kmid == 0)) {
/* Driver isn't loaded, load it now */
if (sysconfig(SYS_SINGLELOAD, (void *)&cfg_ld, sizeof(cfg_ld)) == -1) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: could not load driver: %s",
strerror(errno));
return (PCAP_ERROR);
@@ -1225,7 +1373,7 @@ bpf_load(char *errbuf)
for (i = 0; i < BPF_MINORS; i++) {
cfg_bpf.devno = domakedev(major, i);
if (sysconfig(SYS_CFGKMOD, (void *)&cfg_km, sizeof(cfg_km)) == -1) {
- snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"bpf_load: could not configure driver: %s",
strerror(errno));
return (PCAP_ERROR);
@@ -1239,24 +1387,25 @@ bpf_load(char *errbuf)
#endif
/*
- * Turn off rfmon mode if necessary.
+ * Undo any operations done when opening the device when necessary.
*/
static void
pcap_cleanup_bpf(pcap_t *p)
{
+ struct pcap_bpf *pb = p->priv;
#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.
@@ -1273,7 +1422,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,
@@ -1288,7 +1437,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;
@@ -1306,16 +1455,34 @@ pcap_cleanup_bpf(pcap_t *p)
}
#endif /* HAVE_BSD_IEEE80211 */
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+ /*
+ * Attempt to destroy the usbusN interface that we created.
+ */
+ if (pb->must_do_on_close & MUST_DESTROY_USBUS) {
+ if (if_nametoindex(pb->device) > 0) {
+ int s;
+
+ s = socket(AF_LOCAL, SOCK_DGRAM, 0);
+ if (s >= 0) {
+ strlcpy(ifr.ifr_name, pb->device,
+ sizeof(ifr.ifr_name));
+ ioctl(s, SIOCIFDESTROY, &ifr);
+ close(s);
+ }
+ }
+ }
+#endif /* defined(__FreeBSD__) && defined(SIOCIFCREATE2) */
/*
* Take this pcap out of the list of pcaps for which we
* 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
@@ -1323,17 +1490,17 @@ 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;
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);
}
@@ -1352,7 +1519,7 @@ check_setif_failure(pcap_t *p, int error)
* No such device exists.
*/
#ifdef __APPLE__
- if (p->opt.rfmon && strncmp(p->opt.source, "wlt", 3) == 0) {
+ if (p->opt.rfmon && strncmp(p->opt.device, "wlt", 3) == 0) {
/*
* Monitor mode was requested, and we're trying
* to open a "wltN" device. Assume that this
@@ -1364,7 +1531,7 @@ check_setif_failure(pcap_t *p, int error)
if (fd != -1) {
strlcpy(ifr.ifr_name, "en",
sizeof(ifr.ifr_name));
- strlcat(ifr.ifr_name, p->opt.source + 3,
+ strlcat(ifr.ifr_name, p->opt.device + 3,
sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
/*
@@ -1373,7 +1540,7 @@ check_setif_failure(pcap_t *p, int error)
* exist.
*/
err = PCAP_ERROR_NO_SUCH_DEVICE;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"SIOCGIFFLAGS on %s failed: %s",
ifr.ifr_name, pcap_strerror(errno));
} else {
@@ -1397,7 +1564,7 @@ check_setif_failure(pcap_t *p, int error)
* just report "no such device".
*/
err = PCAP_ERROR_NO_SUCH_DEVICE;
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"socket() failed: %s",
pcap_strerror(errno));
}
@@ -1407,7 +1574,7 @@ check_setif_failure(pcap_t *p, int error)
/*
* No such device.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF failed: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF failed: %s",
pcap_strerror(errno));
return (PCAP_ERROR_NO_SUCH_DEVICE);
} else if (errno == ENETDOWN) {
@@ -1424,8 +1591,8 @@ check_setif_failure(pcap_t *p, int error)
* Some other error; fill in the error string, and
* return PCAP_ERROR.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
- p->opt.source, pcap_strerror(errno));
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
+ p->opt.device, pcap_strerror(errno));
return (PCAP_ERROR);
}
}
@@ -1448,7 +1615,11 @@ check_setif_failure(pcap_t *p, int error)
static int
pcap_activate_bpf(pcap_t *p)
{
+ struct pcap_bpf *pb = p->priv;
int status = 0;
+#ifdef HAVE_BSD_IEEE80211
+ int retv;
+#endif
int fd;
#ifdef LIFNAMSIZ
char *zonesep;
@@ -1493,7 +1664,7 @@ pcap_activate_bpf(pcap_t *p)
u_int bufmode, zbufmax;
#endif
- fd = bpf_open(p);
+ fd = bpf_open(p->errbuf);
if (fd < 0) {
status = fd;
goto bad;
@@ -1502,14 +1673,14 @@ pcap_activate_bpf(pcap_t *p)
p->fd = fd;
if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
}
if (bv.bv_major != BPF_MAJOR_VERSION ||
bv.bv_minor < BPF_MINOR_VERSION) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"kernel bpf filter out of date");
status = PCAP_ERROR;
goto bad;
@@ -1517,30 +1688,57 @@ pcap_activate_bpf(pcap_t *p)
#if defined(LIFNAMSIZ) && defined(ZONENAME_MAX) && defined(lifr_zoneid)
/*
- * Check if the given source network device has a '/' separated
- * zonename prefix string. The zonename prefixed source device
- * can be used by libpcap consumers to capture network traffic
- * in non-global zones from the global zone on Solaris 11 and
- * above. If the zonename prefix is present then we strip the
- * prefix and pass the zone ID as part of lifr_zoneid.
+ * Retrieve the zoneid of the zone we are currently executing in.
*/
- if ((zonesep = strchr(p->opt.source, '/')) != NULL) {
- char zonename[ZONENAME_MAX];
+ if ((ifr.lifr_zoneid = getzoneid()) == -1) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "getzoneid(): %s",
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ /*
+ * Check if the given source datalink name has a '/' separated
+ * zonename prefix string. The zonename prefixed source datalink can
+ * be used by pcap consumers in the Solaris global zone to capture
+ * traffic on datalinks in non-global zones. Non-global zones
+ * do not have access to datalinks outside of their own namespace.
+ */
+ if ((zonesep = strchr(p->opt.device, '/')) != NULL) {
+ char path_zname[ZONENAME_MAX];
int znamelen;
char *lnamep;
- znamelen = zonesep - p->opt.source;
- (void) strlcpy(zonename, p->opt.source, znamelen + 1);
+ if (ifr.lifr_zoneid != GLOBAL_ZONEID) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "zonename/linkname only valid in global zone.");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ znamelen = zonesep - p->opt.device;
+ (void) strlcpy(path_zname, p->opt.device, znamelen + 1);
+ ifr.lifr_zoneid = getzoneidbyname(path_zname);
+ if (ifr.lifr_zoneid == -1) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "getzoneidbyname(%s): %s", path_zname,
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
lnamep = strdup(zonesep + 1);
- ifr.lifr_zoneid = getzoneidbyname(zonename);
- free(p->opt.source);
- p->opt.source = lnamep;
+ if (lnamep == NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ free(p->opt.device);
+ p->opt.device = lnamep;
}
#endif
- p->md.device = strdup(p->opt.source);
- if (p->md.device == NULL) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
+ pb->device = strdup(p->opt.device);
+ if (pb->device == NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -1583,7 +1781,7 @@ pcap_activate_bpf(pcap_t *p)
/*
* 10.4 (Darwin 8.x). s/en/wlt/
*/
- if (strncmp(p->opt.source, "en", 2) != 0) {
+ if (strncmp(p->opt.device, "en", 2) != 0) {
/*
* Not an enN device; check
* whether the device even exists.
@@ -1591,7 +1789,7 @@ pcap_activate_bpf(pcap_t *p)
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd != -1) {
strlcpy(ifrname,
- p->opt.source, ifnamsiz);
+ p->opt.device, ifnamsiz);
if (ioctl(sockfd, SIOCGIFFLAGS,
(char *)&ifr) < 0) {
/*
@@ -1602,7 +1800,7 @@ pcap_activate_bpf(pcap_t *p)
* exist.
*/
status = PCAP_ERROR_NO_SUCH_DEVICE;
- snprintf(p->errbuf,
+ pcap_snprintf(p->errbuf,
PCAP_ERRBUF_SIZE,
"SIOCGIFFLAGS failed: %s",
pcap_strerror(errno));
@@ -1616,25 +1814,25 @@ pcap_activate_bpf(pcap_t *p)
* report "no such device".
*/
status = PCAP_ERROR_NO_SUCH_DEVICE;
- snprintf(p->errbuf,
+ pcap_snprintf(p->errbuf,
PCAP_ERRBUF_SIZE,
"socket() failed: %s",
pcap_strerror(errno));
}
goto bad;
}
- wltdev = malloc(strlen(p->opt.source) + 2);
+ wltdev = malloc(strlen(p->opt.device) + 2);
if (wltdev == NULL) {
- (void)snprintf(p->errbuf,
+ (void)pcap_snprintf(p->errbuf,
PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
}
strcpy(wltdev, "wlt");
- strcat(wltdev, p->opt.source + 2);
- free(p->opt.source);
- p->opt.source = wltdev;
+ strcat(wltdev, p->opt.device + 2);
+ free(p->opt.device);
+ p->opt.device = wltdev;
}
/*
* Everything else is 10.5 or later; for those,
@@ -1643,6 +1841,85 @@ pcap_activate_bpf(pcap_t *p)
}
}
#endif /* __APPLE__ */
+
+ /*
+ * If this is FreeBSD, and the device name begins with "usbus",
+ * try to create the interface if it's not available.
+ */
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+ if (strncmp(p->opt.device, usbus_prefix, USBUS_PREFIX_LEN) == 0) {
+ /*
+ * Do we already have an interface with that name?
+ */
+ if (if_nametoindex(p->opt.device) == 0) {
+ /*
+ * No. We need to create it, and, if we
+ * succeed, remember that we should destroy
+ * it when the pcap_t is closed.
+ */
+ int s;
+
+ /*
+ * Open a socket to use for ioctls to
+ * create the interface.
+ */
+ s = socket(AF_LOCAL, SOCK_DGRAM, 0);
+ if (s < 0) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't open socket: %s",
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * If we haven't already done so, arrange to have
+ * "pcap_close_all()" called when we exit.
+ */
+ if (!pcap_do_addexit(p)) {
+ /*
+ * "atexit()" failed; don't create the
+ * interface, just give up.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "atexit failed");
+ close(s);
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * Create the interface.
+ */
+ strlcpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCIFCREATE2, &ifr) < 0) {
+ if (errno == EINVAL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Invalid USB bus interface %s",
+ p->opt.device);
+ } else {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't create interface for %s: %s",
+ p->opt.device, pcap_strerror(errno));
+ }
+ close(s);
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * Make sure we clean this up when we close.
+ */
+ pb->must_do_on_close |= MUST_DESTROY_USBUS;
+
+ /*
+ * Add this to the list of pcaps to close when we exit.
+ */
+ pcap_add_to_pcaps_to_close(p);
+ }
+ }
+#endif /* defined(__FreeBSD__) && defined(SIOCIFCREATE2) */
+
#ifdef HAVE_ZEROCOPY_BPF
/*
* If the BPF extension to set buffer mode is present, try setting
@@ -1654,7 +1931,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
@@ -1666,8 +1943,9 @@ pcap_activate_bpf(pcap_t *p)
* size.
*/
if (ioctl(fd, BIOCGETZMAX, (caddr_t)&zbufmax) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGETZMAX: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGETZMAX: %s",
pcap_strerror(errno));
+ status = PCAP_ERROR;
goto bad;
}
@@ -1684,34 +1962,37 @@ 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) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "mmap: %s",
+ if (pb->zbuf1 == MAP_FAILED || pb->zbuf2 == MAP_FAILED) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "mmap: %s",
pcap_strerror(errno));
+ status = PCAP_ERROR;
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_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETZBUF: %s",
pcap_strerror(errno));
+ status = PCAP_ERROR;
goto bad;
}
- (void)strncpy(ifrname, p->opt.source, ifnamsiz);
+ (void)strncpy(ifrname, p->opt.device, ifnamsiz);
if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
- p->opt.source, pcap_strerror(errno));
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
+ p->opt.device, pcap_strerror(errno));
+ status = PCAP_ERROR;
goto bad;
}
- v = p->md.zbufsize - sizeof(struct bpf_zbuf_header);
+ v = pb->zbufsize - sizeof(struct bpf_zbuf_header);
} else
#endif
{
@@ -1725,8 +2006,8 @@ pcap_activate_bpf(pcap_t *p)
*/
if (ioctl(fd, BIOCSBLEN,
(caddr_t)&p->opt.buffer_size) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "BIOCSBLEN: %s: %s", p->opt.source,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "BIOCSBLEN: %s: %s", p->opt.device,
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -1735,7 +2016,7 @@ pcap_activate_bpf(pcap_t *p)
/*
* Now bind to the device.
*/
- (void)strncpy(ifrname, p->opt.source, ifnamsiz);
+ (void)strncpy(ifrname, p->opt.device, ifnamsiz);
#ifdef BIOCSETLIF
if (ioctl(fd, BIOCSETLIF, (caddr_t)&ifr) < 0)
#else
@@ -1768,7 +2049,7 @@ pcap_activate_bpf(pcap_t *p)
*/
(void) ioctl(fd, BIOCSBLEN, (caddr_t)&v);
- (void)strncpy(ifrname, p->opt.source, ifnamsiz);
+ (void)strncpy(ifrname, p->opt.device, ifnamsiz);
#ifdef BIOCSETLIF
if (ioctl(fd, BIOCSETLIF, (caddr_t)&ifr) >= 0)
#else
@@ -1783,9 +2064,9 @@ pcap_activate_bpf(pcap_t *p)
}
if (v == 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSBLEN: %s: No buffer size worked",
- p->opt.source);
+ p->opt.device);
status = PCAP_ERROR;
goto bad;
}
@@ -1795,7 +2076,7 @@ pcap_activate_bpf(pcap_t *p)
/* Get the data link layer type. */
if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -1828,7 +2109,7 @@ pcap_activate_bpf(pcap_t *p)
/*
* We don't know what to map this to yet.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown interface type %u",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown interface type %u",
v);
status = PCAP_ERROR;
goto bad;
@@ -1916,7 +2197,7 @@ pcap_activate_bpf(pcap_t *p)
* the default mode, attempt to
* select the new mode.
*/
- if (new_dlt != v) {
+ if ((u_int)new_dlt != v) {
if (ioctl(p->fd, BIOCSDLT,
&new_dlt) != -1) {
/*
@@ -1963,11 +2244,12 @@ pcap_activate_bpf(pcap_t *p)
/*
* Try to put the interface into monitor mode.
*/
- status = monitor_mode(p, 1);
- if (status != 0) {
+ retv = monitor_mode(p, 1);
+ if (retv != 0) {
/*
* We failed.
*/
+ status = retv;
goto bad;
}
@@ -1987,7 +2269,7 @@ pcap_activate_bpf(pcap_t *p)
* If the new mode we want isn't the default mode,
* attempt to select the new mode.
*/
- if (new_dlt != v) {
+ if ((u_int)new_dlt != v) {
if (ioctl(p->fd, BIOCSDLT, &new_dlt) != -1) {
/*
* We succeeded; make this the
@@ -2024,8 +2306,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)
@@ -2039,7 +2321,7 @@ pcap_activate_bpf(pcap_t *p)
* BSDs - check CVS log for "bpf.c"?
*/
if (ioctl(fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
- (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ (void)pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSHDRCMPLT: %s", pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -2047,9 +2329,14 @@ pcap_activate_bpf(pcap_t *p)
#endif
/* set timeout */
#ifdef HAVE_ZEROCOPY_BPF
- if (p->md.timeout != 0 && !p->md.zerocopy) {
+ /*
+ * In zero-copy mode, we just use the timeout in select().
+ * XXX - what if we're in non-blocking mode and the *application*
+ * is using select() or poll() or kqueues or....?
+ */
+ if (p->opt.timeout && !pb->zerocopy) {
#else
- if (p->md.timeout) {
+ if (p->opt.timeout) {
#endif
/*
* XXX - is this seconds/nanoseconds in AIX?
@@ -2073,20 +2360,20 @@ 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 = p->opt.timeout / 1000;
+ bpf_to.tv_usec = (p->opt.timeout * 1000) % 1000000;
if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&bpf_to) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSRTIMEOUT: %s", pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
}
} else {
#endif
- to.tv_sec = p->md.timeout / 1000;
- to.tv_usec = (p->md.timeout * 1000) % 1000000;
+ to.tv_sec = p->opt.timeout / 1000;
+ to.tv_usec = (p->opt.timeout * 1000) % 1000000;
if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"BIOCSRTIMEOUT: %s", pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -2096,7 +2383,6 @@ pcap_activate_bpf(pcap_t *p)
#endif
}
-#ifdef _AIX
#ifdef BIOCIMMEDIATE
/*
* Darren Reed notes that
@@ -2108,74 +2394,71 @@ pcap_activate_bpf(pcap_t *p)
* is reducing things to only a few packets (i.e. one every
* second or so).
*
- * so we turn BIOCIMMEDIATE mode on if this is AIX.
+ * so we always turn BIOCIMMEDIATE mode on if this is AIX.
*
- * We don't turn it on for other platforms, as that means we
- * get woken up for every packet, which may not be what we want;
- * in the Winter 1993 USENIX paper on BPF, they say:
+ * For other platforms, we don't turn immediate mode on by default,
+ * as that would mean we get woken up for every packet, which
+ * probably isn't what you want for a packet sniffer.
*
- * Since a process might want to look at every packet on a
- * network and the time between packets can be only a few
- * microseconds, it is not possible to do a read system call
- * per packet and BPF must collect the data from several
- * packets and return it as a unit when the monitoring
- * application does a read.
- *
- * which I infer is the reason for the timeout - it means we
- * wait that amount of time, in the hopes that more packets
- * will arrive and we'll get them all with one read.
- *
- * Setting BIOCIMMEDIATE mode on FreeBSD (and probably other
- * BSDs) causes the timeout to be ignored.
- *
- * On the other hand, some platforms (e.g., Linux) don't support
- * timeouts, they just hand stuff to you as soon as it arrives;
- * if that doesn't cause a problem on those platforms, it may
- * be OK to have BIOCIMMEDIATE mode on BSD as well.
- *
- * (Note, though, that applications may depend on the read
- * completing, even if no packets have arrived, when the timeout
- * expires, e.g. GUI applications that have to check for input
- * while waiting for packets to arrive; a non-zero timeout
- * prevents "select()" from working right on FreeBSD and
- * possibly other BSDs, as the timer doesn't start until a
- * "read()" is done, so the timer isn't in effect if the
- * application is blocked on a "select()", and the "select()"
- * doesn't get woken up for a BPF device until the buffer
- * fills up.)
+ * We set immediate mode if the caller requested it by calling
+ * pcap_set_immediate() before calling pcap_activate().
*/
- v = 1;
- if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCIMMEDIATE: %s",
- pcap_strerror(errno));
+#ifndef _AIX
+ if (p->opt.immediate) {
+#endif /* _AIX */
+ v = 1;
+ if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "BIOCIMMEDIATE: %s", pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#ifndef _AIX
+ }
+#endif /* _AIX */
+#else /* BIOCIMMEDIATE */
+ if (p->opt.immediate) {
+ /*
+ * We don't support immediate mode. Fail.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Immediate mode not supported");
status = PCAP_ERROR;
goto bad;
}
-#endif /* BIOCIMMEDIATE */
-#endif /* _AIX */
+#endif /* BIOCIMMEDIATE */
if (p->opt.promisc) {
/* set promiscuous mode, just warn if it fails */
if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s",
pcap_strerror(errno));
status = PCAP_WARNING_PROMISC_NOTSUP;
}
}
+#ifdef BIOCSTSTAMP
+ v = BPF_T_BINTIME;
+ if (ioctl(p->fd, BIOCSTSTAMP, &v) < 0) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSTSTAMP: %s",
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#endif /* BIOCSTSTAMP */
+
if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
}
p->bufsize = v;
#ifdef HAVE_ZEROCOPY_BPF
- if (!p->md.zerocopy) {
+ if (!pb->zerocopy) {
#endif
- p->buffer = (u_char *)malloc(p->bufsize);
+ p->buffer = malloc(p->bufsize);
if (p->buffer == NULL) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -2206,7 +2489,7 @@ pcap_activate_bpf(pcap_t *p)
total_prog.bf_len = 1;
total_prog.bf_insns = &total_insn;
if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
pcap_strerror(errno));
status = PCAP_ERROR;
goto bad;
@@ -2272,13 +2555,140 @@ pcap_activate_bpf(pcap_t *p)
return (status);
bad:
- pcap_cleanup_bpf(p);
+ pcap_cleanup_bpf(p);
return (status);
}
+/*
+ * Not all interfaces can be bound to by BPF, so try to bind to
+ * the specified interface; return 0 if we fail with
+ * PCAP_ERROR_NO_SUCH_DEVICE (which means we got an ENXIO when we tried
+ * to bind, which means this interface isn't in the list of interfaces
+ * attached to BPF) and 1 otherwise.
+ */
+static int
+check_bpf_bindable(const char *name)
+{
+ int fd;
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ fd = bpf_open_and_bind(name, errbuf);
+ if (fd < 0) {
+ /*
+ * Error - was it PCAP_ERROR_NO_SUCH_DEVICE?
+ */
+ if (fd == PCAP_ERROR_NO_SUCH_DEVICE) {
+ /*
+ * Yes, so we can't bind to this because it's
+ * not something supported by BPF.
+ */
+ return (0);
+ }
+ /*
+ * No, so we don't know whether it's supported or not;
+ * say it is, so that the user can at least try to
+ * open it and report the error (which is probably
+ * "you don't have permission to open BPF devices";
+ * reporting those interfaces means users will ask
+ * "why am I getting a permissions error when I try
+ * to capture" rather than "why am I not seeing any
+ * interfaces", making the underlying problem clearer).
+ */
+ return (1);
+ }
+
+ /*
+ * Success.
+ */
+ close(fd);
+ return (1);
+}
+
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+static int
+finddevs_usb(pcap_if_t **alldevsp, char *errbuf)
+{
+ DIR *usbdir;
+ struct dirent *usbitem;
+ size_t name_max;
+ char *name;
+
+ /*
+ * We might have USB sniffing support, so try looking for USB
+ * interfaces.
+ *
+ * We want to report a usbusN device for each USB bus, but
+ * usbusN interfaces might, or might not, exist for them -
+ * we create one if there isn't already one.
+ *
+ * So, instead, we look in /dev/usb for all buses and create
+ * a "usbusN" device for each one.
+ */
+ usbdir = opendir("/dev/usb");
+ if (usbdir == NULL) {
+ /*
+ * Just punt.
+ */
+ return (0);
+ }
+
+ /*
+ * Leave enough room for a 32-bit (10-digit) bus number.
+ * Yes, that's overkill, but we won't be using
+ * the buffer very long.
+ */
+ name_max = USBUS_PREFIX_LEN + 10 + 1;
+ name = malloc(name_max);
+ if (name == NULL) {
+ closedir(usbdir);
+ return (0);
+ }
+ while ((usbitem = readdir(usbdir)) != NULL) {
+ char *p;
+ size_t busnumlen;
+ int err;
+
+ if (strcmp(usbitem->d_name, ".") == 0 ||
+ strcmp(usbitem->d_name, "..") == 0) {
+ /*
+ * Ignore these.
+ */
+ continue;
+ }
+ p = strchr(usbitem->d_name, '.');
+ if (p == NULL)
+ continue;
+ busnumlen = p - usbitem->d_name;
+ memcpy(name, usbus_prefix, USBUS_PREFIX_LEN);
+ memcpy(name + USBUS_PREFIX_LEN, usbitem->d_name, busnumlen);
+ *(name + USBUS_PREFIX_LEN + busnumlen) = '\0';
+ err = pcap_add_if(alldevsp, name, PCAP_IF_UP, NULL, errbuf);
+ if (err != 0) {
+ free(name);
+ closedir(usbdir);
+ return (err);
+ }
+ }
+ free(name);
+ closedir(usbdir);
+ return (0);
+}
+#endif
+
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
+ /*
+ * Get the list of regular interfaces first.
+ */
+ if (pcap_findalldevs_interfaces(alldevsp, errbuf, check_bpf_bindable) == -1)
+ return (-1); /* failure */
+
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+ if (finddevs_usb(alldevsp, errbuf) == -1)
+ return (-1);
+#endif
+
return (0);
}
@@ -2286,22 +2696,23 @@ pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
static int
monitor_mode(pcap_t *p, int set)
{
+ struct pcap_bpf *pb = p->priv;
int sock;
struct ifmediareq req;
- int *media_list;
+ IFM_ULIST_TYPE *media_list;
int i;
int can_do;
struct ifreq ifr;
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't open socket: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't open socket: %s",
pcap_strerror(errno));
return (PCAP_ERROR);
}
memset(&req, 0, sizeof req);
- strncpy(req.ifm_name, p->opt.source, sizeof req.ifm_name);
+ strncpy(req.ifm_name, p->opt.device, sizeof req.ifm_name);
/*
* Find out how many media types we have.
@@ -2327,7 +2738,7 @@ monitor_mode(pcap_t *p, int set)
return (PCAP_ERROR_RFMON_NOTSUP);
default:
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"SIOCGIFMEDIA 1: %s", pcap_strerror(errno));
close(sock);
return (PCAP_ERROR);
@@ -2345,16 +2756,16 @@ monitor_mode(pcap_t *p, int set)
* Allocate a buffer to hold all the media types, and
* get the media types.
*/
- media_list = malloc(req.ifm_count * sizeof(int));
+ media_list = malloc(req.ifm_count * sizeof(*media_list));
if (media_list == NULL) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
close(sock);
return (PCAP_ERROR);
}
req.ifm_ulist = media_list;
if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMEDIA: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMEDIA: %s",
pcap_strerror(errno));
free(media_list);
close(sock);
@@ -2407,23 +2818,21 @@ monitor_mode(pcap_t *p, int set)
* "atexit()" failed; don't put the interface
* in monitor mode, just give up.
*/
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "atexit failed");
close(sock);
return (PCAP_ERROR);
}
memset(&ifr, 0, sizeof(ifr));
- (void)strncpy(ifr.ifr_name, p->opt.source,
+ (void)strncpy(ifr.ifr_name, p->opt.device,
sizeof(ifr.ifr_name));
ifr.ifr_media = req.ifm_current | IFM_IEEE80211_MONITOR;
if (ioctl(sock, SIOCSIFMEDIA, &ifr) == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"SIOCSIFMEDIA: %s", pcap_strerror(errno));
close(sock);
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.
@@ -2450,7 +2859,7 @@ static int
find_802_11(struct bpf_dltlist *bdlp)
{
int new_dlt;
- int i;
+ u_int i;
/*
* Scan the list of DLT_ values, looking for 802.11 values,
@@ -2600,6 +3009,8 @@ remove_802_11(pcap_t *p)
static int
pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
{
+ struct pcap_bpf *pb = p->priv;
+
/*
* Free any user-mode filter we might happen to have installed.
*/
@@ -2612,7 +3023,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
@@ -2640,7 +3051,7 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
* some kernels.
*/
if (errno != EINVAL) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
pcap_strerror(errno));
return (-1);
}
@@ -2652,7 +3063,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);
}
@@ -2669,7 +3080,7 @@ pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d)
direction = (d == PCAP_D_IN) ? BPF_D_IN :
((d == PCAP_D_OUT) ? BPF_D_OUT : BPF_D_INOUT);
if (ioctl(p->fd, BIOCSDIRECTION, &direction) == -1) {
- (void) snprintf(p->errbuf, sizeof(p->errbuf),
+ (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"Cannot set direction to %s: %s",
(d == PCAP_D_IN) ? "PCAP_D_IN" :
((d == PCAP_D_OUT) ? "PCAP_D_OUT" : "PCAP_D_INOUT"),
@@ -2684,14 +3095,14 @@ pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d)
* We don't support PCAP_D_OUT.
*/
if (d == PCAP_D_OUT) {
- snprintf(p->errbuf, sizeof(p->errbuf),
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"Setting direction to PCAP_D_OUT is not supported on BPF");
return -1;
}
seesent = (d == PCAP_D_INOUT);
if (ioctl(p->fd, BIOCSSEESENT, &seesent) == -1) {
- (void) snprintf(p->errbuf, sizeof(p->errbuf),
+ (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"Cannot set direction to %s: %s",
(d == PCAP_D_INOUT) ? "PCAP_D_INOUT" : "PCAP_D_IN",
strerror(errno));
@@ -2699,7 +3110,7 @@ pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d)
}
return (0);
#else
- (void) snprintf(p->errbuf, sizeof(p->errbuf),
+ (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"This system doesn't support BIOCSSEESENT, so the direction can't be set");
return (-1);
#endif
@@ -2710,7 +3121,7 @@ pcap_set_datalink_bpf(pcap_t *p, int dlt)
{
#ifdef BIOCSDLT
if (ioctl(p->fd, BIOCSDLT, &dlt) == -1) {
- (void) snprintf(p->errbuf, sizeof(p->errbuf),
+ (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"Cannot set DLT %d: %s", dlt, strerror(errno));
return (-1);
}