summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLawrence Teo <lteo@cvs.openbsd.org>2012-05-25 01:58:09 +0000
committerLawrence Teo <lteo@cvs.openbsd.org>2012-05-25 01:58:09 +0000
commit8093f5e607f42cbabe8359e77f8982ec908b2bac (patch)
treee8e8a3293ceb69d286241fb70129b56c28cbdb86
parent69f23bc61c36de2f09f0f566e98df6fce92c6571 (diff)
Import a number of core functions from libpcap-1.2.0 while preserving
local changes: strncpy() -> strlcpy(), malloc(x * y) -> calloc(x, y), exclude cross-platform cruft, etc. The new functions are pcap_create(), pcap_set_snaplen(), pcap_set_promisc(), pcap_can_set_rfmon(), pcap_set_rfmon(), pcap_set_timeout(), pcap_set_buffer_size(), pcap_activate(), and pcap_statustostr(). This diff was tested on amd64, i386, macppc, and sparc64, where regression tests were done on various pcap-based ports (especially amd64 and i386 where regression tests were run on all pcap-based ports). Testers also tried running pcap-based ports that they are familiar with to ensure that there is no behavioral change. tcpdump and pflogd in base were also tested by different testers. The new pcap_* functions were tested with a proof-of-concept Snort 2.9 port for many months. Thank you to everyone who helped test this diff and provided feedback: haesbaert@, sthen@, matthew@, gonzalo@, brett@, Rodolfo Gouveia, Aaron Bieber, Markus Lude, and Ray Percival. ok haesbaert sthen henning
-rw-r--r--lib/libpcap/Makefile10
-rw-r--r--lib/libpcap/pcap-bpf.c777
-rw-r--r--lib/libpcap/pcap-int.h32
-rw-r--r--lib/libpcap/pcap.373
-rw-r--r--lib/libpcap/pcap.c225
-rw-r--r--lib/libpcap/pcap.h42
-rw-r--r--lib/libpcap/savefile.c3
-rw-r--r--lib/libpcap/shlib_version2
8 files changed, 1050 insertions, 114 deletions
diff --git a/lib/libpcap/Makefile b/lib/libpcap/Makefile
index 3519f88efa5..3673d2997ce 100644
--- a/lib/libpcap/Makefile
+++ b/lib/libpcap/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.20 2009/08/13 19:54:58 jmc Exp $
+# $OpenBSD: Makefile,v 1.21 2012/05/25 01:58:08 lteo Exp $
# $NetBSD: Makefile,v 1.3 1996/05/10 21:54:24 cgd Exp $
LIB= pcap
@@ -25,11 +25,15 @@ MLINKS= pcap.3 pcap_open_live.3 pcap.3 pcap_open_offline.3 \
pcap.3 pcap_sendpacket.3 pcap.3 pcap_next_ex.3 \
pcap.3 pcap_setdirection.3 pcap.3 pcap_dump_file.3 \
pcap.3 pcap_dump_ftell.3 pcap.3 pcap_fopen_offline.3 \
- pcap.3 pcap_dump_flush.3
+ pcap.3 pcap_dump_flush.3 pcap.3 pcap_create.3 \
+ pcap.3 pcap_set_snaplen.3 pcap.3 pcap_set_promisc.3 \
+ pcap.3 pcap_can_set_rfmon.3 pcap.3 pcap_set_rfmon.3 \
+ pcap.3 pcap_set_timeout.3 pcap.3 pcap_set_buffer_size.3 \
+ pcap.3 pcap_activate.3 pcap.3 pcap_statustostr.3
DEFS= -DHAVE_SYS_IOCCOM_H -DHAVE_SYS_SOCKIO_H -DHAVE_ETHER_HOSTTON \
-DHAVE_STRERROR -DHAVE_SOCKADDR_SA_LEN -DLBL_ALIGN -DHAVE_IFADDRS_H \
- -DINET6
+ -DINET6 -DHAVE_BSD_IEEE80211
CFLAGS+=-I. -I${.CURDIR} -Dyylval=pcap_yylval ${DEFS}
diff --git a/lib/libpcap/pcap-bpf.c b/lib/libpcap/pcap-bpf.c
index bc988b1325f..afd2de20e0f 100644
--- a/lib/libpcap/pcap-bpf.c
+++ b/lib/libpcap/pcap-bpf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcap-bpf.c,v 1.20 2006/03/26 20:58:51 djm Exp $ */
+/* $OpenBSD: pcap-bpf.c,v 1.21 2012/05/25 01:58:08 lteo Exp $ */
/*
* Copyright (c) 1993, 1994, 1995, 1996, 1998
@@ -38,6 +38,8 @@
#include <string.h>
#include <unistd.h>
+#include <net/if_media.h>
+
#include "pcap-int.h"
#ifdef HAVE_OS_PROTO_H
@@ -46,6 +48,9 @@
#include "gencode.h"
+static int find_802_11(struct bpf_dltlist *);
+static int monitor_mode(pcap_t *, int);
+
int
pcap_stats(pcap_t *p, struct pcap_stat *ps)
{
@@ -54,7 +59,7 @@ pcap_stats(pcap_t *p, struct pcap_stat *ps)
if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) {
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s",
pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
ps->ps_recv = s.bs_recv;
@@ -76,11 +81,11 @@ pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
if (p->break_loop) {
/*
* Yes - clear the flag that indicates that it
- * has, and return -2 to indicate that we were
- * told to break out of the loop.
+ * has, and return PCAP_ERROR_BREAK to indicate
+ * that we were told to break out of the loop.
*/
p->break_loop = 0;
- return (-2);
+ return (PCAP_ERROR_BREAK);
}
cc = p->cc;
@@ -95,6 +100,21 @@ pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
case EWOULDBLOCK:
return (0);
+
+ case ENXIO:
+ /*
+ * The device on which we're capturing
+ * went away.
+ *
+ * XXX - we should really return
+ * PCAP_ERROR_IFACE_NOT_UP, but
+ * pcap_dispatch() etc. aren't
+ * defined to return that.
+ */
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The interface went down");
+ return (PCAP_ERROR);
+
#if defined(sun) && !defined(BSD)
/*
* Due to a SunOS bug, after 2^31 bytes, the kernel
@@ -112,7 +132,7 @@ pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
}
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",
pcap_strerror(errno));
- return (-1);
+ return (PCAP_ERROR);
}
bp = p->buffer;
} else
@@ -129,21 +149,36 @@ pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
/*
* Has "pcap_breakloop()" been called?
* If so, return immediately - if we haven't read any
- * packets, clear the flag and return -2 to indicate
- * that we were told to break out of the loop, otherwise
- * leave the flag set, so that the *next* call will break
- * out of the loop without having read any packets, and
- * return the number of packets we've processed so far.
+ * packets, clear the flag and return PCAP_ERROR_BREAK
+ * to indicate that we were told to break out of the loop,
+ * otherwise leave the flag set, so that the *next* call
+ * will break out of the loop without having read any
+ * packets, and return the number of packets we've
+ * processed so far.
*/
if (p->break_loop) {
+ p->bp = bp;
+ p->cc = ep - bp;
+ /*
+ * ep is set based on the return value of read(),
+ * but read() from a BPF device doesn't necessarily
+ * return a value that's a multiple of the alignment
+ * value for BPF_WORDALIGN(). However, whenever we
+ * increment bp, we round up the increment value by
+ * a value rounded up by BPF_WORDALIGN(), so we
+ * could increment bp past ep after processing the
+ * last packet in the buffer.
+ *
+ * We treat ep < bp as an indication that this
+ * happened, and just set p->cc to 0.
+ */
+ if (p->cc < 0)
+ p->cc = 0;
if (n == 0) {
p->break_loop = 0;
- return (-2);
- } else {
- p->bp = bp;
- p->cc = ep - bp;
+ return (PCAP_ERROR_BREAK);
+ } else
return (n);
- }
}
caplen = bhp->bh_caplen;
@@ -178,7 +213,7 @@ pcap_sendpacket(pcap_t *p, const u_char *buf, int size)
/* ARGSUSED */
static __inline int
-bpf_open(pcap_t *p, char *errbuf)
+bpf_open(pcap_t *p)
{
int fd;
int n = 0;
@@ -197,50 +232,276 @@ bpf_open(pcap_t *p, char *errbuf)
/*
* XXX better message for all minors used
*/
- if (fd < 0)
- snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
- device, pcap_strerror(errno));
+ if (fd < 0) {
+ switch (errno) {
+
+ case ENOENT:
+ fd = PCAP_ERROR;
+ if (n == 1) {
+ /*
+ * /dev/bpf0 doesn't exist, which
+ * means we probably have no BPF
+ * devices.
+ */
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "(there are no BPF devices)");
+ } else {
+ /*
+ * We got EBUSY on at least one
+ * BPF device, so we have BPF
+ * devices, but all the ones
+ * that exist are busy.
+ */
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "(all BPF devices are busy)");
+ }
+ break;
+
+ case EACCES:
+ /*
+ * Got EACCES on the last device we tried,
+ * and EBUSY on all devices before that,
+ * if any.
+ */
+ fd = PCAP_ERROR_PERM_DENIED;
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "(cannot open BPF device) %s: %s", device,
+ pcap_strerror(errno));
+ break;
+
+ default:
+ /*
+ * Some other problem.
+ */
+ fd = PCAP_ERROR;
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "(cannot open BPF device) %s: %s", device,
+ pcap_strerror(errno));
+ break;
+ }
+ }
return (fd);
}
-pcap_t *
-pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
- char *ebuf)
+static int
+get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf)
+{
+ memset(bdlp, 0, sizeof(*bdlp));
+ if (ioctl(fd, BIOCGDLTLIST, (caddr_t)bdlp) == 0) {
+ bdlp->bfl_list = (u_int *) calloc(bdlp->bfl_len + 1, sizeof(u_int));
+ if (bdlp->bfl_list == NULL) {
+ (void)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,
+ "BIOCGDLTLIST: %s", pcap_strerror(errno));
+ free(bdlp->bfl_list);
+ return (PCAP_ERROR);
+ }
+ } else {
+ /*
+ * EINVAL just means "we don't support this ioctl on
+ * this device"; don't treat it as an error.
+ */
+ if (errno != EINVAL) {
+ (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "BIOCGDLTLIST: %s", pcap_strerror(errno));
+ return (PCAP_ERROR);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Returns 1 if rfmon mode can be set on the pcap_t, 0 if it can't,
+ * a PCAP_ERROR value on an error.
+ */
+int
+pcap_can_set_rfmon(pcap_t *p)
{
+#if defined(HAVE_BSD_IEEE80211)
+ int ret;
+
+ ret = monitor_mode(p, 0);
+ if (ret == PCAP_ERROR_RFMON_NOTSUP)
+ return (0); /* not an error, just a "can't do" */
+ if (ret == 0)
+ return (1); /* success */
+ return (ret);
+#else
+ return (0);
+#endif
+}
+
+static void
+pcap_cleanup_bpf(pcap_t *p)
+{
+#ifdef HAVE_BSD_IEEE80211
+ int sock;
+ struct ifmediareq req;
+ struct ifreq ifr;
+#endif
+
+ if (p->md.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) {
+ /*
+ * We put the interface into rfmon mode;
+ * take it out of rfmon mode.
+ *
+ * XXX - if somebody else wants it in rfmon
+ * mode, this code cannot know that, so it'll take
+ * it out of rfmon mode.
+ */
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock == -1) {
+ fprintf(stderr,
+ "Can't restore interface flags (socket() failed: %s).\n"
+ "Please adjust manually.\n",
+ strerror(errno));
+ } else {
+ memset(&req, 0, sizeof(req));
+ (void)strlcpy(req.ifm_name, p->opt.source,
+ sizeof(req.ifm_name));
+ if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
+ fprintf(stderr,
+ "Can't restore interface flags "
+ "(SIOCGIFMEDIA failed: %s).\n"
+ "Please adjust manually.\n",
+ strerror(errno));
+ } else if (req.ifm_current & IFM_IEEE80211_MONITOR) {
+ /*
+ * Rfmon mode is currently on;
+ * turn it off.
+ */
+ memset(&ifr, 0, sizeof(ifr));
+ (void)strlcpy(ifr.ifr_name,
+ p->opt.source,
+ sizeof(ifr.ifr_name));
+ ifr.ifr_media =
+ req.ifm_current & ~IFM_IEEE80211_MONITOR;
+ if (ioctl(sock, SIOCSIFMEDIA,
+ &ifr) == -1) {
+ fprintf(stderr,
+ "Can't restore interface flags "
+ "(SIOCSIFMEDIA failed: %s).\n"
+ "Please adjust manually.\n",
+ strerror(errno));
+ }
+ }
+ close(sock);
+ }
+ }
+#endif /* HAVE_BSD_IEEE80211 */
+
+ /*
+ * 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;
+ }
+
+ /*XXX*/
+ if (p->fd >= 0) {
+ close(p->fd);
+ p->fd = -1;
+ }
+ if (p->sf.rfile != NULL) {
+ (void)fclose(p->sf.rfile);
+ if (p->sf.base != NULL)
+ free(p->sf.base);
+ } else if (p->buffer != NULL)
+ free(p->buffer);
+ pcap_freecode(&p->fcode);
+ if (p->dlt_list != NULL) {
+ free(p->dlt_list);
+ p->dlt_list = NULL;
+ p->dlt_count = 0;
+ }
+}
+
+void
+pcap_close(pcap_t *p)
+{
+ if (p->opt.source != NULL)
+ free(p->opt.source);
+ pcap_cleanup_bpf(p);
+ free(p);
+}
+
+
+static int
+check_setif_failure(pcap_t *p, int error)
+{
+ if (error == ENXIO) {
+ /*
+ * No such device.
+ */
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETIF failed: %s",
+ pcap_strerror(errno));
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+ } else if (errno == 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.
+ */
+ return (PCAP_ERROR_IFACE_NOT_UP);
+ } else {
+ /*
+ * 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));
+ return (PCAP_ERROR);
+ }
+}
+
+int
+pcap_activate(pcap_t *p)
+{
+ int status = 0;
int fd;
struct ifreq ifr;
struct bpf_version bv;
- u_int v;
- pcap_t *p;
struct bpf_dltlist bdl;
+ int new_dlt;
+ u_int v;
- bzero(&bdl, sizeof(bdl));
- p = (pcap_t *)malloc(sizeof(*p));
- if (p == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
- return (NULL);
- }
- bzero(p, sizeof(*p));
- fd = bpf_open(p, ebuf);
- if (fd < 0)
+ fd = bpf_open(p);
+ if (fd < 0) {
+ status = fd;
goto bad;
+ }
p->fd = fd;
- p->snapshot = snaplen;
if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s",
+ 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(ebuf, PCAP_ERRBUF_SIZE,
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"kernel bpf filter out of date");
+ status = PCAP_ERROR;
goto bad;
}
+
#if 0
/* Just use the kernel default */
v = 32768; /* XXX this should be a user-accessible hook */
@@ -252,16 +513,36 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
(void) ioctl(fd, BIOCSBLEN, (caddr_t)&v);
#endif
- (void)strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ /*
+ * Set the buffer size.
+ */
+ if (p->opt.buffer_size != 0) {
+ /*
+ * A buffer size was explicitly specified; use it.
+ */
+ if (ioctl(fd, BIOCSBLEN,
+ (caddr_t)&p->opt.buffer_size) < 0) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "BIOCSBLEN: %s: %s", p->opt.source,
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ }
+
+ /*
+ * Now bind to the device.
+ */
+ (void)strlcpy(ifr.ifr_name, p->opt.source, sizeof(ifr.ifr_name));
if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s",
- device, pcap_strerror(errno));
+ status = check_setif_failure(p, errno);
goto bad;
}
/* Get the data link layer type. */
if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s",
pcap_strerror(errno));
+ status = PCAP_ERROR;
goto bad;
}
#if _BSDI_VERSION - 0 >= 199510
@@ -275,72 +556,418 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
case DLT_PPP:
v = DLT_PPP_BSDOS;
break;
+
+ case 11: /*DLT_FR*/
+ v = DLT_FRELAY;
+ break;
+
+ case 12: /*DLT_C_HDLC*/
+ v = DLT_CHDLC;
+ break;
}
#endif
- p->linktype = v;
/*
* We know the default link type -- now determine all the DLTs
* this interface supports. If this fails with EINVAL, it's
* not fatal; we just don't get to use the feature later.
*/
- if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) == 0) {
- bdl.bfl_list = (u_int *) calloc(bdl.bfl_len + 1, sizeof(u_int));
- if (bdl.bfl_list == NULL) {
- (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
- pcap_strerror(errno));
- goto bad;
- }
+ if (get_dlt_list(fd, v, &bdl, p->errbuf) == -1) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ p->dlt_count = bdl.bfl_len;
+ p->dlt_list = bdl.bfl_list;
- if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) < 0) {
- (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "BIOCGDLTLIST: %s", pcap_strerror(errno));
+ /*
+ * *BSD with the new 802.11 ioctls.
+ * Do we want monitor mode?
+ */
+ if (p->opt.rfmon) {
+ /*
+ * Try to put the interface into monitor mode.
+ */
+ status = monitor_mode(p, 1);
+ if (status != 0) {
+ /*
+ * We failed.
+ */
goto bad;
}
- p->dlt_count = bdl.bfl_len;
- p->dlt_list = bdl.bfl_list;
- } else {
- if (errno != EINVAL) {
- (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
- "BIOCGDLTLIST: %s", pcap_strerror(errno));
- goto bad;
+
+ /*
+ * We're in monitor mode.
+ * Try to find the best 802.11 DLT_ value and, if we
+ * succeed, try to switch to that mode if we're not
+ * already in that mode.
+ */
+ new_dlt = find_802_11(&bdl);
+ if (new_dlt != -1) {
+ /*
+ * We have at least one 802.11 DLT_ value.
+ * new_dlt is the best of the 802.11
+ * DLT_ values in the list.
+ *
+ * If the new mode we want isn't the default mode,
+ * attempt to select the new mode.
+ */
+ if (new_dlt != v) {
+ if (ioctl(p->fd, BIOCSDLT, &new_dlt) != -1) {
+ /*
+ * We succeeded; make this the
+ * new DLT_ value.
+ */
+ v = new_dlt;
+ }
+ }
}
}
+ p->linktype = v;
/* set timeout */
- if (to_ms != 0) {
+ if (p->md.timeout) {
struct timeval to;
- to.tv_sec = to_ms / 1000;
- to.tv_usec = (to_ms * 1000) % 1000000;
+ to.tv_sec = p->md.timeout / 1000;
+ to.tv_usec = (p->md.timeout * 1000) % 1000000;
if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s",
- pcap_strerror(errno));
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "BIOCSRTIMEOUT: %s", pcap_strerror(errno));
+ status = PCAP_ERROR;
goto bad;
}
}
- if (promisc)
- /* set promiscuous mode, okay if it fails */
- (void)ioctl(p->fd, BIOCPROMISC, NULL);
+
+ 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_strerror(errno));
+ status = PCAP_WARNING_PROMISC_NOTSUP;
+ }
+ }
if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s",
pcap_strerror(errno));
+ status = PCAP_ERROR;
goto bad;
}
p->bufsize = v;
p->buffer = (u_char *)malloc(p->bufsize);
if (p->buffer == NULL) {
- snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s",
pcap_strerror(errno));
+ status = PCAP_ERROR;
goto bad;
}
- return (p);
+ if (status < 0)
+ goto bad;
+
+ p->activated = 1;
+
+ return (status);
bad:
- if (fd >= 0)
- (void)close(fd);
- free(bdl.bfl_list);
- free(p);
+ pcap_cleanup_bpf(p);
+
+ if (p->errbuf[0] == '\0') {
+ /*
+ * No error message supplied by the activate routine;
+ * for the benefit of programs that don't specially
+ * handle errors other than PCAP_ERROR, return the
+ * error message corresponding to the status.
+ */
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
+ pcap_statustostr(status));
+ }
+
+ return (status);
+}
+
+static int
+monitor_mode(pcap_t *p, int set)
+{
+ int sock;
+ struct ifmediareq req;
+ int *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_strerror(errno));
+ return (PCAP_ERROR);
+ }
+
+ memset(&req, 0, sizeof req);
+ (void)strlcpy(req.ifm_name, p->opt.source, sizeof req.ifm_name);
+
+ /*
+ * Find out how many media types we have.
+ */
+ if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
+ /*
+ * Can't get the media types.
+ */
+ switch (errno) {
+
+ case ENXIO:
+ /*
+ * There's no such device.
+ */
+ close(sock);
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+
+ case EINVAL:
+ /*
+ * Interface doesn't support SIOC{G,S}IFMEDIA.
+ */
+ close(sock);
+ return (PCAP_ERROR_RFMON_NOTSUP);
+
+ default:
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "SIOCGIFMEDIA 1: %s", pcap_strerror(errno));
+ close(sock);
+ return (PCAP_ERROR);
+ }
+ }
+ if (req.ifm_count == 0) {
+ /*
+ * No media types.
+ */
+ close(sock);
+ return (PCAP_ERROR_RFMON_NOTSUP);
+ }
+
+ /*
+ * Allocate a buffer to hold all the media types, and
+ * get the media types.
+ */
+ media_list = (int *) calloc(req.ifm_count, sizeof(int));
+ if (media_list == NULL) {
+ 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_strerror(errno));
+ free(media_list);
+ close(sock);
+ return (PCAP_ERROR);
+ }
+
+ /*
+ * Look for an 802.11 "automatic" media type.
+ * We assume that all 802.11 adapters have that media type,
+ * and that it will carry the monitor mode supported flag.
+ */
+ can_do = 0;
+ for (i = 0; i < req.ifm_count; i++) {
+ if (IFM_TYPE(media_list[i]) == IFM_IEEE80211
+ && IFM_SUBTYPE(media_list[i]) == IFM_AUTO) {
+ /* OK, does it do monitor mode? */
+ if (media_list[i] & IFM_IEEE80211_MONITOR) {
+ can_do = 1;
+ break;
+ }
+ }
+ }
+ free(media_list);
+ if (!can_do) {
+ /*
+ * This adapter doesn't support monitor mode.
+ */
+ close(sock);
+ return (PCAP_ERROR_RFMON_NOTSUP);
+ }
+
+ if (set) {
+ /*
+ * Don't just check whether we can enable monitor mode,
+ * do so, if it's not already enabled.
+ */
+ if ((req.ifm_current & IFM_IEEE80211_MONITOR) == 0) {
+ /*
+ * Monitor mode isn't currently on, so turn it on,
+ * and remember that we should turn it off when the
+ * pcap_t is closed.
+ */
+
+ /*
+ * 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 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)strlcpy(ifr.ifr_name, p->opt.source,
+ 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,
+ "SIOCSIFMEDIA: %s", pcap_strerror(errno));
+ close(sock);
+ return (PCAP_ERROR);
+ }
+
+ p->md.must_do_on_close |= MUST_CLEAR_RFMON;
+
+ /*
+ * Add this to the list of pcaps to close when we exit.
+ */
+ pcap_add_to_pcaps_to_close(p);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Check whether we have any 802.11 link-layer types; return the best
+ * of the 802.11 link-layer types if we find one, and return -1
+ * otherwise.
+ *
+ * DLT_IEEE802_11_RADIO, with the radiotap header, is considered the
+ * best 802.11 link-layer type; any of the other 802.11-plus-radio
+ * headers are second-best; 802.11 with no radio information is
+ * the least good.
+ */
+static int
+find_802_11(struct bpf_dltlist *bdlp)
+{
+ int new_dlt;
+ int i;
+
+ /*
+ * Scan the list of DLT_ values, looking for 802.11 values,
+ * and, if we find any, choose the best of them.
+ */
+ new_dlt = -1;
+ for (i = 0; i < bdlp->bfl_len; i++) {
+ switch (bdlp->bfl_list[i]) {
+
+ case DLT_IEEE802_11:
+ /*
+ * 802.11, but no radio.
+ *
+ * Offer this, and select it as the new mode
+ * unless we've already found an 802.11
+ * header with radio information.
+ */
+ if (new_dlt == -1)
+ new_dlt = bdlp->bfl_list[i];
+ break;
+
+ case DLT_IEEE802_11_RADIO:
+ /*
+ * 802.11 with radiotap.
+ *
+ * Offer this, and select it as the new mode.
+ */
+ new_dlt = bdlp->bfl_list[i];
+ break;
+
+ default:
+ /*
+ * Not 802.11.
+ */
+ break;
+ }
+ }
+
+ return (new_dlt);
+}
+
+pcap_t *
+pcap_create(const char *device, char *ebuf)
+{
+ pcap_t *p;
+
+ p = malloc(sizeof(*p));
+ if (p == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ return (NULL);
+ }
+ memset(p, 0, sizeof(*p));
+ p->fd = -1; /* not opened yet */
+
+ p->opt.source = strdup(device);
+ if (p->opt.source == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ free(p);
+ return (NULL);
+ }
+
+ /* put in some defaults*/
+ pcap_set_timeout(p, 0);
+ pcap_set_snaplen(p, 65535); /* max packet size */
+ p->opt.promisc = 0;
+ p->opt.buffer_size = 0;
+ return (p);
+}
+
+pcap_t *
+pcap_open_live(const char *source, int snaplen, int promisc, int to_ms,
+ char *errbuf)
+{
+ pcap_t *p;
+ int status;
+
+ p = pcap_create(source, errbuf);
+ if (p == NULL)
+ return (NULL);
+ status = pcap_set_snaplen(p, snaplen);
+ if (status < 0)
+ goto fail;
+ status = pcap_set_promisc(p, promisc);
+ if (status < 0)
+ goto fail;
+ status = pcap_set_timeout(p, to_ms);
+ if (status < 0)
+ goto fail;
+ /*
+ * Mark this as opened with pcap_open_live(), so that, for
+ * example, we show the full list of DLT_ values, rather
+ * than just the ones that are compatible with capturing
+ * when not in monitor mode. That allows existing applications
+ * to work the way they used to work, but allows new applications
+ * that know about the new open API to, for example, find out the
+ * DLT_ values that they can select without changing whether
+ * the adapter is in monitor mode or not.
+ */
+ p->oldstyle = 1;
+ status = pcap_activate(p);
+ if (status < 0)
+ goto fail;
+ return (p);
+fail:
+ if (status == PCAP_ERROR)
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source,
+ p->errbuf);
+ else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
+ status == PCAP_ERROR_PERM_DENIED ||
+ status == PCAP_ERROR_PROMISC_PERM_DENIED)
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", source,
+ pcap_statustostr(status), p->errbuf);
+ else
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source,
+ pcap_statustostr(status));
+ pcap_close(p);
return (NULL);
}
diff --git a/lib/libpcap/pcap-int.h b/lib/libpcap/pcap-int.h
index d870d326bca..4c0eac9dfe4 100644
--- a/lib/libpcap/pcap-int.h
+++ b/lib/libpcap/pcap-int.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcap-int.h,v 1.11 2006/03/26 20:58:51 djm Exp $ */
+/* $OpenBSD: pcap-int.h,v 1.12 2012/05/25 01:58:08 lteo Exp $ */
/*
* Copyright (c) 1994, 1995, 1996
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#) $Header: /cvs/OpenBSD/src/lib/libpcap/pcap-int.h,v 1.11 2006/03/26 20:58:51 djm Exp $ (LBL)
+ * @(#) $Header: /cvs/OpenBSD/src/lib/libpcap/pcap-int.h,v 1.12 2012/05/25 01:58:08 lteo Exp $ (LBL)
*/
#ifndef pcap_int_h
@@ -41,6 +41,18 @@
#include <pcap.h>
/*
+ * Stuff to do when we close.
+ */
+#define MUST_CLEAR_RFMON 0x00000002 /* clear rfmon (monitor) mode */
+
+struct pcap_opt {
+ int buffer_size;
+ char *source;
+ int promisc;
+ int rfmon;
+};
+
+/*
* Savefile
*/
struct pcap_sf {
@@ -60,11 +72,9 @@ struct pcap_md {
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 */
-#ifdef linux
- int pad;
- int skip;
- char *device;
-#endif
+ 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 */
};
struct pcap {
@@ -73,10 +83,13 @@ struct pcap {
int linktype;
int tzoff; /* timezone offset */
int offset; /* offset for proper alignment */
+ int activated; /* true if the capture is really started */
+ int oldstyle; /* if we're opening with pcap_open_live() */
int break_loop; /* force break from packet-reading loop */
struct pcap_sf sf;
struct pcap_md md;
+ struct pcap_opt opt;
/*
* Read buffer.
@@ -136,6 +149,11 @@ int yylex(void);
int pcap_offline_read(pcap_t *, int, pcap_handler, u_char *);
int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *);
+int pcap_do_addexit(pcap_t *);
+void pcap_add_to_pcaps_to_close(pcap_t *);
+void pcap_remove_from_pcaps_to_close(pcap_t *);
+int pcap_check_activated(pcap_t *);
+
/* Ultrix pads to make everything line up on a nice boundary */
#if defined(ultrix) || defined(__alpha)
#define PCAP_FDDIPAD 3
diff --git a/lib/libpcap/pcap.3 b/lib/libpcap/pcap.3
index dc4cf4b461d..dac4215ecb5 100644
--- a/lib/libpcap/pcap.3
+++ b/lib/libpcap/pcap.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: pcap.3,v 1.30 2007/05/31 19:19:36 jmc Exp $
+.\" $OpenBSD: pcap.3,v 1.31 2012/05/25 01:58:08 lteo Exp $
.\"
.\" Copyright (c) 1994, 1996, 1997
.\" The Regents of the University of California. All rights reserved.
@@ -19,7 +19,7 @@
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
-.Dd $Mdocdate: May 31 2007 $
+.Dd $Mdocdate: May 25 2012 $
.Dt PCAP 3
.Os
.Sh NAME
@@ -121,6 +121,24 @@
.Fn pcap_datalink_val_to_description "int"
.Ft int
.Fn pcap_datalink_name_to_val "const char *"
+.Ft "pcap_t *"
+.Fn pcap_create "const char *source" "char *errbuf"
+.Ft int
+.Fn pcap_set_snaplen "pcap_t *p" "int snaplen"
+.Ft int
+.Fn pcap_set_promisc "pcap_t *p" "int promisc"
+.Ft int
+.Fn pcap_can_set_rfmon "pcap_t *p"
+.Ft int
+.Fn pcap_set_rfmon "pcap_t *p" "int rfmon"
+.Ft int
+.Fn pcap_set_timeout "pcap_t *p" "int timeout"
+.Ft int
+.Fn pcap_set_buffer_size "pcap_t *p" "int buffer_size"
+.Ft int
+.Fn pcap_activate "pcap_t *p"
+.Ft const char *
+.Fn pcap_statustostr "int"
.Sh DESCRIPTION
.Nm
provides a high level interface to packet capture systems.
@@ -486,6 +504,57 @@ if the specified datalink type is not known.
.Fn pcap_datalink_name_to_val
finds the datalink number for a given datalink name.
Returns \-1 if the name is not known.
+.Pp
+.Fn pcap_create
+is used to create a packet capture handle to look at
+packets on the network.
+The returned handle must be activated with
+.Fn pcap_activate
+before packets can be captured with it; options for the
+capture, such as promiscuous mode, can be set on the handle
+before activating it.
+.Pp
+.Fn pcap_set_snaplen
+sets the snapshot length to be used on a capture handle when the
+handle is activated to
+.Fa snaplen .
+.Pp
+.Fn pcap_set_promisc
+sets whether promiscuous mode should be set on a capture handle
+when the handle is activated. If
+.Fa promisc
+is non-zero, promiscuous mode will be set, otherwise it will not be set.
+.Pp
+.Fn pcap_can_set_rfmon
+checks whether monitor mode could be set on a capture handle when the
+handle is activated.
+.Pp
+.Fn pcap_set_rfmon
+sets whether monitor mode should be set on a capture handle
+when the handle is activated. If
+.Fa rfmon
+is non-zero, monitor mode will be set, otherwise it will not be set.
+.Pp
+.Fn pcap_set_timeout
+sets the read timeout that will be used on a capture handle when the
+handle is activated to
+.Fa to_ms ,
+which is in units of milliseconds.
+.Pp
+.Fn pcap_set_buffer_size
+sets the buffer size that will be used on a capture handle when the
+handle is activated to
+.Fa buffer_size ,
+which is in units of bytes.
+.Pp
+.Fn pcap_activate
+is used to activate a packet capture handle to look at
+packets on the network, with the options that were set on the handle
+being in effect.
+.Pp
+.Fn pcap_statustostr
+converts a PCAP_ERROR_ or PCAP_WARNING_ value returned by a libpcap
+routine to an error string.
.Sh SEE ALSO
.Xr tcpdump 8
.\" , tcpslice(1)
diff --git a/lib/libpcap/pcap.c b/lib/libpcap/pcap.c
index 190c37305a9..591094fd2e7 100644
--- a/lib/libpcap/pcap.c
+++ b/lib/libpcap/pcap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcap.c,v 1.12 2010/06/26 16:47:07 henning Exp $ */
+/* $OpenBSD: pcap.c,v 1.13 2012/05/25 01:58:08 lteo Exp $ */
/*
* Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
@@ -175,6 +175,62 @@ pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
return (pcap_read(p, 1, pcap_fakecallback, (u_char *)&s));
}
+int
+pcap_check_activated(pcap_t *p)
+{
+ if (p->activated) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
+ " operation on activated capture");
+ return -1;
+ }
+ return 0;
+}
+
+int
+pcap_set_snaplen(pcap_t *p, int snaplen)
+{
+ if (pcap_check_activated(p))
+ return PCAP_ERROR_ACTIVATED;
+ p->snapshot = snaplen;
+ return 0;
+}
+
+int
+pcap_set_promisc(pcap_t *p, int promisc)
+{
+ if (pcap_check_activated(p))
+ return PCAP_ERROR_ACTIVATED;
+ p->opt.promisc = promisc;
+ return 0;
+}
+
+int
+pcap_set_rfmon(pcap_t *p, int rfmon)
+{
+ if (pcap_check_activated(p))
+ return PCAP_ERROR_ACTIVATED;
+ p->opt.rfmon = rfmon;
+ return 0;
+}
+
+int
+pcap_set_timeout(pcap_t *p, int timeout_ms)
+{
+ if (pcap_check_activated(p))
+ return PCAP_ERROR_ACTIVATED;
+ p->md.timeout = timeout_ms;
+ return 0;
+}
+
+int
+pcap_set_buffer_size(pcap_t *p, int buffer_size)
+{
+ if (pcap_check_activated(p))
+ return PCAP_ERROR_ACTIVATED;
+ p->opt.buffer_size = buffer_size;
+ return 0;
+}
+
/*
* Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate.
*/
@@ -387,6 +443,62 @@ pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
}
/*
+ * Generate error strings for PCAP_ERROR_ and PCAP_WARNING_ values.
+ */
+const char *
+pcap_statustostr(int errnum)
+{
+ static char ebuf[15+10+1];
+
+ switch (errnum) {
+
+ case PCAP_WARNING:
+ return("Generic warning");
+
+ case PCAP_WARNING_TSTAMP_TYPE_NOTSUP:
+ return ("That type of time stamp is not supported by that device");
+
+ case PCAP_WARNING_PROMISC_NOTSUP:
+ return ("That device doesn't support promiscuous mode");
+
+ case PCAP_ERROR:
+ return("Generic error");
+
+ case PCAP_ERROR_BREAK:
+ return("Loop terminated by pcap_breakloop");
+
+ case PCAP_ERROR_NOT_ACTIVATED:
+ return("The pcap_t has not been activated");
+
+ case PCAP_ERROR_ACTIVATED:
+ return ("The setting can't be changed after the pcap_t is activated");
+
+ case PCAP_ERROR_NO_SUCH_DEVICE:
+ return ("No such device exists");
+
+ case PCAP_ERROR_RFMON_NOTSUP:
+ return ("That device doesn't support monitor mode");
+
+ case PCAP_ERROR_NOT_RFMON:
+ return ("That operation is supported only in monitor mode");
+
+ case PCAP_ERROR_PERM_DENIED:
+ return ("You don't have permission to capture on that device");
+
+ case PCAP_ERROR_IFACE_NOT_UP:
+ return ("That device is not up");
+
+ case PCAP_ERROR_CANTSET_TSTAMP_TYPE:
+ return ("That device doesn't support setting the time stamp type");
+
+ case PCAP_ERROR_PROMISC_PERM_DENIED:
+ return ("You don't have permission to capture in promiscuous mode on that device");
+ }
+ (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
+ return(ebuf);
+}
+
+/*
* Not all systems have strerror().
*/
char *
@@ -406,6 +518,95 @@ pcap_strerror(int errnum)
#endif
}
+/*
+ * On some platforms, we need to clean up promiscuous or monitor mode
+ * when we close a device - and we want that to happen even if the
+ * application just exits without explicitl closing devices.
+ * On those platforms, we need to register a "close all the pcaps"
+ * routine to be called when we exit, and need to maintain a list of
+ * pcaps that need to be closed to clean up modes.
+ *
+ * XXX - not thread-safe.
+ */
+
+/*
+ * List of pcaps on which we've done something that needs to be
+ * cleaned up.
+ * If there are any such pcaps, we arrange to call "pcap_close_all()"
+ * when we exit, and have it close all of them.
+ */
+static struct pcap *pcaps_to_close;
+
+/*
+ * TRUE if we've already called "atexit()" to cause "pcap_close_all()" to
+ * be called on exit.
+ */
+static int did_atexit;
+
+static void
+pcap_close_all(void)
+{
+ struct pcap *handle;
+
+ while ((handle = pcaps_to_close) != NULL)
+ pcap_close(handle);
+}
+
+int
+pcap_do_addexit(pcap_t *p)
+{
+ /*
+ * If we haven't already done so, arrange to have
+ * "pcap_close_all()" called when we exit.
+ */
+ if (!did_atexit) {
+ if (atexit(pcap_close_all) == -1) {
+ /*
+ * "atexit()" failed; let our caller know.
+ */
+ (void)strlcpy(p->errbuf, "atexit failed",
+ PCAP_ERRBUF_SIZE);
+ return (0);
+ }
+ did_atexit = 1;
+ }
+ return (1);
+}
+
+void
+pcap_add_to_pcaps_to_close(pcap_t *p)
+{
+ p->md.next = pcaps_to_close;
+ pcaps_to_close = p;
+}
+
+void
+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) {
+ if (pc == p) {
+ /*
+ * Found it. Remove it from the list.
+ */
+ if (prevpc == NULL) {
+ /*
+ * It was at the head of the list.
+ */
+ pcaps_to_close = pc->md.next;
+ } else {
+ /*
+ * It was in the middle of the list.
+ */
+ prevpc->md.next = pc->md.next;
+ }
+ break;
+ }
+ }
+}
+
pcap_t *
pcap_open_dead(int linktype, int snaplen)
{
@@ -421,28 +622,6 @@ pcap_open_dead(int linktype, int snaplen)
return p;
}
-void
-pcap_close(pcap_t *p)
-{
- /*XXX*/
- if (p->fd >= 0)
- close(p->fd);
- if (p->sf.rfile != NULL) {
- (void)fclose(p->sf.rfile);
- if (p->sf.base != NULL)
- free(p->sf.base);
- } else if (p->buffer != NULL)
- free(p->buffer);
-#ifdef linux
- if (p->md.device != NULL)
- free(p->md.device);
-#endif
- pcap_freecode(&p->fcode);
- if (p->dlt_list != NULL)
- free(p->dlt_list);
- free(p);
-}
-
const char *
pcap_lib_version(void)
{
diff --git a/lib/libpcap/pcap.h b/lib/libpcap/pcap.h
index bb71365e32a..77ff89c0132 100644
--- a/lib/libpcap/pcap.h
+++ b/lib/libpcap/pcap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcap.h,v 1.14 2006/03/26 20:58:51 djm Exp $ */
+/* $OpenBSD: pcap.h,v 1.15 2012/05/25 01:58:08 lteo Exp $ */
/*
* Copyright (c) 1993, 1994, 1995, 1996, 1997
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#) $Header: /cvs/OpenBSD/src/lib/libpcap/pcap.h,v 1.14 2006/03/26 20:58:51 djm Exp $ (LBL)
+ * @(#) $Header: /cvs/OpenBSD/src/lib/libpcap/pcap.h,v 1.15 2012/05/25 01:58:08 lteo Exp $ (LBL)
*/
#ifndef lib_pcap_h
@@ -130,12 +130,49 @@ struct pcap_addr {
struct sockaddr *dstaddr; /* P2P destination address for that address */
};
+/*
+ * Error codes for the pcap API.
+ * These will all be negative, so you can check for the success or
+ * failure of a call that returns these codes by checking for a
+ * negative value.
+ */
+#define PCAP_ERROR -1 /* generic error code */
+#define PCAP_ERROR_BREAK -2 /* loop terminated by pcap_breakloop */
+#define PCAP_ERROR_NOT_ACTIVATED -3 /* the capture needs to be activated */
+#define PCAP_ERROR_ACTIVATED -4 /* the operation can't be performed on already activated captures */
+#define PCAP_ERROR_NO_SUCH_DEVICE -5 /* no such device exists */
+#define PCAP_ERROR_RFMON_NOTSUP -6 /* this device doesn't support rfmon (monitor) mode */
+#define PCAP_ERROR_NOT_RFMON -7 /* operation supported only in monitor mode */
+#define PCAP_ERROR_PERM_DENIED -8 /* no permission to open the device */
+#define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */
+#define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10 /* this device doesn't support setting the time stamp type */
+#define PCAP_ERROR_PROMISC_PERM_DENIED -11 /* you don't have permission to capture in promiscuous mode */
+
+/*
+ * Warning codes for the pcap API.
+ * These will all be positive and non-zero, so they won't look like
+ * errors.
+ */
+#define PCAP_WARNING 1 /* generic warning code */
+#define PCAP_WARNING_PROMISC_NOTSUP 2 /* this device doesn't support promiscuous mode */
+#define PCAP_WARNING_TSTAMP_TYPE_NOTSUP 3 /* the requested time stamp type is not supported */
+
typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
const u_char *);
__BEGIN_DECLS
char *pcap_lookupdev(char *);
int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
+
+pcap_t *pcap_create(const char *, char *);
+int pcap_set_snaplen(pcap_t *, int);
+int pcap_set_promisc(pcap_t *, int);
+int pcap_can_set_rfmon(pcap_t *);
+int pcap_set_rfmon(pcap_t *, int);
+int pcap_set_timeout(pcap_t *, int);
+int pcap_set_buffer_size(pcap_t *, int);
+int pcap_activate(pcap_t *);
+
pcap_t *pcap_open_live(const char *, int, int, int, char *);
pcap_t *pcap_open_dead(int, int);
pcap_t *pcap_open_offline(const char *, char *);
@@ -155,6 +192,7 @@ int pcap_setnonblock(pcap_t *, int, char *);
void pcap_perror(pcap_t *, char *);
int pcap_inject(pcap_t *, const void *, size_t);
int pcap_sendpacket(pcap_t *, const u_char *, int);
+const char *pcap_statustostr(int);
char *pcap_strerror(int);
char *pcap_geterr(pcap_t *);
int pcap_compile(pcap_t *, struct bpf_program *, char *, int,
diff --git a/lib/libpcap/savefile.c b/lib/libpcap/savefile.c
index e9ccefff3c0..c0527bacf3b 100644
--- a/lib/libpcap/savefile.c
+++ b/lib/libpcap/savefile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: savefile.c,v 1.9 2006/03/26 20:58:51 djm Exp $ */
+/* $OpenBSD: savefile.c,v 1.10 2012/05/25 01:58:08 lteo Exp $ */
/*
* Copyright (c) 1993, 1994, 1995, 1996, 1997
@@ -395,6 +395,7 @@ pcap_dump_ftell(pcap_dumper_t *p)
return (ftell((FILE *)p));
}
+int
pcap_dump_flush(pcap_dumper_t *p)
{
diff --git a/lib/libpcap/shlib_version b/lib/libpcap/shlib_version
index 9c1551636c5..5b844bbf422 100644
--- a/lib/libpcap/shlib_version
+++ b/lib/libpcap/shlib_version
@@ -1,2 +1,2 @@
-major=6
+major=7
minor=0