This diff ports a few core functions from libpcap 1.2.0 to libpcap in
base.  My main goal is to get the latest versions of Snort (2.9.x) to
build and run, which requires these functions from libpcap>=1.0.
(Technically, it is not Snort that needs libpcap>=1.0, but rather a new
"data aquisition" library called daq that Snort 2.9.x uses to read
packets.)

I have confirmed that Snort 2.9.x will run with this new libpcap and
have managed to make it trigger alerts from fake attack traffic.
Programs other than Snort might also benefit from a more up-to-date
libpcap.

I have tried very carefully to preserve the local changes in base, and
have followed the approach of djm's past commit which imported just
"the good bits" from upstream libpcap without the cross-platform cruft,
as well as strncpy()->strlcpy() and malloc(n*m)->calloc() changes.

This change is backwards-compatible with older versions of libpcap,
such that existing libpcap-based programs like tcpdump, spamlogd,
pflogd, pppd, and the libpthread regression test should not need any
code changes. I have done some basic testing of all these programs but
could not test pppd other than confirming that it builds.

I am also in the midst of building and testing ports that depend on
libpcap to confirm that they work (mainly doing basic tests and running
"make regress" where applicable). There are more than 100 ports that
use libpcap so I would really appreciate some testing help here. :)

Here's a quick one-liner that shows ports that depend on libpcap:

find /usr/ports -name Makefile -exec grep -rn pcap {} ';' | cut -d: -f1 | sort 
-u

I would really appreciate comments, feedback, and tests on this diff.
If anyone is interested in my hackish proof-of-concept daq and Snort
ports, please let me know too.

Thank you,
Lawrence


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    1 Nov 2011 03:54:45 -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  1 Nov 2011 03:54:45 -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,11 +62,12 @@ 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;
        ps->ps_drop = s.bs_drop;
+       ps->ps_ifdrop = 0;
        return (0);
 }
 
@@ -76,11 +85,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 +104,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 +136,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 +153,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 +217,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 +236,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 +520,34 @@ 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;
+               }
+       }
+
+       (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));
+               snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+                   p->opt.source, pcap_strerror(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 +561,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  1 Nov 2011 03:54:45 -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      1 Nov 2011 03:54:45 -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      1 Nov 2011 03:54:46 -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      1 Nov 2011 03:54:46 -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