diff options
author | 2005-11-18 11:05:38 +0000 | |
---|---|---|
committer | 2005-11-18 11:05:38 +0000 | |
commit | a878b8190bd951d272b5ce5df54b7a46fd7a9b0d (patch) | |
tree | 1a081693f9083731b7ed15ed3eeb9429e2dd5f01 /lib/libpcap/pcap.c | |
parent | remove stray .Ed; (diff) | |
download | wireguard-openbsd-a878b8190bd951d272b5ce5df54b7a46fd7a9b0d.tar.xz wireguard-openbsd-a878b8190bd951d272b5ce5df54b7a46fd7a9b0d.zip |
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/libpcap/pcap.c')
-rw-r--r-- | lib/libpcap/pcap.c | 182 |
1 files changed, 181 insertions, 1 deletions
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); +} + |