summaryrefslogtreecommitdiffstats
path: root/contrib/libpcap/pcap.c
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2013-05-30 08:02:00 +0000
committerdelphij <delphij@FreeBSD.org>2013-05-30 08:02:00 +0000
commit8be1d9016e057c1f30a906165802d48b52b73938 (patch)
tree5ab08c0c24a5cec0f64a701f8ba689a47b1d5fec /contrib/libpcap/pcap.c
parent351801626880685262a58abdd5f5db9dca6da379 (diff)
downloadFreeBSD-src-8be1d9016e057c1f30a906165802d48b52b73938.zip
FreeBSD-src-8be1d9016e057c1f30a906165802d48b52b73938.tar.gz
MFV: libpcap 1.4.0.
MFC after: 4 weeks
Diffstat (limited to 'contrib/libpcap/pcap.c')
-rw-r--r--contrib/libpcap/pcap.c234
1 files changed, 225 insertions, 9 deletions
diff --git a/contrib/libpcap/pcap.c b/contrib/libpcap/pcap.c
index afbcb73..be884b8 100644
--- a/contrib/libpcap/pcap.c
+++ b/contrib/libpcap/pcap.c
@@ -75,8 +75,35 @@ static const char rcsid[] _U_ =
#include "pcap-int.h"
#ifdef HAVE_DAG_API
-#include <dagnew.h>
-#include <dagapi.h>
+#include "pcap-dag.h"
+#endif /* HAVE_DAG_API */
+
+#ifdef HAVE_SEPTEL_API
+#include "pcap-septel.h"
+#endif /* HAVE_SEPTEL_API */
+
+#ifdef HAVE_SNF_API
+#include "pcap-snf.h"
+#endif /* HAVE_SNF_API */
+
+#ifdef PCAP_SUPPORT_USB
+#include "pcap-usb-linux.h"
+#endif
+
+#ifdef PCAP_SUPPORT_BT
+#include "pcap-bt-linux.h"
+#endif
+
+#ifdef PCAP_SUPPORT_CAN
+#include "pcap-can-linux.h"
+#endif
+
+#ifdef PCAP_SUPPORT_CANUSB
+#include "pcap-canusb-linux.h"
+#endif
+
+#ifdef PCAP_SUPPORT_NETFILTER
+#include "pcap-netfilter-linux.h"
#endif
int
@@ -233,6 +260,173 @@ pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s));
}
+#if defined(DAG_ONLY)
+int
+pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
+{
+ return (dag_findalldevs(alldevsp, errbuf));
+}
+
+pcap_t *
+pcap_create(const char *source, char *errbuf)
+{
+ return (dag_create(source, errbuf));
+}
+#elif defined(SEPTEL_ONLY)
+int
+pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
+{
+ return (septel_findalldevs(alldevsp, errbuf));
+}
+
+pcap_t *
+pcap_create(const char *source, char *errbuf)
+{
+ return (septel_create(source, errbuf));
+}
+#elif defined(SNF_ONLY)
+int
+pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
+{
+ return (snf_findalldevs(alldevsp, errbuf));
+}
+
+pcap_t *
+pcap_create(const char *source, char *errbuf)
+{
+ return (snf_create(source, errbuf));
+}
+#else /* regular pcap */
+struct capture_source_type {
+ int (*findalldevs_op)(pcap_if_t **, char *);
+ pcap_t *(*create_op)(const char *, char *, int *);
+} capture_source_types[] = {
+#ifdef HAVE_DAG_API
+ { dag_findalldevs, dag_create },
+#endif
+#ifdef HAVE_SEPTEL_API
+ { septel_findalldevs, septel_create },
+#endif
+#ifdef HAVE_SNF_API
+ { snf_findalldevs, snf_create },
+#endif
+#ifdef PCAP_SUPPORT_BT
+ { bt_findalldevs, bt_create },
+#endif
+#if PCAP_SUPPORT_CANUSB
+ { canusb_findalldevs, canusb_create },
+#endif
+#ifdef PCAP_SUPPORT_CAN
+ { can_findalldevs, can_create },
+#endif
+#ifdef PCAP_SUPPORT_USB
+ { usb_findalldevs, usb_create },
+#endif
+#ifdef PCAP_SUPPORT_NETFILTER
+ { netfilter_findalldevs, netfilter_create },
+#endif
+ { NULL, NULL }
+};
+
+/*
+ * Get a list of all capture sources 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.
+ */
+int
+pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
+{
+ size_t i;
+
+ /*
+ * Get the list of regular interfaces first.
+ */
+ if (pcap_findalldevs_interfaces(alldevsp, errbuf) == -1)
+ return (-1); /* failure */
+
+ /*
+ * Add any interfaces that need a platform-specific mechanism
+ * to find.
+ */
+ if (pcap_platform_finddevs(alldevsp, errbuf) == -1) {
+ /*
+ * We had an error; free the list we've been
+ * constructing.
+ */
+ if (*alldevsp != NULL) {
+ pcap_freealldevs(*alldevsp);
+ *alldevsp = NULL;
+ }
+ return (-1);
+ }
+
+ /*
+ * Ask each of the non-local-network-interface capture
+ * source types what interfaces they have.
+ */
+ for (i = 0; capture_source_types[i].findalldevs_op != NULL; i++) {
+ if (capture_source_types[i].findalldevs_op(alldevsp, errbuf) == -1) {
+ /*
+ * We had an error; free the list we've been
+ * constructing.
+ */
+ if (*alldevsp != NULL) {
+ pcap_freealldevs(*alldevsp);
+ *alldevsp = NULL;
+ }
+ return (-1);
+ }
+ }
+ return (0);
+}
+
+pcap_t *
+pcap_create(const char *source, char *errbuf)
+{
+ size_t i;
+ int is_theirs;
+ pcap_t *p;
+
+ /*
+ * A null source name is equivalent to the "any" device -
+ * which might not be supported on this platform, but
+ * this means that you'll get a "not supported" error
+ * rather than, say, a crash when we try to dereference
+ * the null pointer.
+ */
+ if (source == NULL)
+ source = "any";
+
+ /*
+ * Try each of the non-local-network-interface capture
+ * source types until we find one that works for this
+ * device or run out of types.
+ */
+ for (i = 0; capture_source_types[i].create_op != NULL; i++) {
+ is_theirs = 0;
+ p = capture_source_types[i].create_op(source, errbuf, &is_theirs);
+ if (is_theirs) {
+ /*
+ * The device name refers to a device of the
+ * type in question; either it succeeded,
+ * in which case p refers to a pcap_t to
+ * later activate for the device, or it
+ * failed, in which case p is null and we
+ * should return that to report the failure
+ * to create.
+ */
+ return (p);
+ }
+ }
+
+ /*
+ * OK, try it as a regular network interface.
+ */
+ return (pcap_create_interface(source, errbuf));
+}
+#endif
+
static void
initialize_ops(pcap_t *p)
{
@@ -1024,7 +1218,18 @@ pcap_geterr(pcap_t *p)
int
pcap_getnonblock(pcap_t *p, char *errbuf)
{
- return (p->getnonblock_op(p, errbuf));
+ int ret;
+
+ ret = p->getnonblock_op(p, errbuf);
+ if (ret == -1) {
+ /*
+ * In case somebody depended on the bug wherein
+ * the error message was put into p->errbuf
+ * by pcap_getnonblock_fd().
+ */
+ strlcpy(p->errbuf, errbuf, PCAP_ERRBUF_SIZE);
+ }
+ return (ret);
}
/*
@@ -1042,7 +1247,7 @@ pcap_getnonblock_fd(pcap_t *p, char *errbuf)
fdflags = fcntl(p->fd, F_GETFL, 0);
if (fdflags == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
pcap_strerror(errno));
return (-1);
}
@@ -1056,7 +1261,18 @@ pcap_getnonblock_fd(pcap_t *p, char *errbuf)
int
pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
{
- return (p->setnonblock_op(p, nonblock, errbuf));
+ int ret;
+
+ ret = p->setnonblock_op(p, nonblock, errbuf);
+ if (ret == -1) {
+ /*
+ * In case somebody depended on the bug wherein
+ * the error message was put into p->errbuf
+ * by pcap_setnonblock_fd().
+ */
+ strlcpy(p->errbuf, errbuf, PCAP_ERRBUF_SIZE);
+ }
+ return (ret);
}
#if !defined(WIN32) && !defined(MSDOS)
@@ -1073,7 +1289,7 @@ pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf)
fdflags = fcntl(p->fd, F_GETFL, 0);
if (fdflags == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
pcap_strerror(errno));
return (-1);
}
@@ -1082,7 +1298,7 @@ pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf)
else
fdflags &= ~O_NONBLOCK;
if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
- snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
pcap_strerror(errno));
return (-1);
}
@@ -1465,10 +1681,10 @@ pcap_close(pcap_t *p)
* the packet doesn't pass and non-zero if the packet does pass.
*/
int
-pcap_offline_filter(struct bpf_program *fp, const struct pcap_pkthdr *h,
+pcap_offline_filter(const struct bpf_program *fp, const struct pcap_pkthdr *h,
const u_char *pkt)
{
- struct bpf_insn *fcode = fp->bf_insns;
+ const struct bpf_insn *fcode = fp->bf_insns;
if (fcode != NULL)
return (bpf_filter(fcode, pkt, h->len, h->caplen));
OpenPOWER on IntegriCloud