diff options
author | delphij <delphij@FreeBSD.org> | 2013-05-30 08:02:00 +0000 |
---|---|---|
committer | delphij <delphij@FreeBSD.org> | 2013-05-30 08:02:00 +0000 |
commit | 8be1d9016e057c1f30a906165802d48b52b73938 (patch) | |
tree | 5ab08c0c24a5cec0f64a701f8ba689a47b1d5fec /contrib/libpcap/pcap.c | |
parent | 351801626880685262a58abdd5f5db9dca6da379 (diff) | |
download | FreeBSD-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.c | 234 |
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)); |