summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDamien Miller <djm@cvs.openbsd.org>2005-11-18 11:05:40 +0000
committerDamien Miller <djm@cvs.openbsd.org>2005-11-18 11:05:40 +0000
commitb3d796352917fe2a0f9021b3d370e7fa278210f1 (patch)
tree0c943c5097ed32c71ced43194d854fcb75db9446 /lib
parent237b9b47f2326dabd4a6bddc33123e3a52be6179 (diff)
pull in the good bits of libpcap-0.9.4's API without the cross-platform
cruft. help from deraadt@, mpf@, jmc@; ok mpf@a nb. this will break tcpdump unless it updated too
Diffstat (limited to 'lib')
-rw-r--r--lib/libpcap/Makefile13
-rw-r--r--lib/libpcap/fad-getad.c498
-rw-r--r--lib/libpcap/inet.c68
-rw-r--r--lib/libpcap/pcap-bpf.c113
-rw-r--r--lib/libpcap/pcap-int.h19
-rw-r--r--lib/libpcap/pcap-namedb.h6
-rw-r--r--lib/libpcap/pcap.383
-rw-r--r--lib/libpcap/pcap.c182
-rw-r--r--lib/libpcap/pcap.h45
-rw-r--r--lib/libpcap/shlib_version4
10 files changed, 997 insertions, 34 deletions
diff --git a/lib/libpcap/Makefile b/lib/libpcap/Makefile
index 12d178175ac..3e0d2a560ac 100644
--- a/lib/libpcap/Makefile
+++ b/lib/libpcap/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.15 2003/02/20 03:20:09 deraadt Exp $
+# $OpenBSD: Makefile,v 1.16 2005/11/18 11:05:38 djm Exp $
# $NetBSD: Makefile,v 1.3 1996/05/10 21:54:24 cgd Exp $
LIB= pcap
@@ -13,7 +13,14 @@ MLINKS= pcap.3 pcap_open_live.3 pcap.3 pcap_open_offline.3 \
pcap_stats.3 pcap.3 pcap_file.3 pcap.3 pcap_fileno.3 pcap.3 \
pcap_perror.3 pcap.3 pcap_geterr.3 pcap.3 pcap_strerror.3 \
pcap.3 pcap_close.3 pcap.3 pcap_dump_close.3 \
- pcap.3 pcap_freecode.3
+ pcap.3 pcap_freecode.3 pcap.3 pcap_breakloop.3 \
+ pcap.3 pcap_findalldevs.3 pcap.3 pcap_freealldevs.3 \
+ pcap.3 pcap_getnonblock.3 pcap.3 pcap_setnonblock.3 \
+ pcap.3 pcap_set_datalink.3 pcap.3 pcap_list_datalinks.3 \
+ pcap.3 pcap_open_dead.3 pcap.3 pcap_lib_version.3 \
+ pcap.3 pcap_datalink_val_to_name.3 \
+ pcap.3 pcap_datalink_val_to_description.3 \
+ pcap.3 pcap_datalink_name_to_val.3
DEFS= -DHAVE_SYS_IOCCOM_H -DHAVE_SYS_SOCKIO_H -DHAVE_ETHER_HOSTTON \
-DHAVE_STRERROR -DHAVE_SOCKADDR_SA_LEN -DLBL_ALIGN -DHAVE_IFADDRS_H \
@@ -24,7 +31,7 @@ CFLAGS+=-I. -I${.CURDIR} -Dyylval=pcap_yylval ${DEFS}
HDRS= pcap.h pcap-int.h pcap-namedb.h
SRCS= pcap.c inet.c gencode.c optimize.c nametoaddr.c etherent.c \
savefile.c bpf_filter.c bpf_image.c grammar.y scanner.l \
- pcap-bpf.c version.c
+ pcap-bpf.c version.c fad-getad.c
.PATH: ${.CURDIR}/../../sys/net
CLEANFILES+= grammar.c scanner.c grammar.tab.h version.c
diff --git a/lib/libpcap/fad-getad.c b/lib/libpcap/fad-getad.c
new file mode 100644
index 00000000000..94783071dfc
--- /dev/null
+++ b/lib/libpcap/fad-getad.c
@@ -0,0 +1,498 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1994, 1995, 1996, 1997, 1998
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/if.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ifaddrs.h>
+#include <limits.h>
+
+#include "pcap-int.h"
+
+static struct sockaddr *
+dup_sockaddr(struct sockaddr *sa, size_t sa_length)
+{
+ struct sockaddr *newsa;
+
+ if ((newsa = malloc(sa_length)) == NULL)
+ return (NULL);
+ return (memcpy(newsa, sa, sa_length));
+}
+
+static int
+get_instance(const char *name)
+{
+ const char *cp, *endcp;
+ int n;
+
+ if (strcmp(name, "any") == 0) {
+ /*
+ * Give the "any" device an artificially high instance
+ * number, so it shows up after all other non-loopback
+ * interfaces.
+ */
+ return INT_MAX;
+ }
+
+ endcp = name + strlen(name);
+ for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp)
+ continue;
+
+ if (isdigit((unsigned char)*cp))
+ n = atoi(cp);
+ else
+ n = 0;
+ return (n);
+}
+
+static int
+add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name,
+ u_int flags, const char *description, char *errbuf)
+{
+ pcap_t *p;
+ pcap_if_t *curdev, *prevdev, *nextdev;
+ int this_instance;
+ size_t len;
+
+ /*
+ * Can we open this interface for live capture?
+ *
+ * We do this check so that interfaces that are supplied
+ * by the interface enumeration mechanism we're using
+ * but that don't support packet capture aren't included
+ * in the list. An example of this is loopback interfaces
+ * on Solaris; we don't just omit loopback interfaces
+ * becaue you *can* capture on loopback interfaces on some
+ * OSes.
+ */
+ p = pcap_open_live(name, 68, 0, 0, errbuf);
+ if (p == NULL) {
+ /*
+ * No. Don't bother including it.
+ * Don't treat this as an error, though.
+ */
+ *curdev_ret = NULL;
+ return (0);
+ }
+ pcap_close(p);
+
+ /*
+ * Is there already an entry in the list for this interface?
+ */
+ for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) {
+ if (strcmp(name, curdev->name) == 0)
+ break; /* yes, we found it */
+ }
+ if (curdev == NULL) {
+ /*
+ * No, we didn't find it.
+ * Allocate a new entry.
+ */
+ curdev = malloc(sizeof(pcap_if_t));
+ if (curdev == NULL) {
+ (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ return (-1);
+ }
+
+ /*
+ * Fill in the entry.
+ */
+ curdev->next = NULL;
+ len = strlen(name) + 1;
+ curdev->name = malloc(len);
+ strlcpy(curdev->name, name, len);
+ if (description != NULL) {
+ /*
+ * We have a description for this interface.
+ */
+ len = strlen(description) + 1;
+ curdev->description = malloc(len);
+ strlcpy(curdev->description, description, len);
+ } else {
+ /*
+ * We don't.
+ */
+ curdev->description = NULL;
+ }
+ curdev->addresses = NULL; /* list starts out as empty */
+ curdev->flags = 0;
+ if (ISLOOPBACK(name, flags))
+ curdev->flags |= PCAP_IF_LOOPBACK;
+
+ /*
+ * Add it to the list, in the appropriate location.
+ * First, get the instance number of this interface.
+ */
+ this_instance = get_instance(name);
+
+ /*
+ * Now look for the last interface with an instance number
+ * less than or equal to the new interface's instance
+ * number - except that non-loopback interfaces are
+ * arbitrarily treated as having interface numbers less
+ * than those of loopback interfaces, so the loopback
+ * interfaces are put at the end of the list.
+ *
+ * We start with "prevdev" being NULL, meaning we're before
+ * the first element in the list.
+ */
+ prevdev = NULL;
+ for (;;) {
+ /*
+ * Get the interface after this one.
+ */
+ if (prevdev == NULL) {
+ /*
+ * The next element is the first element.
+ */
+ nextdev = *alldevs;
+ } else
+ nextdev = prevdev->next;
+
+ /*
+ * Are we at the end of the list?
+ */
+ if (nextdev == NULL) {
+ /*
+ * Yes - we have to put the new entry
+ * after "prevdev".
+ */
+ break;
+ }
+
+ /*
+ * Is the new interface a non-loopback interface
+ * and the next interface a loopback interface?
+ */
+ if (!(curdev->flags & PCAP_IF_LOOPBACK) &&
+ (nextdev->flags & PCAP_IF_LOOPBACK)) {
+ /*
+ * Yes, we should put the new entry
+ * before "nextdev", i.e. after "prevdev".
+ */
+ break;
+ }
+
+ /*
+ * Is the new interface's instance number less
+ * than the next interface's instance number,
+ * and is it the case that the new interface is a
+ * non-loopback interface or the next interface is
+ * a loopback interface?
+ *
+ * (The goal of both loopback tests is to make
+ * sure that we never put a loopback interface
+ * before any non-loopback interface and that we
+ * always put a non-loopback interface before all
+ * loopback interfaces.)
+ */
+ if (this_instance < get_instance(nextdev->name) &&
+ (!(curdev->flags & PCAP_IF_LOOPBACK) ||
+ (nextdev->flags & PCAP_IF_LOOPBACK))) {
+ /*
+ * Yes - we should put the new entry
+ * before "nextdev", i.e. after "prevdev".
+ */
+ break;
+ }
+
+ prevdev = nextdev;
+ }
+
+ /*
+ * Insert before "nextdev".
+ */
+ curdev->next = nextdev;
+
+ /*
+ * Insert after "prevdev" - unless "prevdev" is null,
+ * in which case this is the first interface.
+ */
+ if (prevdev == NULL) {
+ /*
+ * This is the first interface. Pass back a
+ * pointer to it, and put "curdev" before
+ * "nextdev".
+ */
+ *alldevs = curdev;
+ } else
+ prevdev->next = curdev;
+ }
+
+ *curdev_ret = curdev;
+ return (0);
+}
+
+static int
+add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags,
+ struct sockaddr *addr, size_t addr_size,
+ struct sockaddr *netmask, size_t netmask_size,
+ struct sockaddr *broadaddr, size_t broadaddr_size,
+ struct sockaddr *dstaddr, size_t dstaddr_size,
+ char *errbuf)
+{
+ pcap_if_t *curdev;
+ pcap_addr_t *curaddr, *prevaddr, *nextaddr;
+
+ if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) {
+ /*
+ * Error - give up.
+ */
+ return (-1);
+ }
+ if (curdev == NULL) {
+ /*
+ * Device wasn't added because it can't be opened.
+ * Not a fatal error.
+ */
+ return (0);
+ }
+
+ /*
+ * "curdev" is an entry for this interface; add an entry for this
+ * address to its list of addresses.
+ *
+ * Allocate the new entry and fill it in.
+ */
+ curaddr = malloc(sizeof(pcap_addr_t));
+ if (curaddr == NULL) {
+ (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ return (-1);
+ }
+
+ curaddr->next = NULL;
+ if (addr != NULL) {
+ curaddr->addr = dup_sockaddr(addr, addr_size);
+ if (curaddr->addr == NULL) {
+ (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ free(curaddr);
+ return (-1);
+ }
+ } else
+ curaddr->addr = NULL;
+
+ if (netmask != NULL) {
+ curaddr->netmask = dup_sockaddr(netmask, netmask_size);
+ if (curaddr->netmask == NULL) {
+ (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ free(curaddr);
+ return (-1);
+ }
+ } else
+ curaddr->netmask = NULL;
+
+ if (broadaddr != NULL) {
+ curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size);
+ if (curaddr->broadaddr == NULL) {
+ (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ free(curaddr);
+ return (-1);
+ }
+ } else
+ curaddr->broadaddr = NULL;
+
+ if (dstaddr != NULL) {
+ curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size);
+ if (curaddr->dstaddr == NULL) {
+ (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc: %s", pcap_strerror(errno));
+ free(curaddr);
+ return (-1);
+ }
+ } else
+ curaddr->dstaddr = NULL;
+
+ /*
+ * Find the end of the list of addresses.
+ */
+ for (prevaddr = curdev->addresses; prevaddr != NULL;
+ prevaddr = nextaddr) {
+ nextaddr = prevaddr->next;
+ if (nextaddr == NULL) {
+ /*
+ * This is the end of the list.
+ */
+ break;
+ }
+ }
+
+ if (prevaddr == NULL) {
+ /*
+ * The list was empty; this is the first member.
+ */
+ curdev->addresses = curaddr;
+ } else {
+ /*
+ * "prevaddr" is the last member of the list; append
+ * this member to it.
+ */
+ prevaddr->next = curaddr;
+ }
+
+ return (0);
+}
+
+/*
+ * Get a list of all interfaces that are up and that we can open.
+ * Returns -1 on error, 0 otherwise.
+ * The list, as returned through "alldevsp", may be null if no interfaces
+ * were up and could be opened.
+ *
+ * This is the implementation used on platforms that have "getifaddrs()".
+ */
+int
+pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
+{
+ pcap_if_t *devlist = NULL;
+ struct ifaddrs *ifap, *ifa;
+ struct sockaddr *addr, *netmask, *broadaddr, *dstaddr;
+ size_t addr_size, broadaddr_size, dstaddr_size;
+ int ret = 0;
+
+ /*
+ * Get the list of interface addresses.
+ *
+ * Note: this won't return information about interfaces
+ * with no addresses; are there any such interfaces
+ * that would be capable of receiving packets?
+ * (Interfaces incapable of receiving packets aren't
+ * very interesting from libpcap's point of view.)
+ *
+ * LAN interfaces will probably have link-layer
+ * addresses; I don't know whether all implementations
+ * of "getifaddrs()" now, or in the future, will return
+ * those.
+ */
+ if (getifaddrs(&ifap) != 0) {
+ (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "getifaddrs: %s", pcap_strerror(errno));
+ return (-1);
+ }
+ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+ /*
+ * Is this interface up?
+ */
+ if (!(ifa->ifa_flags & IFF_UP)) {
+ /*
+ * No, so don't add it to the list.
+ */
+ continue;
+ }
+
+ /*
+ * "ifa_addr" was apparently null on at least one
+ * interface on some system.
+ *
+ * "ifa_broadaddr" may be non-null even on
+ * non-broadcast interfaces, and was null on
+ * at least one OpenBSD 3.4 system on at least
+ * one interface with IFF_BROADCAST set.
+ *
+ * "ifa_dstaddr" was, on at least one FreeBSD 4.1
+ * system, non-null on a non-point-to-point
+ * interface.
+ *
+ * Therefore, we supply the address and netmask only
+ * if "ifa_addr" is non-null (if there's no address,
+ * there's obviously no netmask), and supply the
+ * broadcast and destination addresses if the appropriate
+ * flag is set *and* the appropriate "ifa_" entry doesn't
+ * evaluate to a null pointer.
+ */
+ if (ifa->ifa_addr != NULL) {
+ addr = ifa->ifa_addr;
+ addr_size = SA_LEN(addr);
+ netmask = ifa->ifa_netmask;
+ } else {
+ addr = NULL;
+ addr_size = 0;
+ netmask = NULL;
+ }
+ if (ifa->ifa_flags & IFF_BROADCAST &&
+ ifa->ifa_broadaddr != NULL) {
+ broadaddr = ifa->ifa_broadaddr;
+ broadaddr_size = SA_LEN(broadaddr);
+ } else {
+ broadaddr = NULL;
+ broadaddr_size = 0;
+ }
+ if (ifa->ifa_flags & IFF_POINTOPOINT &&
+ ifa->ifa_dstaddr != NULL) {
+ dstaddr = ifa->ifa_dstaddr;
+ dstaddr_size = SA_LEN(ifa->ifa_dstaddr);
+ } else {
+ dstaddr = NULL;
+ dstaddr_size = 0;
+ }
+
+ /*
+ * Add information for this address to the list.
+ */
+ if (add_addr_to_iflist(&devlist, ifa->ifa_name,
+ ifa->ifa_flags, addr, addr_size, netmask, addr_size,
+ broadaddr, broadaddr_size, dstaddr, dstaddr_size,
+ errbuf) < 0) {
+ ret = -1;
+ break;
+ }
+ }
+
+ freeifaddrs(ifap);
+
+ if (ret == -1) {
+ /*
+ * We had an error; free the list we've been constructing.
+ */
+ if (devlist != NULL) {
+ pcap_freealldevs(devlist);
+ devlist = NULL;
+ }
+ }
+
+ *alldevsp = devlist;
+ return (ret);
+}
diff --git a/lib/libpcap/inet.c b/lib/libpcap/inet.c
index 983275446d5..23bb811e04d 100644
--- a/lib/libpcap/inet.c
+++ b/lib/libpcap/inet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: inet.c,v 1.16 2004/01/27 06:58:03 tedu Exp $ */
+/* $OpenBSD: inet.c,v 1.17 2005/11/18 11:05:39 djm Exp $ */
/*
* Copyright (c) 1994, 1995, 1996, 1997, 1998
@@ -66,13 +66,52 @@ struct rtentry;
#include "os-proto.h"
#endif
-/* Not all systems have IFF_LOOPBACK */
-#ifdef IFF_LOOPBACK
-#define ISLOOPBACK(p) ((p)->ifr_flags & IFF_LOOPBACK)
-#else
-#define ISLOOPBACK(p) ((p)->ifr_name[0] == 'l' && (p)->ifr_name[1] == 'o' && \
- (isdigit((p)->ifr_name[2]) || (p)->ifr_name[2] == '\0'))
-#endif
+/*
+ * Free a list of interfaces.
+ */
+void
+pcap_freealldevs(pcap_if_t *alldevs)
+{
+ pcap_if_t *curdev, *nextdev;
+ pcap_addr_t *curaddr, *nextaddr;
+
+ for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
+ nextdev = curdev->next;
+
+ /*
+ * Free all addresses.
+ */
+ for (curaddr = curdev->addresses; curaddr != NULL;
+ curaddr = nextaddr) {
+ nextaddr = curaddr->next;
+ if (curaddr->addr)
+ free(curaddr->addr);
+ if (curaddr->netmask)
+ free(curaddr->netmask);
+ if (curaddr->broadaddr)
+ free(curaddr->broadaddr);
+ if (curaddr->dstaddr)
+ free(curaddr->dstaddr);
+ free(curaddr);
+ }
+
+ /*
+ * Free the name string.
+ */
+ free(curdev->name);
+
+ /*
+ * Free the description string, if any.
+ */
+ if (curdev->description != NULL)
+ free(curdev->description);
+
+ /*
+ * Free the interface.
+ */
+ free(curdev);
+ }
+}
/*
* Return the name of a network interface attached to the system, or NULL
@@ -100,16 +139,8 @@ pcap_lookupdev(errbuf)
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
if ((ifa->ifa_flags & IFF_UP) == 0)
continue;
-#ifdef IFF_LOOPBACK
- if ((ifa->ifa_flags & IFF_LOOPBACK) != 0)
- continue;
-#else
- if (strncmp(ifa->ifa_name, "lo", 2) == 0 &&
- (ifa->ifa_name[2] == '\0' || isdigit(ifa->ifa_name[2]))) {
+ if (ISLOOPBACK(ifa->ifa_name, ifa->ifa_flags))
continue;
- }
-#endif
-
for (cp = ifa->ifa_name; !isdigit(*cp); ++cp)
continue;
n = atoi(cp);
@@ -190,7 +221,8 @@ pcap_lookupdev(errbuf)
}
/* Must be up and not the loopback */
- if ((ifr.ifr_flags & IFF_UP) == 0 || ISLOOPBACK(&ifr))
+ if ((ifr.ifr_flags & IFF_UP) == 0 ||
+ ISLOOPBACK(ifr.ifr_name, ifr.ifr_flags)
continue;
for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp)
diff --git a/lib/libpcap/pcap-bpf.c b/lib/libpcap/pcap-bpf.c
index f81375e0203..ac72b43f703 100644
--- a/lib/libpcap/pcap-bpf.c
+++ b/lib/libpcap/pcap-bpf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcap-bpf.c,v 1.16 2004/02/06 22:41:24 tedu Exp $ */
+/* $OpenBSD: pcap-bpf.c,v 1.17 2005/11/18 11:05:39 djm Exp $ */
/*
* Copyright (c) 1993, 1994, 1995, 1996, 1998
@@ -70,6 +70,19 @@ pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
register u_char *bp, *ep;
again:
+ /*
+ * Has "pcap_breakloop()" been called?
+ */
+ 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.
+ */
+ p->break_loop = 0;
+ return (-2);
+ }
+
cc = p->cc;
if (p->cc == 0) {
cc = read(p->fd, (char *)p->buffer, p->bufsize);
@@ -112,6 +125,27 @@ pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
ep = bp + cc;
while (bp < ep) {
register int caplen, hdrlen;
+
+ /*
+ * 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.
+ */
+ if (p->break_loop) {
+ if (n == 0) {
+ p->break_loop = 0;
+ return (-2);
+ } else {
+ p->bp = bp;
+ p->cc = ep - bp;
+ return (n);
+ }
+ }
+
caplen = bhp->bh_caplen;
hdrlen = bhp->bh_hdrlen;
/*
@@ -164,13 +198,15 @@ bpf_open(pcap_t *p, char *errbuf)
}
pcap_t *
-pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
+pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
+ char *ebuf)
{
int fd;
struct ifreq ifr;
struct bpf_version bv;
u_int v;
pcap_t *p;
+ struct bpf_dltlist bdl;
p = (pcap_t *)malloc(sizeof(*p));
if (p == NULL) {
@@ -235,6 +271,37 @@ pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
#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.
+ */
+ bzero(&bdl, sizeof(bdl));
+ if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) == 0) {
+ bdl.bfl_list = (u_int *) malloc(sizeof(u_int) *
+ bdl.bfl_len + 1);
+ if (bdl.bfl_list == NULL) {
+ (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
+ pcap_strerror(errno));
+ goto bad;
+ }
+
+ if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) < 0) {
+ (void)snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "BIOCGDLTLIST: %s", pcap_strerror(errno));
+ free(bdl.bfl_list);
+ 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;
+ }
+ }
+
/* set timeout */
if (to_ms != 0) {
struct timeval to;
@@ -298,3 +365,45 @@ pcap_setfilter(pcap_t *p, struct bpf_program *fp)
}
return (0);
}
+
+int
+pcap_set_datalink(pcap_t *p, int dlt)
+{
+ int i;
+
+ if (p->dlt_count == 0) {
+ /*
+ * We couldn't fetch the list of DLTs, or we don't
+ * have a "set datalink" operation, which means
+ * this platform doesn't support changing the
+ * DLT for an interface. Check whether the new
+ * DLT is the one this interface supports.
+ */
+ if (p->linktype != dlt)
+ goto unsupported;
+
+ /*
+ * It is, so there's nothing we need to do here.
+ */
+ return (0);
+ }
+ for (i = 0; i < p->dlt_count; i++)
+ if (p->dlt_list[i] == dlt)
+ break;
+ if (i >= p->dlt_count)
+ goto unsupported;
+ if (ioctl(p->fd, BIOCSDLT, &dlt) == -1) {
+ (void) snprintf(p->errbuf, sizeof(p->errbuf),
+ "Cannot set DLT %d: %s", dlt, strerror(errno));
+ return (-1);
+ }
+ p->linktype = dlt;
+ return (0);
+
+unsupported:
+ (void) snprintf(p->errbuf, sizeof(p->errbuf),
+ "DLT %d is not one of the DLTs supported by this device",
+ dlt);
+ return (-1);
+}
+
diff --git a/lib/libpcap/pcap-int.h b/lib/libpcap/pcap-int.h
index a3997831619..e5d2e204b33 100644
--- a/lib/libpcap/pcap-int.h
+++ b/lib/libpcap/pcap-int.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcap-int.h,v 1.9 2001/10/02 18:04:35 deraadt Exp $ */
+/* $OpenBSD: pcap-int.h,v 1.10 2005/11/18 11:05:39 djm Exp $ */
/*
* Copyright (c) 1994, 1995, 1996
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#) $Header: /cvs/OpenBSD/src/lib/libpcap/pcap-int.h,v 1.9 2001/10/02 18:04:35 deraadt Exp $ (LBL)
+ * @(#) $Header: /cvs/OpenBSD/src/lib/libpcap/pcap-int.h,v 1.10 2005/11/18 11:05:39 djm Exp $ (LBL)
*/
#ifndef pcap_int_h
@@ -73,6 +73,7 @@ struct pcap {
int linktype;
int tzoff; /* timezone offset */
int offset; /* offset for proper alignment */
+ int break_loop; /* force break from packet-reading loop */
struct pcap_sf sf;
struct pcap_md md;
@@ -96,6 +97,12 @@ struct pcap {
*/
struct bpf_program fcode;
+ /*
+ * Datalink types supported on underlying fd
+ */
+ int dlt_count;
+ u_int *dlt_list;
+
char errbuf[PCAP_ERRBUF_SIZE];
};
@@ -115,6 +122,14 @@ int yylex(void);
#define min(a, b) ((a) > (b) ? (b) : (a))
#endif
+/* Not all systems have IFF_LOOPBACK */
+#ifdef IFF_LOOPBACK
+#define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK)
+#else
+#define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \
+ (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0'))
+#endif
+
/* 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 *);
diff --git a/lib/libpcap/pcap-namedb.h b/lib/libpcap/pcap-namedb.h
index 5b50bc77867..5e336b28d4f 100644
--- a/lib/libpcap/pcap-namedb.h
+++ b/lib/libpcap/pcap-namedb.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcap-namedb.h,v 1.6 2000/04/26 21:25:53 jakob Exp $ */
+/* $OpenBSD: pcap-namedb.h,v 1.7 2005/11/18 11:05:39 djm Exp $ */
/*
* Copyright (c) 1994, 1996
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#) $Header: /cvs/OpenBSD/src/lib/libpcap/pcap-namedb.h,v 1.6 2000/04/26 21:25:53 jakob Exp $ (LBL)
+ * @(#) $Header: /cvs/OpenBSD/src/lib/libpcap/pcap-namedb.h,v 1.7 2005/11/18 11:05:39 djm Exp $ (LBL)
*/
#ifndef lib_pcap_ethers_h
@@ -65,6 +65,8 @@ bpf_u_int32 pcap_nametonetaddr(const char *);
int pcap_nametoport(const char *, int *, int *);
int pcap_nametoproto(const char *);
int pcap_nametoeproto(const char *);
+int pcap_nametollc(const char *);
+
/*
* If a protocol is unknown, PROTO_UNDEF is returned.
* Also, pcap_nametoport() returns the protocol along with the port number.
diff --git a/lib/libpcap/pcap.3 b/lib/libpcap/pcap.3
index 666ac9ab549..e144afd32cb 100644
--- a/lib/libpcap/pcap.3
+++ b/lib/libpcap/pcap.3
@@ -1,4 +1,4 @@
-.\" $OpenBSD: pcap.3,v 1.25 2003/03/06 20:13:15 jmc Exp $
+.\" $OpenBSD: pcap.3,v 1.26 2005/11/18 11:05:39 djm Exp $
.\"
.\" Copyright (c) 1994, 1996, 1997
.\" The Regents of the University of California. All rights reserved.
@@ -79,6 +79,30 @@
.Fn pcap_close "pcap_t *p"
.Ft void
.Fn pcap_dump_close "pcap_dumper_t *p"
+.Ft int
+.Fn pcap_breakloop "pcap_t *p"
+.Ft int
+.Fn pcap_findalldevs "pcap_if_t **alldevsp" "char *errbuf"
+.Ft void
+.Fn pcap_freealldevs "pcap_if_t *alldevs"
+.Ft int
+.Fn pcap_getnonblock "pcap_t *p" "char *errbuf"
+.Ft int
+.Fn pcap_setnonblock "pcap_t *p" "int nonblock" "char *errbuf"
+.Ft int
+.Fn pcap_set_datalink "pcap_t *" "int dlt"
+.Ft int
+.Fn pcap_list_datalinks "pcap_t *p" "int **dlts"
+.Ft pcap_t
+.Fn pcap_open_dead "int linktype" "int snaplen"
+.Ft const char *
+.Fn pcap_lib_version "void"
+.Ft const char *
+.Fn pcap_datalink_val_to_name "int"
+.Ft const char *
+.Fn pcap_datalink_val_to_description "int"
+.Ft int
+.Fn pcap_datalink_name_to_val "const char *"
.Sh DESCRIPTION
.Nm
provides a high level interface to packet capture systems.
@@ -91,6 +115,7 @@ through this mechanism.
in
.Fn pcap_open_live ,
.Fn pcap_open_offline ,
+.Fn pcap_findalldevs ,
.Fn pcap_lookupdev ,
and
.Fn pcap_lookupnet
@@ -287,6 +312,12 @@ A negative
causes
.Fn pcap_loop
to loop forever (or at least until an error occurs).
+.Fn pcap_loop
+may be terminated early through an explicit call to
+.Fn pcap_breakloop .
+In this case, the return value of
+.Fn pcap_loop
+will be \-2.
.Pp
.Fn pcap_next
returns a
@@ -352,6 +383,56 @@ and deallocates resources.
.Pp
.Fn pcap_dump_close
closes the savefile.
+.Pp
+.Fn pcap_findalldevs
+constructs a linked list of network devices that are suitable for
+opening with
+.Fn pcap_open_live .
+.Pp
+.Fn pcap_freealldevs
+frees a list of interfaces built by
+.Fn pcap_findalldevs .
+.Pp
+.Fn pcap_getnonblock
+returns 1 if the capture file descriptor is in non-blocking mode, 0
+if it is in blocking mode, or \-1 on error.
+.Pp
+.Fn pcap_setnonblock
+sets or resets non-blocking mode on a capture file descriptor.
+.Pp
+.Fn pcap_set_datalink
+sets the datalink type on a live capture device that supports multiple
+datalink types.
+.Pp
+.Fn pcap_list_datalinks
+returns an array of the supported datalink types for an opened live capture
+device as a \-1 terminated array.
+It is the caller's responsibility to free this list.
+.Pp
+.Fn pcap_breakloop
+safely breaks out of a
+.Fn pcap_loop .
+This function sets an internal flag and is safe to be called from inside a
+signal handler.
+.Pp
+.Fn pcap_open_dead
+is used for creating a pcap_t structure to use when calling the
+other functions in libpcap.
+It is typically used when just using libpcap for compiling BPF code.
+.Pp
+.Fn pcap_lib_version
+returns a string describing the version of
+.Xr pcap 3 .
+.Fn pcap_datalink_val_to_name
+and
+.Fn pcap_datalink_val_to_description
+lookup the name or description of a datalink type by number.
+These functions return
+.Dv NULL
+if the specified datalink type is not known.
+.Fn pcap_datalink_name_to_val
+finds the datalink number for a given datalink name.
+Returns \-1 if the name is not known.
.Sh SEE ALSO
.Xr tcpdump 8
.\" , tcpslice(1)
diff --git a/lib/libpcap/pcap.c b/lib/libpcap/pcap.c
index 3eab3051cef..30f58292718 100644
--- a/lib/libpcap/pcap.c
+++ b/lib/libpcap/pcap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcap.c,v 1.8 2004/01/27 06:58:03 tedu Exp $ */
+/* $OpenBSD: pcap.c,v 1.9 2005/11/18 11:05:39 djm Exp $ */
/*
* Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
@@ -39,6 +39,8 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
#ifdef HAVE_OS_PROTO_H
#include "os-proto.h"
@@ -46,6 +48,8 @@
#include "pcap-int.h"
+static const char pcap_version_string[] = "OpenBSD libpcap";
+
int
pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
@@ -107,6 +111,15 @@ pcap_next(pcap_t *p, struct pcap_pkthdr *h)
return (s.pkt);
}
+/*
+ * Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate.
+ */
+void
+pcap_breakloop(pcap_t *p)
+{
+ p->break_loop = 1;
+}
+
int
pcap_datalink(pcap_t *p)
{
@@ -114,6 +127,109 @@ pcap_datalink(pcap_t *p)
}
int
+pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
+{
+ if (p->dlt_count == 0) {
+ /*
+ * We couldn't fetch the list of DLTs, which means
+ * this platform doesn't support changing the
+ * DLT for an interface. Return a list of DLTs
+ * containing only the DLT this device supports.
+ */
+ *dlt_buffer = (int*)malloc(sizeof(**dlt_buffer));
+ if (*dlt_buffer == NULL) {
+ (void)snprintf(p->errbuf, sizeof(p->errbuf),
+ "malloc: %s", pcap_strerror(errno));
+ return (-1);
+ }
+ **dlt_buffer = p->linktype;
+ return (1);
+ } else {
+ *dlt_buffer = (int*)malloc(sizeof(**dlt_buffer) * p->dlt_count);
+ if (*dlt_buffer == NULL) {
+ (void)snprintf(p->errbuf, sizeof(p->errbuf),
+ "malloc: %s", pcap_strerror(errno));
+ return (-1);
+ }
+ (void)memcpy(*dlt_buffer, p->dlt_list,
+ sizeof(**dlt_buffer) * p->dlt_count);
+ return (p->dlt_count);
+ }
+}
+
+struct dlt_choice {
+ const char *name;
+ const char *description;
+ int dlt;
+};
+
+static struct dlt_choice dlts[] = {
+#define DLT_CHOICE(code, description) { #code, description, code }
+DLT_CHOICE(DLT_NULL, "no link-layer encapsulation"),
+DLT_CHOICE(DLT_EN10MB, "Ethernet (10Mb)"),
+DLT_CHOICE(DLT_EN3MB, "Experimental Ethernet (3Mb)"),
+DLT_CHOICE(DLT_AX25, "Amateur Radio AX.25"),
+DLT_CHOICE(DLT_PRONET, "Proteon ProNET Token Ring"),
+DLT_CHOICE(DLT_CHAOS, "Chaos"),
+DLT_CHOICE(DLT_IEEE802, "IEEE 802 Networks"),
+DLT_CHOICE(DLT_ARCNET, "ARCNET"),
+DLT_CHOICE(DLT_SLIP, "Serial Line IP"),
+DLT_CHOICE(DLT_PPP, "Point-to-point Protocol"),
+DLT_CHOICE(DLT_FDDI, "FDDI"),
+DLT_CHOICE(DLT_ATM_RFC1483, "LLC/SNAP encapsulated atm"),
+DLT_CHOICE(DLT_LOOP, "loopback type (af header)"),
+DLT_CHOICE(DLT_ENC, "IPSEC enc type (af header, spi, flags)"),
+DLT_CHOICE(DLT_RAW, "raw IP"),
+DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS Serial Line IP"),
+DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS Point-to-point Protocol"),
+DLT_CHOICE(DLT_OLD_PFLOG, "Packet filter logging, old (XXX remove?)"),
+DLT_CHOICE(DLT_PFSYNC, "Packet filter state syncing"),
+DLT_CHOICE(DLT_PPP_ETHER, "PPP over Ethernet; session only w/o ether header"),
+DLT_CHOICE(DLT_IEEE802_11, "IEEE 802.11 wireless"),
+DLT_CHOICE(DLT_PFLOG, "Packet filter logging, by pcap people"),
+DLT_CHOICE(DLT_IEEE802_11_RADIO, "IEEE 802.11 plus WLAN header"),
+#undef DLT_CHOICE
+ { NULL, NULL, -1}
+};
+
+int
+pcap_datalink_name_to_val(const char *name)
+{
+ int i;
+
+ for (i = 0; dlts[i].name != NULL; i++) {
+ /* Skip leading "DLT_" */
+ if (strcasecmp(dlts[i].name + 4, name) == 0)
+ return (dlts[i].dlt);
+ }
+ return (-1);
+}
+
+const char *
+pcap_datalink_val_to_name(int dlt)
+{
+ int i;
+
+ for (i = 0; dlts[i].name != NULL; i++) {
+ if (dlts[i].dlt == dlt)
+ return (dlts[i].name + 4); /* Skip leading "DLT_" */
+ }
+ return (NULL);
+}
+
+const char *
+pcap_datalink_val_to_description(int dlt)
+{
+ int i;
+
+ for (i = 0; dlts[i].name != NULL; i++) {
+ if (dlts[i].dlt == dlt)
+ return (dlts[i].description);
+ }
+ return (NULL);
+}
+
+int
pcap_snapshot(pcap_t *p)
{
return (p->snapshot);
@@ -161,6 +277,46 @@ pcap_geterr(pcap_t *p)
return (p->errbuf);
}
+int
+pcap_getnonblock(pcap_t *p, char *errbuf)
+{
+ int fdflags;
+
+ fdflags = fcntl(p->fd, F_GETFL, 0);
+ if (fdflags == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
+ pcap_strerror(errno));
+ return (-1);
+ }
+ if (fdflags & O_NONBLOCK)
+ return (1);
+ else
+ return (0);
+}
+
+int
+pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
+{
+ int fdflags;
+
+ fdflags = fcntl(p->fd, F_GETFL, 0);
+ if (fdflags == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
+ pcap_strerror(errno));
+ return (-1);
+ }
+ if (nonblock)
+ fdflags |= O_NONBLOCK;
+ else
+ fdflags &= ~O_NONBLOCK;
+ if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
+ pcap_strerror(errno));
+ return (-1);
+ }
+ return (0);
+}
+
/*
* Not all systems have strerror().
*/
@@ -181,6 +337,21 @@ pcap_strerror(int errnum)
#endif
}
+pcap_t *
+pcap_open_dead(int linktype, int snaplen)
+{
+ pcap_t *p;
+
+ p = malloc(sizeof(*p));
+ if (p == NULL)
+ return NULL;
+ memset (p, 0, sizeof(*p));
+ p->snapshot = snaplen;
+ p->linktype = linktype;
+ p->fd = -1;
+ return p;
+}
+
void
pcap_close(pcap_t *p)
{
@@ -198,5 +369,14 @@ pcap_close(pcap_t *p)
free(p->md.device);
#endif
pcap_freecode(&p->fcode);
+ if (p->dlt_list != NULL)
+ free(p->dlt_list);
free(p);
}
+
+const char *
+pcap_lib_version(void)
+{
+ return (pcap_version_string);
+}
+
diff --git a/lib/libpcap/pcap.h b/lib/libpcap/pcap.h
index 0404f31f92e..f4c0e2eade6 100644
--- a/lib/libpcap/pcap.h
+++ b/lib/libpcap/pcap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcap.h,v 1.12 2004/06/24 18:29:38 naddy Exp $ */
+/* $OpenBSD: pcap.h,v 1.13 2005/11/18 11:05:39 djm Exp $ */
/*
* Copyright (c) 1993, 1994, 1995, 1996, 1997
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#) $Header: /cvs/OpenBSD/src/lib/libpcap/pcap.h,v 1.12 2004/06/24 18:29:38 naddy Exp $ (LBL)
+ * @(#) $Header: /cvs/OpenBSD/src/lib/libpcap/pcap.h,v 1.13 2005/11/18 11:05:39 djm Exp $ (LBL)
*/
#ifndef lib_pcap_h
@@ -60,6 +60,8 @@ typedef u_int bpf_u_int32;
#endif
typedef struct pcap pcap_t;
+typedef struct pcap_if pcap_if_t;
+typedef struct pcap_addr pcap_addr_t;
typedef struct pcap_dumper pcap_dumper_t;
/*
@@ -98,14 +100,39 @@ struct pcap_stat {
u_int ps_ifdrop; /* drops by interface XXX not yet supported */
};
+/*
+ * Item in a list of interfaces.
+ */
+struct pcap_if {
+ struct pcap_if *next;
+ char *name; /* name to hand to "pcap_open_live()" */
+ char *description; /* textual description of interface, or NULL */
+ struct pcap_addr *addresses;
+ bpf_u_int32 flags; /* PCAP_IF_ interface flags */
+};
+
+#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */
+
+/*
+ * Representation of an interface address.
+ */
+struct pcap_addr {
+ struct pcap_addr *next;
+ struct sockaddr *addr; /* address */
+ struct sockaddr *netmask; /* netmask for that address */
+ struct sockaddr *broadaddr; /* broadcast address for that address */
+ struct sockaddr *dstaddr; /* P2P destination address for that address */
+};
+
typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
const u_char *);
__BEGIN_DECLS
char *pcap_lookupdev(char *);
int pcap_lookupnet(char *, bpf_u_int32 *, bpf_u_int32 *, char *);
-pcap_t *pcap_open_live(char *, int, int, int, char *);
+pcap_t *pcap_open_live(const char *, int, int, int, char *);
pcap_t *pcap_open_offline(const char *, char *);
+pcap_t *pcap_open_dead(int, int);
void pcap_close(pcap_t *);
int pcap_loop(pcap_t *, int, pcap_handler, u_char *);
int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
@@ -114,6 +141,8 @@ const u_char*
int pcap_stats(pcap_t *, struct pcap_stat *);
int pcap_inject(pcap_t *, const void *, size_t);
int pcap_setfilter(pcap_t *, struct bpf_program *);
+int pcap_getnonblock(pcap_t *, char *);
+int pcap_setnonblock(pcap_t *, int, char *);
void pcap_perror(pcap_t *, char *);
char *pcap_strerror(int);
char *pcap_geterr(pcap_t *);
@@ -122,7 +151,14 @@ int pcap_compile(pcap_t *, struct bpf_program *, char *, int,
int pcap_compile_nopcap(int, int, struct bpf_program *,
char *, int, bpf_u_int32);
void pcap_freecode(struct bpf_program *);
+void pcap_breakloop(pcap_t *);
int pcap_datalink(pcap_t *);
+int pcap_list_datalinks(pcap_t *, int **);
+int pcap_set_datalink(pcap_t *, int);
+int pcap_datalink_name_to_val(const char *);
+const char *pcap_datalink_val_to_name(int);
+const char *pcap_datalink_val_to_description(int);
+const char *pcap_lib_version(void);
int pcap_snapshot(pcap_t *);
int pcap_is_swapped(pcap_t *);
int pcap_major_version(pcap_t *);
@@ -136,6 +172,9 @@ pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
void pcap_dump_close(pcap_dumper_t *);
void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
+int pcap_findalldevs(pcap_if_t **, char *);
+void pcap_freealldevs(pcap_if_t *);
+
/* XXX this guy lives in the bpf tree */
u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
char *bpf_image(struct bpf_insn *, int);
diff --git a/lib/libpcap/shlib_version b/lib/libpcap/shlib_version
index 3f0196ebf4a..d9961ea9fef 100644
--- a/lib/libpcap/shlib_version
+++ b/lib/libpcap/shlib_version
@@ -1,2 +1,2 @@
-major=3
-minor=1
+major=4
+minor=0