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.c626
1 files changed, 395 insertions, 231 deletions
diff --git a/freebsd/contrib/libpcap/pcap-bpf.c b/freebsd/contrib/libpcap/pcap-bpf.c
index 60111cf5..dc2942af 100644
--- a/freebsd/contrib/libpcap/pcap-bpf.c
+++ b/freebsd/contrib/libpcap/pcap-bpf.c
@@ -19,25 +19,20 @@
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- *
- * $FreeBSD$
*/
#ifdef HAVE_CONFIG_H
-#include "config.h"
+#include <config.h>
#endif
#include <sys/param.h> /* optionally get BSD define */
-#ifdef HAVE_ZEROCOPY_BPF
-#include <sys/mman.h>
-#endif
#include <sys/socket.h>
#include <time.h>
/*
* <net/bpf.h> defines ioctls, but doesn't include <sys/ioccom.h>.
*
* We include <sys/ioctl.h> as it might be necessary to declare ioctl();
- * at least on *BSD and Mac OS X, it also defines various SIOC ioctls -
+ * at least on *BSD and macOS, it also defines various SIOC ioctls -
* we could include <sys/sockio.h>, but if we're already including
* <sys/ioctl.h>, which includes <sys/sockio.h> on those platforms,
* there's not much point in doing so.
@@ -61,10 +56,6 @@ static const char usbus_prefix[] = "usbus";
#include <dirent.h>
#endif
-#ifdef HAVE_ZEROCOPY_BPF
-#include <machine/atomic.h>
-#endif
-
#include <net/if.h>
#ifdef _AIX
@@ -86,6 +77,16 @@ static const char usbus_prefix[] = "usbus";
#include <net/bpf.h>
#define _AIX
+/*
+ * If both BIOCROTZBUF and BPF_BUFMODE_ZBUF are defined, we have
+ * zero-copy BPF.
+ */
+#if defined(BIOCROTZBUF) && defined(BPF_BUFMODE_ZBUF)
+ #define HAVE_ZEROCOPY_BPF
+ #include <sys/mman.h>
+ #include <machine/atomic.h>
+#endif
+
#include <net/if_types.h> /* for IFT_ values */
#include <sys/sysconfig.h>
#include <sys/device.h>
@@ -125,7 +126,7 @@ static int bpf_load(char *errbuf);
#include <string.h>
#include <unistd.h>
-#ifdef HAVE_NET_IF_MEDIA_H
+#ifdef SIOCGIFMEDIA
# include <net/if_media.h>
#endif
@@ -228,8 +229,9 @@ static void remove_802_11(pcap_t *);
#endif
/*
- * On OS X, we don't even get any of the 802.11-plus-radio-header DLT_'s
- * defined, even though some of them are used by various Airport drivers.
+ * In some versions of macOS, we might not even get any of the
+ * 802.11-plus-radio-header DLT_'s defined, even though some
+ * of them are used by various Airport drivers in those versions.
*/
#ifndef DLT_PRISM_HEADER
#define DLT_PRISM_HEADER 119
@@ -256,7 +258,7 @@ static int pcap_set_datalink_bpf(pcap_t *p, int dlt);
* blocking mode.
*/
static int
-pcap_getnonblock_bpf(pcap_t *p, char *errbuf)
+pcap_getnonblock_bpf(pcap_t *p)
{
#ifdef HAVE_ZEROCOPY_BPF
struct pcap_bpf *pb = p->priv;
@@ -264,11 +266,11 @@ pcap_getnonblock_bpf(pcap_t *p, char *errbuf)
if (pb->zerocopy)
return (pb->nonblock);
#endif
- return (pcap_getnonblock_fd(p, errbuf));
+ return (pcap_getnonblock_fd(p));
}
static int
-pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf)
+pcap_setnonblock_bpf(pcap_t *p, int nonblock)
{
#ifdef HAVE_ZEROCOPY_BPF
struct pcap_bpf *pb = p->priv;
@@ -278,7 +280,7 @@ pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf)
return (0);
}
#endif
- return (pcap_setnonblock_fd(p, nonblock, errbuf));
+ return (pcap_setnonblock_fd(p, nonblock));
}
#ifdef HAVE_ZEROCOPY_BPF
@@ -369,8 +371,8 @@ pcap_next_zbuf(pcap_t *p, int *cc)
if (data)
return (data);
if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
- (void) pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "BIOCROTZBUF: %s", strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "BIOCROTZBUF");
return (PCAP_ERROR);
}
return (pcap_next_zbuf_shm(p, cc));
@@ -397,8 +399,8 @@ pcap_next_zbuf(pcap_t *p, int *cc)
}
return (0);
} else if (r < 0) {
- (void) pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "select: %s", strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "select");
return (PCAP_ERROR);
}
}
@@ -416,8 +418,8 @@ pcap_next_zbuf(pcap_t *p, int *cc)
* data.
*/
if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
- (void) pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "BIOCROTZBUF: %s", strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCROTZBUF");
return (PCAP_ERROR);
}
return (pcap_next_zbuf_shm(p, cc));
@@ -459,8 +461,8 @@ pcap_create_interface(const char *device _U_, char *ebuf)
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));
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno,
+ "malloc");
free(p);
return (NULL);
}
@@ -477,13 +479,11 @@ pcap_create_interface(const char *device _U_, char *ebuf)
static int
bpf_open(char *errbuf)
{
- int fd;
-#ifdef HAVE_CLONING_BPF
- static const char device[] = "/dev/bpf";
-#else
+ int fd = -1;
+ static const char cloning_device[] = "/dev/bpf";
int n = 0;
char device[sizeof "/dev/bpf0000000000"];
-#endif
+ static int no_cloning_bpf = 0;
#ifdef _AIX
/*
@@ -495,40 +495,55 @@ bpf_open(char *errbuf)
return (PCAP_ERROR);
#endif
-#ifdef HAVE_CLONING_BPF
- if ((fd = open(device, O_RDWR)) == -1 &&
- (errno != EACCES || (fd = open(device, O_RDONLY)) == -1)) {
- if (errno == EACCES)
- fd = PCAP_ERROR_PERM_DENIED;
- else
- fd = PCAP_ERROR;
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "(cannot open device) %s: %s", device, pcap_strerror(errno));
- }
-#else
/*
- * Go through all the minors and find one that isn't in use.
+ * First, unless we've already tried opening /dev/bpf and
+ * gotten ENOENT, try opening /dev/bpf.
+ * If it fails with ENOENT, remember that, so we don't try
+ * again, and try /dev/bpfN.
*/
- do {
- (void)pcap_snprintf(device, sizeof(device), "/dev/bpf%d", n++);
+ if (!no_cloning_bpf &&
+ (fd = open(cloning_device, O_RDWR)) == -1 &&
+ ((errno != EACCES && errno != ENOENT) ||
+ (fd = open(cloning_device, O_RDONLY)) == -1)) {
+ if (errno != ENOENT) {
+ if (errno == EACCES)
+ fd = PCAP_ERROR_PERM_DENIED;
+ else
+ fd = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "(cannot open device) %s", cloning_device);
+ return (fd);
+ }
+ no_cloning_bpf = 1;
+ }
+
+ if (no_cloning_bpf) {
/*
- * Initially try a read/write open (to allow the inject
- * method to work). If that fails due to permission
- * issues, fall back to read-only. This allows a
- * non-root user to be granted specific access to pcap
- * capabilities via file permissions.
- *
- * XXX - we should have an API that has a flag that
- * controls whether to open read-only or read-write,
- * so that denial of permission to send (or inability
- * to send, if sending packets isn't supported on
- * the device in question) can be indicated at open
- * time.
+ * We don't have /dev/bpf.
+ * Go through all the /dev/bpfN minors and find one
+ * that isn't in use.
*/
- fd = open(device, O_RDWR);
- if (fd == -1 && errno == EACCES)
- fd = open(device, O_RDONLY);
- } while (fd < 0 && errno == EBUSY);
+ do {
+ (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
+ * issues, fall back to read-only. This allows a
+ * non-root user to be granted specific access to pcap
+ * capabilities via file permissions.
+ *
+ * XXX - we should have an API that has a flag that
+ * controls whether to open read-only or read-write,
+ * so that denial of permission to send (or inability
+ * to send, if sending packets isn't supported on
+ * the device in question) can be indicated at open
+ * time.
+ */
+ fd = open(device, O_RDWR);
+ if (fd == -1 && errno == EACCES)
+ fd = open(device, O_RDONLY);
+ } while (fd < 0 && errno == EBUSY);
+ }
/*
* XXX better message for all minors used
@@ -565,9 +580,8 @@ bpf_open(char *errbuf)
* if any.
*/
fd = PCAP_ERROR_PERM_DENIED;
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "(cannot open BPF device) %s: %s", device,
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "(cannot open BPF device) %s", device);
break;
default:
@@ -575,13 +589,11 @@ bpf_open(char *errbuf)
* Some other problem.
*/
fd = PCAP_ERROR;
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "(cannot open BPF device) %s: %s", device,
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "(cannot open BPF device) %s", device);
break;
}
}
-#endif
return (fd);
}
@@ -633,8 +645,8 @@ bpf_open_and_bind(const char *name, char *errbuf)
return (PCAP_ERROR_IFACE_NOT_UP);
default:
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "BIOCSETIF: %s: %s", name, pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSETIF: %s", name);
close(fd);
return (PCAP_ERROR);
}
@@ -657,14 +669,14 @@ 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)pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
return (PCAP_ERROR);
}
if (ioctl(fd, BIOCGDLTLIST, (caddr_t)bdlp) < 0) {
- (void)pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "BIOCGDLTLIST: %s", pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCGDLTLIST");
free(bdlp->bfl_list);
return (PCAP_ERROR);
}
@@ -718,8 +730,8 @@ 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)pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "BIOCGDLTLIST: %s", pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCGDLTLIST");
return (PCAP_ERROR);
}
}
@@ -739,7 +751,7 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
#endif
/*
- * The joys of monitor mode on OS X.
+ * The joys of monitor mode on Mac OS X/OS X/macOS.
*
* Prior to 10.4, it's not supported at all.
*
@@ -785,8 +797,8 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
}
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1) {
- (void)pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "socket: %s", pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "socket");
return (PCAP_ERROR);
}
strlcpy(ifr.ifr_name, "wlt", sizeof(ifr.ifr_name));
@@ -840,9 +852,8 @@ pcap_can_set_rfmon_bpf(pcap_t *p)
return (PCAP_ERROR_IFACE_NOT_UP);
default:
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "BIOCSETIF: %s: %s",
- p->opt.device, pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSETIF: %s", p->opt.device);
close(fd);
return (PCAP_ERROR);
}
@@ -904,8 +915,8 @@ 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) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCGSTATS");
return (PCAP_ERROR);
}
@@ -1032,8 +1043,8 @@ pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
/* fall through */
#endif
}
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "read");
return (PCAP_ERROR);
}
bp = (u_char *)p->buffer;
@@ -1186,13 +1197,13 @@ pcap_inject_bpf(pcap_t *p, const void *buf, size_t size)
#ifdef __APPLE__
if (ret == -1 && errno == EAFNOSUPPORT) {
/*
- * In Mac OS X, there's a bug wherein setting the
- * BIOCSHDRCMPLT flag causes writes to fail; see,
- * for example:
+ * In some versions of macOS, there's a bug wherein setting
+ * the BIOCSHDRCMPLT flag causes writes to fail; see, for
+ * example:
*
* http://cerberus.sourcefire.com/~jeff/archives/patches/macosx/BIOCSHDRCMPLT-10.3.3.patch
*
- * So, if, on OS X, we get EAFNOSUPPORT from the write, we
+ * So, if, on macOS, we get EAFNOSUPPORT from the write, we
* assume it's due to that bug, and turn off that flag
* and try again. If we succeed, it either means that
* somebody applied the fix from that URL, or other patches
@@ -1201,14 +1212,13 @@ pcap_inject_bpf(pcap_t *p, const void *buf, size_t size)
* http://cerberus.sourcefire.com/~jeff/archives/patches/macosx/
*
* and are running a Darwin kernel with those fixes, or
- * that Apple fixed the problem in some OS X release.
+ * that Apple fixed the problem in some macOS release.
*/
u_int spoof_eth_src = 0;
if (ioctl(p->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
- (void)pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "send: can't turn off BIOCSHDRCMPLT: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "send: can't turn off BIOCSHDRCMPLT");
return (PCAP_ERROR);
}
@@ -1219,8 +1229,8 @@ pcap_inject_bpf(pcap_t *p, const void *buf, size_t size)
}
#endif /* __APPLE__ */
if (ret == -1) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "send");
return (PCAP_ERROR);
}
return (ret);
@@ -1308,8 +1318,8 @@ bpf_load(char *errbuf)
major = genmajor(BPF_NAME);
if (major == -1) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "bpf_load: genmajor failed: %s", pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "bpf_load: genmajor failed");
(void)bpf_odmcleanup(NULL);
return (PCAP_ERROR);
}
@@ -1318,9 +1328,8 @@ bpf_load(char *errbuf)
if (!minors) {
minors = genminor("bpf", major, 0, BPF_MINORS, 1, 1);
if (!minors) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "bpf_load: genminor failed: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "bpf_load: genminor failed");
(void)bpf_odmcleanup(NULL);
return (PCAP_ERROR);
}
@@ -1331,20 +1340,19 @@ bpf_load(char *errbuf)
rc = stat(BPF_NODE "0", &sbuf);
if (rc == -1 && errno != ENOENT) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "bpf_load: can't stat %s: %s",
- BPF_NODE "0", pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "bpf_load: can't stat %s", BPF_NODE "0");
return (PCAP_ERROR);
}
if (rc == -1 || getmajor(sbuf.st_rdev) != major) {
for (i = 0; i < BPF_MINORS; i++) {
- sprintf(buf, "%s%d", BPF_NODE, i);
+ pcap_snprintf(buf, sizeof(buf), "%s%d", BPF_NODE, i);
unlink(buf);
if (mknod(buf, S_IRUSR | S_IFCHR, domakedev(major, i)) == -1) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "bpf_load: can't mknod %s: %s",
- buf, pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "bpf_load: can't mknod %s", buf);
return (PCAP_ERROR);
}
}
@@ -1353,14 +1361,13 @@ bpf_load(char *errbuf)
/* Check if the driver is loaded */
memset(&cfg_ld, 0x0, sizeof(cfg_ld));
cfg_ld.path = buf;
- sprintf(cfg_ld.path, "%s/%s", DRIVER_PATH, BPF_NAME);
+ pcap_snprintf(cfg_ld.path, sizeof(cfg_ld.path), "%s/%s", DRIVER_PATH, BPF_NAME);
if ((sysconfig(SYS_QUERYLOAD, (void *)&cfg_ld, sizeof(cfg_ld)) == -1) ||
(cfg_ld.kmid == 0)) {
/* Driver isn't loaded, load it now */
if (sysconfig(SYS_SINGLELOAD, (void *)&cfg_ld, sizeof(cfg_ld)) == -1) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "bpf_load: could not load driver: %s",
- strerror(errno));
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "bpf_load: could not load driver");
return (PCAP_ERROR);
}
}
@@ -1373,9 +1380,8 @@ 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) {
- pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
- "bpf_load: could not configure driver: %s",
- strerror(errno));
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "bpf_load: could not configure driver");
return (PCAP_ERROR);
}
}
@@ -1495,7 +1501,6 @@ pcap_cleanup_bpf(pcap_t *p)
if (pb->zbuf2 != MAP_FAILED && pb->zbuf2 != NULL)
(void) munmap(pb->zbuf2, pb->zbufsize);
p->buffer = NULL;
- p->buffer = NULL;
}
#endif
if (pb->device != NULL) {
@@ -1540,9 +1545,10 @@ check_setif_failure(pcap_t *p, int error)
* exist.
*/
err = PCAP_ERROR_NO_SUCH_DEVICE;
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "SIOCGIFFLAGS on %s failed: %s",
- ifr.ifr_name, pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "SIOCGIFFLAGS on %s failed",
+ ifr.ifr_name);
} else {
/*
* The underlying "enN" device
@@ -1564,9 +1570,9 @@ check_setif_failure(pcap_t *p, int error)
* just report "no such device".
*/
err = PCAP_ERROR_NO_SUCH_DEVICE;
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "socket() failed: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ errno, PCAP_ERRBUF_SIZE,
+ "socket() failed");
}
return (err);
}
@@ -1574,8 +1580,8 @@ check_setif_failure(pcap_t *p, int error)
/*
* No such device.
*/
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF failed: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSETIF failed");
return (PCAP_ERROR_NO_SUCH_DEVICE);
} else if (errno == ENETDOWN) {
/*
@@ -1591,8 +1597,8 @@ check_setif_failure(pcap_t *p, int error)
* Some other error; fill in the error string, and
* return PCAP_ERROR.
*/
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
- p->opt.device, pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSETIF: %s", p->opt.device);
return (PCAP_ERROR);
}
}
@@ -1649,15 +1655,6 @@ pcap_activate_bpf(pcap_t *p)
struct bpf_insn total_insn;
struct bpf_program total_prog;
struct utsname osinfo;
-
-#ifdef HAVE_DAG_API
- if (strstr(device, "dag")) {
- return dag_open_live(device, snaplen, promisc, to_ms, ebuf);
- }
-#endif /* HAVE_DAG_API */
-
-#ifdef BIOCGDLTLIST
- memset(&bdl, 0, sizeof(bdl));
int have_osinfo = 0;
#ifdef HAVE_ZEROCOPY_BPF
struct bpf_zbuf bz;
@@ -1673,8 +1670,8 @@ pcap_activate_bpf(pcap_t *p)
p->fd = fd;
if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCVERSION");
status = PCAP_ERROR;
goto bad;
}
@@ -1686,13 +1683,24 @@ pcap_activate_bpf(pcap_t *p)
goto bad;
}
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+ p->snapshot = MAXIMUM_SNAPLEN;
+
#if defined(LIFNAMSIZ) && defined(ZONENAME_MAX) && defined(lifr_zoneid)
/*
* Retrieve the zoneid of the zone we are currently executing in.
*/
if ((ifr.lifr_zoneid = getzoneid()) == -1) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "getzoneid(): %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "getzoneid()");
status = PCAP_ERROR;
goto bad;
}
@@ -1718,16 +1726,15 @@ pcap_activate_bpf(pcap_t *p)
(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));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "getzoneidbyname(%s)", path_zname);
status = PCAP_ERROR;
goto bad;
}
lnamep = strdup(zonesep + 1);
if (lnamep == NULL) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "strdup");
status = PCAP_ERROR;
goto bad;
}
@@ -1738,20 +1745,13 @@ pcap_activate_bpf(pcap_t *p)
pb->device = strdup(p->opt.device);
if (pb->device == NULL) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "strdup");
status = PCAP_ERROR;
goto bad;
}
/*
- * Try finding a good size for the buffer; 32768 may be too
- * big, so keep cutting it in half until we find a size
- * that works, or run out of sizes to try. If the default
- * is larger, don't make it smaller.
- *
- * XXX - there should be a user-accessible hook to set the
- * initial buffer size.
* Attempt to find out the version of the OS on which we're running.
*/
if (uname(&osinfo) == 0)
@@ -1800,10 +1800,10 @@ pcap_activate_bpf(pcap_t *p)
* exist.
*/
status = PCAP_ERROR_NO_SUCH_DEVICE;
- pcap_snprintf(p->errbuf,
+ pcap_fmt_errmsg_for_errno(p->errbuf,
PCAP_ERRBUF_SIZE,
- "SIOCGIFFLAGS failed: %s",
- pcap_strerror(errno));
+ errno,
+ "SIOCGIFFLAGS failed");
} else
status = PCAP_ERROR_RFMON_NOTSUP;
close(sockfd);
@@ -1814,18 +1814,17 @@ pcap_activate_bpf(pcap_t *p)
* report "no such device".
*/
status = PCAP_ERROR_NO_SUCH_DEVICE;
- pcap_snprintf(p->errbuf,
- PCAP_ERRBUF_SIZE,
- "socket() failed: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "socket() failed");
}
goto bad;
}
wltdev = malloc(strlen(p->opt.device) + 2);
if (wltdev == NULL) {
- (void)pcap_snprintf(p->errbuf,
- PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "malloc");
status = PCAP_ERROR;
goto bad;
}
@@ -1865,9 +1864,9 @@ pcap_activate_bpf(pcap_t *p)
*/
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));
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "Can't open socket");
status = PCAP_ERROR;
goto bad;
}
@@ -1898,9 +1897,10 @@ pcap_activate_bpf(pcap_t *p)
"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));
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "Can't create interface for %s",
+ p->opt.device);
}
close(s);
status = PCAP_ERROR;
@@ -1943,8 +1943,8 @@ pcap_activate_bpf(pcap_t *p)
* size.
*/
if (ioctl(fd, BIOCGETZMAX, (caddr_t)&zbufmax) < 0) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGETZMAX: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCGETZMAX");
status = PCAP_ERROR;
goto bad;
}
@@ -1970,8 +1970,8 @@ pcap_activate_bpf(pcap_t *p)
pb->zbuf2 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE,
MAP_ANON, -1, 0);
if (pb->zbuf1 == MAP_FAILED || pb->zbuf2 == MAP_FAILED) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "mmap: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "mmap");
status = PCAP_ERROR;
goto bad;
}
@@ -1980,15 +1980,15 @@ pcap_activate_bpf(pcap_t *p)
bz.bz_bufb = pb->zbuf2;
bz.bz_buflen = pb->zbufsize;
if (ioctl(fd, BIOCSETZBUF, (caddr_t)&bz) < 0) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETZBUF: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSETZBUF");
status = PCAP_ERROR;
goto bad;
}
(void)strncpy(ifrname, p->opt.device, ifnamsiz);
if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s",
- p->opt.device, pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSETIF: %s", p->opt.device);
status = PCAP_ERROR;
goto bad;
}
@@ -2006,9 +2006,9 @@ pcap_activate_bpf(pcap_t *p)
*/
if (ioctl(fd, BIOCSBLEN,
(caddr_t)&p->opt.buffer_size) < 0) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "BIOCSBLEN: %s: %s", p->opt.device,
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "BIOCSBLEN: %s", p->opt.device);
status = PCAP_ERROR;
goto bad;
}
@@ -2072,12 +2072,11 @@ pcap_activate_bpf(pcap_t *p)
}
}
}
-#endif
/* Get the data link layer type. */
if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCGDLT");
status = PCAP_ERROR;
goto bad;
}
@@ -2321,8 +2320,8 @@ pcap_activate_bpf(pcap_t *p)
* BSDs - check CVS log for "bpf.c"?
*/
if (ioctl(fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
- (void)pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "BIOCSHDRCMPLT: %s", pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSHDRCMPLT");
status = PCAP_ERROR;
goto bad;
}
@@ -2363,8 +2362,8 @@ pcap_activate_bpf(pcap_t *p)
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) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "BIOCSRTIMEOUT: %s", pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ errno, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT");
status = PCAP_ERROR;
goto bad;
}
@@ -2373,8 +2372,8 @@ pcap_activate_bpf(pcap_t *p)
to.tv_sec = p->opt.timeout / 1000;
to.tv_usec = (p->opt.timeout * 1000) % 1000000;
if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "BIOCSRTIMEOUT: %s", pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ errno, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT");
status = PCAP_ERROR;
goto bad;
}
@@ -2408,8 +2407,8 @@ pcap_activate_bpf(pcap_t *p)
#endif /* _AIX */
v = 1;
if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "BIOCIMMEDIATE: %s", pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCIMMEDIATE");
status = PCAP_ERROR;
goto bad;
}
@@ -2430,8 +2429,8 @@ pcap_activate_bpf(pcap_t *p)
if (p->opt.promisc) {
/* set promiscuous mode, just warn if it fails */
if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCPROMISC");
status = PCAP_WARNING_PROMISC_NOTSUP;
}
}
@@ -2439,16 +2438,16 @@ pcap_activate_bpf(pcap_t *p)
#ifdef BIOCSTSTAMP
v = BPF_T_BINTIME;
if (ioctl(p->fd, BIOCSTSTAMP, &v) < 0) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSTSTAMP: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSTSTAMP");
status = PCAP_ERROR;
goto bad;
}
#endif /* BIOCSTSTAMP */
if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCGBLEN");
status = PCAP_ERROR;
goto bad;
}
@@ -2458,8 +2457,8 @@ pcap_activate_bpf(pcap_t *p)
#endif
p->buffer = malloc(p->bufsize);
if (p->buffer == NULL) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
status = PCAP_ERROR;
goto bad;
}
@@ -2489,8 +2488,8 @@ 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) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSETF");
status = PCAP_ERROR;
goto bad;
}
@@ -2572,6 +2571,44 @@ check_bpf_bindable(const char *name)
int fd;
char errbuf[PCAP_ERRBUF_SIZE];
+ /*
+ * On macOS, we don't do this check if the device name begins
+ * with "wlt"; at least some versions of macOS (actually, it
+ * was called "Mac OS X" then...) offer monitor mode capturing
+ * by having a separate "monitor mode" device for each wireless
+ * adapter, rather than by implementing the ioctls that
+ * {Free,Net,Open,DragonFly}BSD provide. Opening that device
+ * puts the adapter into monitor mode, which, at least for
+ * some adapters, causes them to deassociate from the network
+ * with which they're associated.
+ *
+ * Instead, we try to open the corresponding "en" device (so
+ * that we don't end up with, for users without sufficient
+ * privilege to open capture devices, a list of adapters that
+ * only includes the wlt devices).
+ */
+#ifdef __APPLE__
+ if (strncmp(name, "wlt", 3) == 0) {
+ char *en_name;
+ size_t en_name_len;
+
+ /*
+ * Try to allocate a buffer for the "en"
+ * device's name.
+ */
+ en_name_len = strlen(name) - 1;
+ en_name = malloc(en_name_len + 1);
+ if (en_name == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return (-1);
+ }
+ strcpy(en_name, "en");
+ strcat(en_name, name + 3);
+ fd = bpf_open_and_bind(en_name, errbuf);
+ free(en_name);
+ } else
+#endif /* __APPLE */
fd = bpf_open_and_bind(name, errbuf);
if (fd < 0) {
/*
@@ -2606,7 +2643,18 @@ check_bpf_bindable(const char *name)
#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
static int
-finddevs_usb(pcap_if_t **alldevsp, char *errbuf)
+get_usb_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+{
+ /*
+ * XXX - if there's a way to determine whether there's something
+ * plugged into a given USB bus, use that to determine whether
+ * this device is "connected" or not.
+ */
+ return (0);
+}
+
+static int
+finddevs_usb(pcap_if_list_t *devlistp, char *errbuf)
{
DIR *usbdir;
struct dirent *usbitem;
@@ -2646,7 +2694,6 @@ finddevs_usb(pcap_if_t **alldevsp, char *errbuf)
while ((usbitem = readdir(usbdir)) != NULL) {
char *p;
size_t busnumlen;
- int err;
if (strcmp(usbitem->d_name, ".") == 0 ||
strcmp(usbitem->d_name, "..") == 0) {
@@ -2662,11 +2709,18 @@ finddevs_usb(pcap_if_t **alldevsp, char *errbuf)
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) {
+ /*
+ * There's an entry in this directory for every USB device,
+ * not for every bus; if there's more than one device on
+ * the bus, there'll be more than one entry for that bus,
+ * so we need to avoid adding multiple capture devices
+ * for each bus.
+ */
+ if (find_or_add_dev(devlistp, name, PCAP_IF_UP,
+ get_usb_if_flags, NULL, errbuf) == NULL) {
free(name);
closedir(usbdir);
- return (err);
+ return (PCAP_ERROR);
}
}
free(name);
@@ -2675,17 +2729,116 @@ finddevs_usb(pcap_if_t **alldevsp, char *errbuf)
}
#endif
+/*
+ * Get additional flags for a device, using SIOCGIFMEDIA.
+ */
+#ifdef SIOCGIFMEDIA
+static int
+get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
+{
+ int sock;
+ struct ifmediareq req;
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock == -1) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
+ "Can't create socket to get media information for %s",
+ name);
+ return (-1);
+ }
+ memset(&req, 0, sizeof(req));
+ strncpy(req.ifm_name, name, sizeof(req.ifm_name));
+ if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
+ if (errno == EOPNOTSUPP || errno == EINVAL || errno == ENOTTY ||
+ errno == ENODEV) {
+ /*
+ * Not supported, so we can't provide any
+ * additional information. Assume that
+ * this means that "connected" vs.
+ * "disconnected" doesn't apply.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+ close(sock);
+ return (0);
+ }
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
+ "SIOCGIFMEDIA on %s failed", name);
+ close(sock);
+ return (-1);
+ }
+ close(sock);
+
+ /*
+ * OK, what type of network is this?
+ */
+ switch (IFM_TYPE(req.ifm_active)) {
+
+ case IFM_IEEE80211:
+ /*
+ * Wireless.
+ */
+ *flags |= PCAP_IF_WIRELESS;
+ break;
+ }
+
+ /*
+ * Do we know whether it's connected?
+ */
+ if (req.ifm_status & IFM_AVALID) {
+ /*
+ * Yes.
+ */
+ if (req.ifm_status & IFM_ACTIVE) {
+ /*
+ * It's connected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_CONNECTED;
+ } else {
+ /*
+ * It's disconnected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
+ }
+ }
+ return (0);
+}
+#else
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+{
+ /*
+ * Nothing we can do other than mark loopback devices as "the
+ * connected/disconnected status doesn't apply".
+ *
+ * XXX - on Solaris, can we do what the dladm command does,
+ * i.e. get a connected/disconnected indication from a kstat?
+ * (Note that you can also get the link speed, and possibly
+ * other information, from a kstat as well.)
+ */
+ if (*flags & PCAP_IF_LOOPBACK) {
+ /*
+ * Loopback devices aren't wireless, and "connected"/
+ * "disconnected" doesn't apply to them.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+ return (0);
+ }
+ return (0);
+}
+#endif
+
int
-pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
{
/*
* Get the list of regular interfaces first.
*/
- if (pcap_findalldevs_interfaces(alldevsp, errbuf, check_bpf_bindable) == -1)
+ if (pcap_findalldevs_interfaces(devlistp, errbuf, check_bpf_bindable,
+ get_if_flags) == -1)
return (-1); /* failure */
#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
- if (finddevs_usb(alldevsp, errbuf) == -1)
+ if (finddevs_usb(devlistp, errbuf) == -1)
return (-1);
#endif
@@ -2706,8 +2859,8 @@ monitor_mode(pcap_t *p, int set)
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't open socket: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "can't open socket");
return (PCAP_ERROR);
}
@@ -2738,8 +2891,8 @@ monitor_mode(pcap_t *p, int set)
return (PCAP_ERROR_RFMON_NOTSUP);
default:
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "SIOCGIFMEDIA 1: %s", pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGIFMEDIA 1");
close(sock);
return (PCAP_ERROR);
}
@@ -2758,15 +2911,15 @@ monitor_mode(pcap_t *p, int set)
*/
media_list = malloc(req.ifm_count * sizeof(*media_list));
if (media_list == NULL) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
close(sock);
return (PCAP_ERROR);
}
req.ifm_ulist = media_list;
if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFMEDIA: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGIFMEDIA");
free(media_list);
close(sock);
return (PCAP_ERROR);
@@ -2826,8 +2979,8 @@ monitor_mode(pcap_t *p, int set)
sizeof(ifr.ifr_name));
ifr.ifr_media = req.ifm_current | IFM_IEEE80211_MONITOR;
if (ioctl(sock, SIOCSIFMEDIA, &ifr) == -1) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
- "SIOCSIFMEDIA: %s", pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "SIOCSIFMEDIA");
close(sock);
return (PCAP_ERROR);
}
@@ -3051,8 +3204,8 @@ pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
* some kernels.
*/
if (errno != EINVAL) {
- pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s",
- pcap_strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSETF");
return (-1);
}
@@ -3080,11 +3233,10 @@ 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) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
- "Cannot set direction to %s: %s",
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "Cannot set direction to %s",
(d == PCAP_D_IN) ? "PCAP_D_IN" :
- ((d == PCAP_D_OUT) ? "PCAP_D_OUT" : "PCAP_D_INOUT"),
- strerror(errno));
+ ((d == PCAP_D_OUT) ? "PCAP_D_OUT" : "PCAP_D_INOUT"));
return (-1);
}
return (0);
@@ -3102,10 +3254,9 @@ pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d)
seesent = (d == PCAP_D_INOUT);
if (ioctl(p->fd, BIOCSSEESENT, &seesent) == -1) {
- (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));
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "Cannot set direction to %s",
+ (d == PCAP_D_INOUT) ? "PCAP_D_INOUT" : "PCAP_D_IN");
return (-1);
}
return (0);
@@ -3121,10 +3272,23 @@ pcap_set_datalink_bpf(pcap_t *p, int dlt)
{
#ifdef BIOCSDLT
if (ioctl(p->fd, BIOCSDLT, &dlt) == -1) {
- (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
- "Cannot set DLT %d: %s", dlt, strerror(errno));
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "Cannot set DLT %d", dlt);
return (-1);
}
#endif
return (0);
}
+
+/*
+ * Platform-specific information.
+ */
+const char *
+pcap_lib_version(void)
+{
+#ifdef HAVE_ZEROCOPY_BPF
+ return (PCAP_VERSION_STRING " (with zerocopy support)");
+#else
+ return (PCAP_VERSION_STRING);
+#endif
+}