I sent a diff to update libpcap in base in November 2011 [1].  Here's
the latest version that fixes a bug I found after running regression
tests on all pcap-based ports in the ports tree.

If anyone would like to test the diff, the programs in base that link to
libpcap and would also require testing are:

- /usr/libexec/spamlogd
- /usr/sbin/pppd
- /usr/sbin/tcpdump
- /sbin/tcpdump

There's also a test program in /usr/src/regress/lib/libpthread/pcap/
that uses libpcap.

I have set up a simple page at the following URL to keep track of my own
progress and to encourage more widespread testing.

http://lteo.net/libpcap/

If you do test it, I would really appreciate it if you could please let
me know your feedback, both positive and negative.

Thank you!
Lawrence

[1] http://marc.info/?l=openbsd-tech&m=132029368027597&w=2

====

How to apply:

cd /usr/src/lib/libpcap
patch < libpcap-1.2.0-20120511.diff
make obj
make includes
make
make install

cd /usr/src/usr.sbin/tcpdump
make obj && make && make install

cd /usr/src/libexec/spamlogd
make obj && make && make install

cd /usr/src/sbin/pflogd
make obj && make && make install

cd /usr/src/usr.sbin/pppd
make obj && make && make install

Index: Makefile
===================================================================
RCS file: /cvs/src/lib/libpcap/Makefile,v
retrieving revision 1.20
diff -u -p -r1.20 Makefile
--- Makefile    13 Aug 2009 19:54:58 -0000      1.20
+++ Makefile    11 May 2012 04:35:01 -0000
@@ -25,11 +25,15 @@ MLINKS=     pcap.3 pcap_open_live.3 pcap.3 p
        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}
 
Index: pcap-bpf.c
===================================================================
RCS file: /cvs/src/lib/libpcap/pcap-bpf.c,v
retrieving revision 1.20
diff -u -p -r1.20 pcap-bpf.c
--- pcap-bpf.c  26 Mar 2006 20:58:51 -0000      1.20
+++ pcap-bpf.c  11 May 2012 04:35:01 -0000
@@ -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,12 @@
 
 #include "gencode.h"
 
+static int find_802_11(struct bpf_dltlist *);
+static int monitor_mode(pcap_t *, int);
+
+static int pcap_activate_bpf(pcap_t *p);
+static int pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp);
+
 int
 pcap_stats(pcap_t *p, struct pcap_stat *ps)
 {
@@ -54,7 +62,7 @@ pcap_stats(pcap_t *p, struct pcap_stat *
        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 +84,11 @@ pcap_read(pcap_t *p, int cnt, pcap_handl
        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 +103,21 @@ pcap_read(pcap_t *p, int cnt, pcap_handl
 
                        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 retur 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 +135,7 @@ pcap_read(pcap_t *p, int cnt, pcap_handl
                        }
                        snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s",
                            pcap_strerror(errno));
-                       return (-1);
+                       return (PCAP_ERROR);
                }
                bp = p->buffer;
        } else
@@ -129,21 +152,36 @@ pcap_read(pcap_t *p, int cnt, pcap_handl
                /*
                 * 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 +216,7 @@ pcap_sendpacket(pcap_t *p, const u_char 
 
 /* ARGSUSED */
 static __inline int
-bpf_open(pcap_t *p, char *errbuf)
+bpf_open(pcap_t *p)
 {
        int fd;
        int n = 0;
@@ -197,50 +235,279 @@ 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) {
+               u_int i;
+               int is_ethernet;
+
+               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 +519,36 @@ pcap_open_live(const char *device, int s
        (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 +562,418 @@ pcap_open_live(const char *device, int s
        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);
 }
 
Index: pcap-int.h
===================================================================
RCS file: /cvs/src/lib/libpcap/pcap-int.h,v
retrieving revision 1.11
diff -u -p -r1.11 pcap-int.h
--- pcap-int.h  26 Mar 2006 20:58:51 -0000      1.11
+++ pcap-int.h  11 May 2012 04:35:01 -0000
@@ -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.
@@ -135,6 +148,11 @@ int        yylex(void);
 /* XXX should these be in pcap.h? */
 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)
Index: pcap.3
===================================================================
RCS file: /cvs/src/lib/libpcap/pcap.3,v
retrieving revision 1.30
diff -u -p -r1.30 pcap.3
--- pcap.3      31 May 2007 19:19:36 -0000      1.30
+++ pcap.3      11 May 2012 04:35:01 -0000
@@ -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 kn
 .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)
Index: pcap.c
===================================================================
RCS file: /cvs/src/lib/libpcap/pcap.c,v
retrieving revision 1.12
diff -u -p -r1.12 pcap.c
--- pcap.c      26 Jun 2010 16:47:07 -0000      1.12
+++ pcap.c      11 May 2012 04:35:01 -0000
@@ -175,6 +175,62 @@ pcap_next_ex(pcap_t *p, struct pcap_pkth
        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
 }
 
 /*
+ * 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)
 {
@@ -419,28 +620,6 @@ pcap_open_dead(int linktype, int snaplen
        p->linktype = linktype;
        p->fd = -1;
        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 *
Index: pcap.h
===================================================================
RCS file: /cvs/src/lib/libpcap/pcap.h,v
retrieving revision 1.14
diff -u -p -r1.14 pcap.h
--- pcap.h      26 Mar 2006 20:58:51 -0000      1.14
+++ pcap.h      11 May 2012 04:35:01 -0000
@@ -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,
Index: shlib_version
===================================================================
RCS file: /cvs/src/lib/libpcap/shlib_version,v
retrieving revision 1.12
diff -u -p -r1.12 shlib_version
@@ -1,2 +1,2 @@
-major=6
+major=7
 minor=0

Reply via email to