diff options
Diffstat (limited to 'freebsd/contrib/libpcap/pcap.c')
-rw-r--r-- | freebsd/contrib/libpcap/pcap.c | 1185 |
1 files changed, 855 insertions, 330 deletions
diff --git a/freebsd/contrib/libpcap/pcap.c b/freebsd/contrib/libpcap/pcap.c index e2991fb3..c7e7d02e 100644 --- a/freebsd/contrib/libpcap/pcap.c +++ b/freebsd/contrib/libpcap/pcap.c @@ -33,20 +33,13 @@ * SUCH DAMAGE. */ -#if 0 -#ifndef lint -static const char rcsid[] _U_ = - "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.128 2008-12-23 20:13:29 guy Exp $ (LBL)"; -#endif -#endif - #ifdef HAVE_CONFIG_H #include "config.h" #endif -#ifdef WIN32 +#ifdef _WIN32 #include <pcap-stdinc.h> -#else /* WIN32 */ +#else /* _WIN32 */ #if HAVE_INTTYPES_H #include <inttypes.h> #elif HAVE_STDINT_H @@ -57,7 +50,7 @@ static const char rcsid[] _U_ = #endif #include <sys/types.h> #include <sys/mman.h> -#endif /* WIN32 */ +#endif /* _WIN32 */ #include <stdio.h> #include <stdlib.h> @@ -90,6 +83,10 @@ static const char rcsid[] _U_ = #include "pcap-snf.h" #endif /* HAVE_SNF_API */ +#ifdef HAVE_TC_API +#include "pcap-tc.h" +#endif /* HAVE_TC_API */ + #ifdef PCAP_SUPPORT_USB #include "pcap-usb-linux.h" #endif @@ -98,25 +95,66 @@ static const char rcsid[] _U_ = #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" +#ifdef PCAP_SUPPORT_BT_MONITOR +#include "pcap-bt-monitor-linux.h" #endif #ifdef PCAP_SUPPORT_NETFILTER #include "pcap-netfilter-linux.h" #endif -int +#ifdef PCAP_SUPPORT_NETMAP +pcap_t* pcap_netmap_create(const char *device, char *ebuf, int *is_ours); +#endif + +#ifdef PCAP_SUPPORT_DBUS +#include "pcap-dbus.h" +#endif + +static int pcap_not_initialized(pcap_t *pcap) { + /* in case the caller doesn't check for PCAP_ERROR_NOT_ACTIVATED */ + (void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf), + "This handle hasn't been activated yet"); /* this means 'not initialized' */ return (PCAP_ERROR_NOT_ACTIVATED); } +#ifdef _WIN32 +static void * +pcap_not_initialized_ptr(pcap_t *pcap) +{ + (void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf), + "This handle hasn't been activated yet"); + return (NULL); +} + +static HANDLE +pcap_getevent_not_initialized(pcap_t *pcap) +{ + (void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf), + "This handle hasn't been activated yet"); + return (INVALID_HANDLE_VALUE); +} + +static u_int +pcap_sendqueue_transmit_not_initialized(pcap_t *pcap, pcap_send_queue* queue, int sync) +{ + (void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf), + "This handle hasn't been activated yet"); + return (0); +} + +static PAirpcapHandle +pcap_get_airpcap_handle_not_initialized(pcap_t *pcap) +{ + (void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf), + "This handle hasn't been activated yet"); + return (NULL); +} +#endif + /* * Returns 1 if rfmon mode can be set on the pcap_t, 0 if it can't, * a PCAP_ERROR value on an error. @@ -159,7 +197,7 @@ pcap_list_tstamp_types(pcap_t *p, int **tstamp_typesp) *tstamp_typesp = (int*)calloc(sizeof(**tstamp_typesp), p->tstamp_type_count); if (*tstamp_typesp == NULL) { - (void)snprintf(p->errbuf, sizeof(p->errbuf), + (void)pcap_snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); return (PCAP_ERROR); } @@ -191,7 +229,7 @@ pcap_free_tstamp_types(int *tstamp_type_list) * packet data cannot be guaranteed to be available after the callback * returns, so that a copy must be made. */ -static void +void pcap_oneshot(u_char *user, const struct pcap_pkthdr *h, const u_char *pkt) { struct oneshot_userdata *sp = (struct oneshot_userdata *)user; @@ -227,7 +265,7 @@ pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, /* Saves a pointer to the packet headers */ *pkt_header= &p->pcap_header; - if (p->sf.rfile != NULL) { + if (p->rfile != NULL) { int status; /* We are on an offline capture */ @@ -264,47 +302,13 @@ 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 { +static struct capture_source_type { int (*findalldevs_op)(pcap_if_t **, char *); pcap_t *(*create_op)(const char *, char *, int *); } capture_source_types[] = { +#ifdef PCAP_SUPPORT_NETMAP + { NULL, pcap_netmap_create }, +#endif #ifdef HAVE_DAG_API { dag_findalldevs, dag_create }, #endif @@ -314,14 +318,14 @@ struct capture_source_type { #ifdef HAVE_SNF_API { snf_findalldevs, snf_create }, #endif +#ifdef HAVE_TC_API + { TcFindAllDevs, TcCreate }, +#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 }, +#ifdef PCAP_SUPPORT_BT_MONITOR + { bt_monitor_findalldevs, bt_monitor_create }, #endif #ifdef PCAP_SUPPORT_USB { usb_findalldevs, usb_create }, @@ -329,6 +333,9 @@ struct capture_source_type { #ifdef PCAP_SUPPORT_NETFILTER { netfilter_findalldevs, netfilter_create }, #endif +#ifdef PCAP_SUPPORT_DBUS + { dbus_findalldevs, dbus_create }, +#endif { NULL, NULL } }; @@ -344,26 +351,11 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) size_t i; /* - * Get the list of regular interfaces first. + * Find all the local network interfaces on which we + * can capture. */ - 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; - } + if (pcap_platform_finddevs(alldevsp, errbuf) == -1) return (-1); - } /* * Ask each of the non-local-network-interface capture @@ -382,25 +374,58 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) return (-1); } } + return (0); } pcap_t * -pcap_create(const char *source, char *errbuf) +pcap_create(const char *device, char *errbuf) { size_t i; int is_theirs; pcap_t *p; + char *device_str; /* - * A null source name is equivalent to the "any" device - + * A null device 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"; + if (device == NULL) + device_str = strdup("any"); + else { +#ifdef _WIN32 + /* + * If the string appears to be little-endian UCS-2/UTF-16, + * convert it to ASCII. + * + * XXX - to UTF-8 instead? Or report an error if any + * character isn't ASCII? + */ + if (device[0] != '\0' && device[1] == '\0') { + size_t length; + + length = wcslen((wchar_t *)device); + device_str = (char *)malloc(length + 1); + if (device_str == NULL) { + pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + return (NULL); + } + + pcap_snprintf(device_str, length + 1, "%ws", + (const wchar_t *)device); + } else +#endif + device_str = strdup(device); + } + if (device_str == NULL) { + pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + return (NULL); + } /* * Try each of the non-local-network-interface capture @@ -409,7 +434,8 @@ pcap_create(const char *source, char *errbuf) */ 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); + p = capture_source_types[i].create_op(device_str, errbuf, + &is_theirs); if (is_theirs) { /* * The device name refers to a device of the @@ -420,6 +446,14 @@ pcap_create(const char *source, char *errbuf) * should return that to report the failure * to create. */ + if (p == NULL) { + /* + * We assume the caller filled in errbuf. + */ + free(device_str); + return (NULL); + } + p->opt.device = device_str; return (p); } } @@ -427,9 +461,17 @@ pcap_create(const char *source, char *errbuf) /* * OK, try it as a regular network interface. */ - return (pcap_create_interface(source, errbuf)); + p = pcap_create_interface(device_str, errbuf); + if (p == NULL) { + /* + * We assume the caller filled in errbuf. + */ + free(device_str); + return (NULL); + } + p->opt.device = device_str; + return (p); } -#endif static void initialize_ops(pcap_t *p) @@ -447,10 +489,19 @@ initialize_ops(pcap_t *p) p->getnonblock_op = (getnonblock_op_t)pcap_not_initialized; p->setnonblock_op = (setnonblock_op_t)pcap_not_initialized; p->stats_op = (stats_op_t)pcap_not_initialized; -#ifdef WIN32 +#ifdef _WIN32 + p->stats_ex_op = (stats_ex_op_t)pcap_not_initialized_ptr; p->setbuff_op = (setbuff_op_t)pcap_not_initialized; p->setmode_op = (setmode_op_t)pcap_not_initialized; p->setmintocopy_op = (setmintocopy_op_t)pcap_not_initialized; + p->getevent_op = pcap_getevent_not_initialized; + p->oid_get_request_op = (oid_get_request_op_t)pcap_not_initialized; + p->oid_set_request_op = (oid_set_request_op_t)pcap_not_initialized; + p->sendqueue_transmit_op = pcap_sendqueue_transmit_not_initialized; + p->setuserbuffer_op = (setuserbuffer_op_t)pcap_not_initialized; + p->live_dump_op = (live_dump_op_t)pcap_not_initialized; + p->live_dump_ended_op = (live_dump_ended_op_t)pcap_not_initialized; + p->get_airpcap_handle_op = pcap_get_airpcap_handle_not_initialized; #endif /* @@ -461,38 +512,65 @@ initialize_ops(pcap_t *p) p->cleanup_op = pcap_cleanup_live_common; /* - * In most cases, the standard one-short callback can + * In most cases, the standard one-shot callback can * be used for pcap_next()/pcap_next_ex(). */ p->oneshot_callback = pcap_oneshot; } -pcap_t * -pcap_create_common(const char *source, char *ebuf) +static pcap_t * +pcap_alloc_pcap_t(char *ebuf, size_t size) { + char *chunk; pcap_t *p; - p = malloc(sizeof(*p)); - if (p == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", + /* + * Allocate a chunk of memory big enough for a pcap_t + * plus a structure following it of size "size". The + * structure following it is a private data structure + * for the routines that handle this pcap_t. + */ + chunk = malloc(sizeof (pcap_t) + size); + if (chunk == NULL) { + pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); return (NULL); } - memset(p, 0, sizeof(*p)); -#ifndef WIN32 + memset(chunk, 0, sizeof (pcap_t) + size); + + /* + * Get a pointer to the pcap_t at the beginning. + */ + p = (pcap_t *)chunk; + +#ifndef _WIN32 p->fd = -1; /* not opened yet */ p->selectable_fd = -1; - p->send_fd = -1; #endif - p->opt.source = strdup(source); - if (p->opt.source == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", - pcap_strerror(errno)); - free(p); - return (NULL); + if (size == 0) { + /* No private data was requested. */ + p->priv = NULL; + } else { + /* + * Set the pointer to the private data; that's the structure + * of size "size" following the pcap_t. + */ + p->priv = (void *)(chunk + sizeof (pcap_t)); } + return (p); +} + +pcap_t * +pcap_create_common(char *ebuf, size_t size) +{ + pcap_t *p; + + p = pcap_alloc_pcap_t(ebuf, size); + if (p == NULL) + return (NULL); + /* * Default to "can't set rfmon mode"; if it's supported by * a platform, the create routine that called us can set @@ -504,11 +582,20 @@ pcap_create_common(const char *source, char *ebuf) initialize_ops(p); /* put in some defaults*/ - pcap_set_timeout(p, 0); - pcap_set_snaplen(p, 65535); /* max packet size */ + p->snapshot = MAXIMUM_SNAPLEN; /* max packet size */ + p->opt.timeout = 0; /* no timeout specified */ + p->opt.buffer_size = 0; /* use the platform's default */ p->opt.promisc = 0; - p->opt.buffer_size = 0; + p->opt.rfmon = 0; + p->opt.immediate = 0; p->opt.tstamp_type = -1; /* default to not setting time stamp type */ + p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO; + + /* + * Start out with no BPF code generation flags set. + */ + p->bpf_codegen_flags = 0; + return (p); } @@ -516,7 +603,7 @@ int pcap_check_activated(pcap_t *p) { if (p->activated) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform " + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform " " operation on activated capture"); return (-1); } @@ -528,6 +615,16 @@ pcap_set_snaplen(pcap_t *p, int snaplen) { if (pcap_check_activated(p)) return (PCAP_ERROR_ACTIVATED); + + /* + * Turn invalid values, or excessively large values, into + * the maximum allowed value. + * + * If some application really *needs* a bigger snapshot + * length, we should just increase MAXIMUM_SNAPLEN. + */ + if (snaplen <= 0 || snaplen > MAXIMUM_SNAPLEN) + snaplen = MAXIMUM_SNAPLEN; p->snapshot = snaplen; return (0); } @@ -555,7 +652,7 @@ pcap_set_timeout(pcap_t *p, int timeout_ms) { if (pcap_check_activated(p)) return (PCAP_ERROR_ACTIVATED); - p->md.timeout = timeout_ms; + p->opt.timeout = timeout_ms; return (0); } @@ -568,42 +665,122 @@ pcap_set_tstamp_type(pcap_t *p, int tstamp_type) return (PCAP_ERROR_ACTIVATED); /* - * If p->tstamp_type_count is 0, we don't support setting - * the time stamp type at all. + * The argument should have been u_int, but that's too late + * to change now - it's an API. */ - if (p->tstamp_type_count == 0) - return (PCAP_ERROR_CANTSET_TSTAMP_TYPE); + if (tstamp_type < 0) + return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP); /* - * Check whether we claim to support this type of time stamp. + * If p->tstamp_type_count is 0, we only support PCAP_TSTAMP_HOST; + * the default time stamp type is PCAP_TSTAMP_HOST. */ - for (i = 0; i < p->tstamp_type_count; i++) { - if (p->tstamp_type_list[i] == tstamp_type) { - /* - * Yes. - */ + if (p->tstamp_type_count == 0) { + if (tstamp_type == PCAP_TSTAMP_HOST) { p->opt.tstamp_type = tstamp_type; return (0); } + } else { + /* + * Check whether we claim to support this type of time stamp. + */ + for (i = 0; i < p->tstamp_type_count; i++) { + if (p->tstamp_type_list[i] == (u_int)tstamp_type) { + /* + * Yes. + */ + p->opt.tstamp_type = tstamp_type; + return (0); + } + } } /* - * No. We support setting the time stamp type, but not to this - * particular value. + * We don't support this type of time stamp. */ return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP); } int +pcap_set_immediate_mode(pcap_t *p, int immediate) +{ + if (pcap_check_activated(p)) + return (PCAP_ERROR_ACTIVATED); + p->opt.immediate = immediate; + return (0); +} + +int pcap_set_buffer_size(pcap_t *p, int buffer_size) { if (pcap_check_activated(p)) return (PCAP_ERROR_ACTIVATED); + if (buffer_size <= 0) { + /* + * Silently ignore invalid values. + */ + return (0); + } p->opt.buffer_size = buffer_size; return (0); } int +pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision) +{ + int i; + + if (pcap_check_activated(p)) + return (PCAP_ERROR_ACTIVATED); + + /* + * The argument should have been u_int, but that's too late + * to change now - it's an API. + */ + if (tstamp_precision < 0) + return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP); + + /* + * If p->tstamp_precision_count is 0, we only support setting + * the time stamp precision to microsecond precision; every + * pcap module *MUST* support microsecond precision, even if + * it does so by converting the native precision to + * microseconds. + */ + if (p->tstamp_precision_count == 0) { + if (tstamp_precision == PCAP_TSTAMP_PRECISION_MICRO) { + p->opt.tstamp_precision = tstamp_precision; + return (0); + } + } else { + /* + * Check whether we claim to support this precision of + * time stamp. + */ + for (i = 0; i < p->tstamp_precision_count; i++) { + if (p->tstamp_precision_list[i] == (u_int)tstamp_precision) { + /* + * Yes. + */ + p->opt.tstamp_precision = tstamp_precision; + return (0); + } + } + } + + /* + * We don't support this time stamp precision. + */ + return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP); +} + +int +pcap_get_tstamp_precision(pcap_t *p) +{ + return (p->opt.tstamp_precision); +} + +int pcap_activate(pcap_t *p) { int status; @@ -628,7 +805,7 @@ pcap_activate(pcap_t *p) * handle errors other than PCAP_ERROR, return the * error message corresponding to the status. */ - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s", + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s", pcap_statustostr(status)); } @@ -642,12 +819,12 @@ pcap_activate(pcap_t *p) } pcap_t * -pcap_open_live(const char *source, int snaplen, int promisc, int to_ms, char *errbuf) +pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf) { pcap_t *p; int status; - p = pcap_create(source, errbuf); + p = pcap_create(device, errbuf); if (p == NULL) return (NULL); status = pcap_set_snaplen(p, snaplen); @@ -676,33 +853,37 @@ pcap_open_live(const char *source, int snaplen, int promisc, int to_ms, char *er return (p); fail: if (status == PCAP_ERROR) - snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, + pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", device, 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_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", device, pcap_statustostr(status), p->errbuf); else - snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source, + pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", device, pcap_statustostr(status)); pcap_close(p); return (NULL); } -int -pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +pcap_t * +pcap_open_offline_common(char *ebuf, size_t size) { - return (p->read_op(p, cnt, callback, user)); + pcap_t *p; + + p = pcap_alloc_pcap_t(ebuf, size); + if (p == NULL) + return (NULL); + + p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO; + + return (p); } -/* - * XXX - is this necessary? - */ int -pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { - return (p->read_op(p, cnt, callback, user)); } @@ -712,7 +893,7 @@ pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) register int n; for (;;) { - if (p->sf.rfile != NULL) { + if (p->rfile != NULL) { /* * 0 means EOF, so don't loop if we get 0. */ @@ -728,7 +909,7 @@ pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) } if (n <= 0) return (n); - if (cnt > 0) { + if (!PACKET_COUNT_IS_UNLIMITED(cnt)) { cnt -= n; if (cnt <= 0) return (0); @@ -748,18 +929,24 @@ pcap_breakloop(pcap_t *p) int pcap_datalink(pcap_t *p) { + if (!p->activated) + return (PCAP_ERROR_NOT_ACTIVATED); return (p->linktype); } int pcap_datalink_ext(pcap_t *p) { + if (!p->activated) + return (PCAP_ERROR_NOT_ACTIVATED); return (p->linktype_ext); } int pcap_list_datalinks(pcap_t *p, int **dlt_buffer) { + if (!p->activated) + return (PCAP_ERROR_NOT_ACTIVATED); if (p->dlt_count == 0) { /* * We couldn't fetch the list of DLTs, which means @@ -769,18 +956,18 @@ pcap_list_datalinks(pcap_t *p, int **dlt_buffer) */ *dlt_buffer = (int*)malloc(sizeof(**dlt_buffer)); if (*dlt_buffer == NULL) { - (void)snprintf(p->errbuf, sizeof(p->errbuf), + (void)pcap_snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); - return (-1); + return (PCAP_ERROR); } **dlt_buffer = p->linktype; return (1); } else { *dlt_buffer = (int*)calloc(sizeof(**dlt_buffer), p->dlt_count); if (*dlt_buffer == NULL) { - (void)snprintf(p->errbuf, sizeof(p->errbuf), + (void)pcap_snprintf(p->errbuf, sizeof(p->errbuf), "malloc: %s", pcap_strerror(errno)); - return (-1); + return (PCAP_ERROR); } (void)memcpy(*dlt_buffer, p->dlt_list, sizeof(**dlt_buffer) * p->dlt_count); @@ -811,6 +998,9 @@ pcap_set_datalink(pcap_t *p, int dlt) int i; const char *dlt_name; + if (dlt < 0) + goto unsupported; + if (p->dlt_count == 0 || p->set_datalink_op == NULL) { /* * We couldn't fetch the list of DLTs, or we don't @@ -828,7 +1018,7 @@ pcap_set_datalink(pcap_t *p, int dlt) return (0); } for (i = 0; i < p->dlt_count; i++) - if (p->dlt_list[i] == dlt) + if (p->dlt_list[i] == (u_int)dlt) break; if (i >= p->dlt_count) goto unsupported; @@ -856,11 +1046,11 @@ pcap_set_datalink(pcap_t *p, int dlt) unsupported: dlt_name = pcap_datalink_val_to_name(dlt); if (dlt_name != NULL) { - (void) snprintf(p->errbuf, sizeof(p->errbuf), + (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf), "%s is not one of the DLTs supported by this device", dlt_name); } else { - (void) snprintf(p->errbuf, sizeof(p->errbuf), + (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf), "DLT %d is not one of the DLTs supported by this device", dlt); } @@ -958,113 +1148,139 @@ struct dlt_choice { int dlt; }; -#define DLT_CHOICE(code, description) { #code, description, code } +#define DLT_CHOICE(code, description) { #code, description, DLT_ ## code } #define DLT_CHOICE_SENTINEL { NULL, NULL, 0 } static struct dlt_choice dlt_choices[] = { - DLT_CHOICE(DLT_NULL, "BSD loopback"), - DLT_CHOICE(DLT_EN10MB, "Ethernet"), - DLT_CHOICE(DLT_IEEE802, "Token ring"), - DLT_CHOICE(DLT_ARCNET, "BSD ARCNET"), - DLT_CHOICE(DLT_SLIP, "SLIP"), - DLT_CHOICE(DLT_PPP, "PPP"), - DLT_CHOICE(DLT_FDDI, "FDDI"), - DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"), - DLT_CHOICE(DLT_RAW, "Raw IP"), - DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS SLIP"), - DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS PPP"), - DLT_CHOICE(DLT_ATM_CLIP, "Linux Classical IP-over-ATM"), - DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"), - DLT_CHOICE(DLT_PPP_ETHER, "PPPoE"), - DLT_CHOICE(DLT_SYMANTEC_FIREWALL, "Symantec Firewall"), - DLT_CHOICE(DLT_C_HDLC, "Cisco HDLC"), - DLT_CHOICE(DLT_IEEE802_11, "802.11"), - DLT_CHOICE(DLT_FRELAY, "Frame Relay"), - DLT_CHOICE(DLT_LOOP, "OpenBSD loopback"), - DLT_CHOICE(DLT_ENC, "OpenBSD encapsulated IP"), - DLT_CHOICE(DLT_LINUX_SLL, "Linux cooked"), - DLT_CHOICE(DLT_LTALK, "Localtalk"), - DLT_CHOICE(DLT_PFLOG, "OpenBSD pflog file"), - DLT_CHOICE(DLT_PFSYNC, "Packet filter state syncing"), - DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"), - DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"), - DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"), - DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus radiotap header"), - DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"), - DLT_CHOICE(DLT_JUNIPER_MLPPP, "Juniper Multi-Link PPP"), - DLT_CHOICE(DLT_JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"), - DLT_CHOICE(DLT_JUNIPER_ES, "Juniper Encryption Services PIC"), - DLT_CHOICE(DLT_JUNIPER_GGSN, "Juniper GGSN PIC"), - DLT_CHOICE(DLT_JUNIPER_MFR, "Juniper FRF.16 Frame Relay"), - DLT_CHOICE(DLT_JUNIPER_ATM2, "Juniper ATM2 PIC"), - DLT_CHOICE(DLT_JUNIPER_SERVICES, "Juniper Advanced Services PIC"), - DLT_CHOICE(DLT_JUNIPER_ATM1, "Juniper ATM1 PIC"), - DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"), - DLT_CHOICE(DLT_MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"), - DLT_CHOICE(DLT_MTP2, "SS7 MTP2"), - DLT_CHOICE(DLT_MTP3, "SS7 MTP3"), - DLT_CHOICE(DLT_SCCP, "SS7 SCCP"), - DLT_CHOICE(DLT_DOCSIS, "DOCSIS"), - DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"), - DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"), - DLT_CHOICE(DLT_JUNIPER_MONITOR, "Juniper Passive Monitor PIC"), - DLT_CHOICE(DLT_PPP_PPPD, "PPP for pppd, with direction flag"), - DLT_CHOICE(DLT_JUNIPER_PPPOE, "Juniper PPPoE"), - DLT_CHOICE(DLT_JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"), - DLT_CHOICE(DLT_GPRS_LLC, "GPRS LLC"), - DLT_CHOICE(DLT_GPF_T, "GPF-T"), - DLT_CHOICE(DLT_GPF_F, "GPF-F"), - DLT_CHOICE(DLT_JUNIPER_PIC_PEER, "Juniper PIC Peer"), - DLT_CHOICE(DLT_ERF_ETH, "Ethernet with Endace ERF header"), - DLT_CHOICE(DLT_ERF_POS, "Packet-over-SONET with Endace ERF header"), - DLT_CHOICE(DLT_LINUX_LAPD, "Linux vISDN LAPD"), - DLT_CHOICE(DLT_JUNIPER_ETHER, "Juniper Ethernet"), - DLT_CHOICE(DLT_JUNIPER_PPP, "Juniper PPP"), - DLT_CHOICE(DLT_JUNIPER_FRELAY, "Juniper Frame Relay"), - DLT_CHOICE(DLT_JUNIPER_CHDLC, "Juniper C-HDLC"), - DLT_CHOICE(DLT_MFR, "FRF.16 Frame Relay"), - DLT_CHOICE(DLT_JUNIPER_VP, "Juniper Voice PIC"), - DLT_CHOICE(DLT_A429, "Arinc 429"), - DLT_CHOICE(DLT_A653_ICM, "Arinc 653 Interpartition Communication"), - DLT_CHOICE(DLT_USB, "USB"), - DLT_CHOICE(DLT_BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"), - DLT_CHOICE(DLT_IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"), - DLT_CHOICE(DLT_USB_LINUX, "USB with Linux header"), - DLT_CHOICE(DLT_CAN20B, "Controller Area Network (CAN) v. 2.0B"), - DLT_CHOICE(DLT_IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"), - DLT_CHOICE(DLT_PPI, "Per-Packet Information"), - DLT_CHOICE(DLT_IEEE802_16_MAC_CPS_RADIO, "IEEE 802.16 MAC Common Part Sublayer plus radiotap header"), - DLT_CHOICE(DLT_JUNIPER_ISM, "Juniper Integrated Service Module"), - DLT_CHOICE(DLT_IEEE802_15_4, "IEEE 802.15.4 with FCS"), - DLT_CHOICE(DLT_SITA, "SITA pseudo-header"), - DLT_CHOICE(DLT_ERF, "Endace ERF header"), - DLT_CHOICE(DLT_RAIF1, "Ethernet with u10 Networks pseudo-header"), - DLT_CHOICE(DLT_IPMB, "IPMB"), - DLT_CHOICE(DLT_JUNIPER_ST, "Juniper Secure Tunnel"), - DLT_CHOICE(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"), - DLT_CHOICE(DLT_AX25_KISS, "AX.25 with KISS header"), - DLT_CHOICE(DLT_IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"), - DLT_CHOICE(DLT_MPLS, "MPLS with label as link-layer header"), - DLT_CHOICE(DLT_USB_LINUX_MMAPPED, "USB with padded Linux header"), - DLT_CHOICE(DLT_DECT, "DECT"), - DLT_CHOICE(DLT_AOS, "AOS Space Data Link protocol"), - DLT_CHOICE(DLT_WIHART, "Wireless HART"), - DLT_CHOICE(DLT_FC_2, "Fibre Channel FC-2"), - DLT_CHOICE(DLT_FC_2_WITH_FRAME_DELIMS, "Fibre Channel FC-2 with frame delimiters"), - DLT_CHOICE(DLT_IPNET, "Solaris ipnet"), - DLT_CHOICE(DLT_CAN_SOCKETCAN, "CAN-bus with SocketCAN headers"), - DLT_CHOICE(DLT_IPV4, "Raw IPv4"), - DLT_CHOICE(DLT_IPV6, "Raw IPv6"), - DLT_CHOICE(DLT_IEEE802_15_4_NOFCS, "IEEE 802.15.4 without FCS"), - DLT_CHOICE(DLT_JUNIPER_VS, "Juniper Virtual Server"), - DLT_CHOICE(DLT_JUNIPER_SRX_E2E, "Juniper SRX E2E"), - DLT_CHOICE(DLT_JUNIPER_FIBRECHANNEL, "Juniper Fibre Channel"), - DLT_CHOICE(DLT_DVB_CI, "DVB-CI"), - DLT_CHOICE(DLT_JUNIPER_ATM_CEMIC, "Juniper ATM CEMIC"), - DLT_CHOICE(DLT_NFLOG, "Linux netfilter log messages"), - DLT_CHOICE(DLT_NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"), - DLT_CHOICE(DLT_NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"), - DLT_CHOICE(DLT_IPOIB, "RFC 4391 IP-over-Infiniband"), + DLT_CHOICE(NULL, "BSD loopback"), + DLT_CHOICE(EN10MB, "Ethernet"), + DLT_CHOICE(IEEE802, "Token ring"), + DLT_CHOICE(ARCNET, "BSD ARCNET"), + DLT_CHOICE(SLIP, "SLIP"), + DLT_CHOICE(PPP, "PPP"), + DLT_CHOICE(FDDI, "FDDI"), + DLT_CHOICE(ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"), + DLT_CHOICE(RAW, "Raw IP"), + DLT_CHOICE(SLIP_BSDOS, "BSD/OS SLIP"), + DLT_CHOICE(PPP_BSDOS, "BSD/OS PPP"), + DLT_CHOICE(ATM_CLIP, "Linux Classical IP-over-ATM"), + DLT_CHOICE(PPP_SERIAL, "PPP over serial"), + DLT_CHOICE(PPP_ETHER, "PPPoE"), + DLT_CHOICE(SYMANTEC_FIREWALL, "Symantec Firewall"), + DLT_CHOICE(C_HDLC, "Cisco HDLC"), + DLT_CHOICE(IEEE802_11, "802.11"), + DLT_CHOICE(FRELAY, "Frame Relay"), + DLT_CHOICE(LOOP, "OpenBSD loopback"), + DLT_CHOICE(ENC, "OpenBSD encapsulated IP"), + DLT_CHOICE(LINUX_SLL, "Linux cooked"), + DLT_CHOICE(LTALK, "Localtalk"), + DLT_CHOICE(PFLOG, "OpenBSD pflog file"), + DLT_CHOICE(PFSYNC, "Packet filter state syncing"), + DLT_CHOICE(PRISM_HEADER, "802.11 plus Prism header"), + DLT_CHOICE(IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"), + DLT_CHOICE(SUNATM, "Sun raw ATM"), + DLT_CHOICE(IEEE802_11_RADIO, "802.11 plus radiotap header"), + DLT_CHOICE(ARCNET_LINUX, "Linux ARCNET"), + DLT_CHOICE(JUNIPER_MLPPP, "Juniper Multi-Link PPP"), + DLT_CHOICE(JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"), + DLT_CHOICE(JUNIPER_ES, "Juniper Encryption Services PIC"), + DLT_CHOICE(JUNIPER_GGSN, "Juniper GGSN PIC"), + DLT_CHOICE(JUNIPER_MFR, "Juniper FRF.16 Frame Relay"), + DLT_CHOICE(JUNIPER_ATM2, "Juniper ATM2 PIC"), + DLT_CHOICE(JUNIPER_SERVICES, "Juniper Advanced Services PIC"), + DLT_CHOICE(JUNIPER_ATM1, "Juniper ATM1 PIC"), + DLT_CHOICE(APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"), + DLT_CHOICE(MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"), + DLT_CHOICE(MTP2, "SS7 MTP2"), + DLT_CHOICE(MTP3, "SS7 MTP3"), + DLT_CHOICE(SCCP, "SS7 SCCP"), + DLT_CHOICE(DOCSIS, "DOCSIS"), + DLT_CHOICE(LINUX_IRDA, "Linux IrDA"), + DLT_CHOICE(IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"), + DLT_CHOICE(JUNIPER_MONITOR, "Juniper Passive Monitor PIC"), + DLT_CHOICE(BACNET_MS_TP, "BACnet MS/TP"), + DLT_CHOICE(PPP_PPPD, "PPP for pppd, with direction flag"), + DLT_CHOICE(JUNIPER_PPPOE, "Juniper PPPoE"), + DLT_CHOICE(JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"), + DLT_CHOICE(GPRS_LLC, "GPRS LLC"), + DLT_CHOICE(GPF_T, "GPF-T"), + DLT_CHOICE(GPF_F, "GPF-F"), + DLT_CHOICE(JUNIPER_PIC_PEER, "Juniper PIC Peer"), + DLT_CHOICE(ERF_ETH, "Ethernet with Endace ERF header"), + DLT_CHOICE(ERF_POS, "Packet-over-SONET with Endace ERF header"), + DLT_CHOICE(LINUX_LAPD, "Linux vISDN LAPD"), + DLT_CHOICE(JUNIPER_ETHER, "Juniper Ethernet"), + DLT_CHOICE(JUNIPER_PPP, "Juniper PPP"), + DLT_CHOICE(JUNIPER_FRELAY, "Juniper Frame Relay"), + DLT_CHOICE(JUNIPER_CHDLC, "Juniper C-HDLC"), + DLT_CHOICE(MFR, "FRF.16 Frame Relay"), + DLT_CHOICE(JUNIPER_VP, "Juniper Voice PIC"), + DLT_CHOICE(A429, "Arinc 429"), + DLT_CHOICE(A653_ICM, "Arinc 653 Interpartition Communication"), + DLT_CHOICE(USB_FREEBSD, "USB with FreeBSD header"), + DLT_CHOICE(BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"), + DLT_CHOICE(IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"), + DLT_CHOICE(USB_LINUX, "USB with Linux header"), + DLT_CHOICE(CAN20B, "Controller Area Network (CAN) v. 2.0B"), + DLT_CHOICE(IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"), + DLT_CHOICE(PPI, "Per-Packet Information"), + DLT_CHOICE(IEEE802_16_MAC_CPS_RADIO, "IEEE 802.16 MAC Common Part Sublayer plus radiotap header"), + DLT_CHOICE(JUNIPER_ISM, "Juniper Integrated Service Module"), + DLT_CHOICE(IEEE802_15_4, "IEEE 802.15.4 with FCS"), + DLT_CHOICE(SITA, "SITA pseudo-header"), + DLT_CHOICE(ERF, "Endace ERF header"), + DLT_CHOICE(RAIF1, "Ethernet with u10 Networks pseudo-header"), + DLT_CHOICE(IPMB, "IPMB"), + DLT_CHOICE(JUNIPER_ST, "Juniper Secure Tunnel"), + DLT_CHOICE(BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"), + DLT_CHOICE(AX25_KISS, "AX.25 with KISS header"), + DLT_CHOICE(IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"), + DLT_CHOICE(MPLS, "MPLS with label as link-layer header"), + DLT_CHOICE(LINUX_EVDEV, "Linux evdev events"), + DLT_CHOICE(USB_LINUX_MMAPPED, "USB with padded Linux header"), + DLT_CHOICE(DECT, "DECT"), + DLT_CHOICE(AOS, "AOS Space Data Link protocol"), + DLT_CHOICE(WIHART, "Wireless HART"), + DLT_CHOICE(FC_2, "Fibre Channel FC-2"), + DLT_CHOICE(FC_2_WITH_FRAME_DELIMS, "Fibre Channel FC-2 with frame delimiters"), + DLT_CHOICE(IPNET, "Solaris ipnet"), + DLT_CHOICE(CAN_SOCKETCAN, "CAN-bus with SocketCAN headers"), + DLT_CHOICE(IPV4, "Raw IPv4"), + DLT_CHOICE(IPV6, "Raw IPv6"), + DLT_CHOICE(IEEE802_15_4_NOFCS, "IEEE 802.15.4 without FCS"), + DLT_CHOICE(DBUS, "D-Bus"), + DLT_CHOICE(JUNIPER_VS, "Juniper Virtual Server"), + DLT_CHOICE(JUNIPER_SRX_E2E, "Juniper SRX E2E"), + DLT_CHOICE(JUNIPER_FIBRECHANNEL, "Juniper Fibre Channel"), + DLT_CHOICE(DVB_CI, "DVB-CI"), + DLT_CHOICE(MUX27010, "MUX27010"), + DLT_CHOICE(STANAG_5066_D_PDU, "STANAG 5066 D_PDUs"), + DLT_CHOICE(JUNIPER_ATM_CEMIC, "Juniper ATM CEMIC"), + DLT_CHOICE(NFLOG, "Linux netfilter log messages"), + DLT_CHOICE(NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"), + DLT_CHOICE(NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"), + DLT_CHOICE(IPOIB, "RFC 4391 IP-over-Infiniband"), + DLT_CHOICE(MPEG_2_TS, "MPEG-2 transport stream"), + DLT_CHOICE(NG40, "ng40 protocol tester Iub/Iur"), + DLT_CHOICE(NFC_LLCP, "NFC LLCP PDUs with pseudo-header"), + DLT_CHOICE(INFINIBAND, "InfiniBand"), + DLT_CHOICE(SCTP, "SCTP"), + DLT_CHOICE(USBPCAP, "USB with USBPcap header"), + DLT_CHOICE(RTAC_SERIAL, "Schweitzer Engineering Laboratories RTAC packets"), + DLT_CHOICE(BLUETOOTH_LE_LL, "Bluetooth Low Energy air interface"), + DLT_CHOICE(NETLINK, "Linux netlink"), + DLT_CHOICE(BLUETOOTH_LINUX_MONITOR, "Bluetooth Linux Monitor"), + DLT_CHOICE(BLUETOOTH_BREDR_BB, "Bluetooth Basic Rate/Enhanced Data Rate baseband packets"), + DLT_CHOICE(BLUETOOTH_LE_LL_WITH_PHDR, "Bluetooth Low Energy air interface with pseudo-header"), + DLT_CHOICE(PROFIBUS_DL, "PROFIBUS data link layer"), + DLT_CHOICE(PKTAP, "Apple DLT_PKTAP"), + DLT_CHOICE(EPON, "Ethernet with 802.3 Clause 65 EPON preamble"), + DLT_CHOICE(IPMI_HPM_2, "IPMI trace packets"), + DLT_CHOICE(ZWAVE_R1_R2, "Z-Wave RF profile R1 and R2 packets"), + DLT_CHOICE(ZWAVE_R3, "Z-Wave RF profile R3 packets"), + DLT_CHOICE(WATTSTOPPER_DLM, "WattStopper Digital Lighting Management (DLM) and Legrand Nitoo Open protocol"), + DLT_CHOICE(ISO_14443, "ISO 14443 messages"), + DLT_CHOICE(RDS, "IEC 62106 Radio Data System groups"), DLT_CHOICE_SENTINEL }; @@ -1074,8 +1290,7 @@ pcap_datalink_name_to_val(const char *name) int i; for (i = 0; dlt_choices[i].name != NULL; i++) { - if (pcap_strcasecmp(dlt_choices[i].name + sizeof("DLT_") - 1, - name) == 0) + if (pcap_strcasecmp(dlt_choices[i].name, name) == 0) return (dlt_choices[i].dlt); } return (-1); @@ -1088,7 +1303,7 @@ pcap_datalink_val_to_name(int dlt) for (i = 0; dlt_choices[i].name != NULL; i++) { if (dlt_choices[i].dlt == dlt) - return (dlt_choices[i].name + sizeof("DLT_") - 1); + return (dlt_choices[i].name); } return (NULL); } @@ -1159,47 +1374,55 @@ pcap_tstamp_type_val_to_description(int tstamp_type) int pcap_snapshot(pcap_t *p) { + if (!p->activated) + return (PCAP_ERROR_NOT_ACTIVATED); return (p->snapshot); } int pcap_is_swapped(pcap_t *p) { - return (p->sf.swapped); + if (!p->activated) + return (PCAP_ERROR_NOT_ACTIVATED); + return (p->swapped); } int pcap_major_version(pcap_t *p) { - return (p->sf.version_major); + if (!p->activated) + return (PCAP_ERROR_NOT_ACTIVATED); + return (p->version_major); } int pcap_minor_version(pcap_t *p) { - return (p->sf.version_minor); + if (!p->activated) + return (PCAP_ERROR_NOT_ACTIVATED); + return (p->version_minor); } FILE * pcap_file(pcap_t *p) { - return (p->sf.rfile); + return (p->rfile); } int pcap_fileno(pcap_t *p) { -#ifndef WIN32 +#ifndef _WIN32 return (p->fd); #else if (p->adapter != NULL) return ((int)(DWORD)p->adapter->hFile); else - return (-1); + return (PCAP_ERROR); #endif } -#if !defined(WIN32) && !defined(MSDOS) +#if !defined(_WIN32) && !defined(MSDOS) int pcap_get_selectable_fd(pcap_t *p) { @@ -1208,7 +1431,7 @@ pcap_get_selectable_fd(pcap_t *p) #endif void -pcap_perror(pcap_t *p, char *prefix) +pcap_perror(pcap_t *p, const char *prefix) { fprintf(stderr, "%s: %s\n", prefix, p->errbuf); } @@ -1239,11 +1462,8 @@ pcap_getnonblock(pcap_t *p, char *errbuf) /* * Get the current non-blocking mode setting, under the assumption that * it's just the standard POSIX non-blocking flag. - * - * We don't look at "p->nonblock", in case somebody tweaked the FD - * directly. */ -#if !defined(WIN32) && !defined(MSDOS) +#if !defined(_WIN32) && !defined(MSDOS) int pcap_getnonblock_fd(pcap_t *p, char *errbuf) { @@ -1251,7 +1471,7 @@ pcap_getnonblock_fd(pcap_t *p, char *errbuf) fdflags = fcntl(p->fd, F_GETFL, 0); if (fdflags == -1) { - snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", + pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", pcap_strerror(errno)); return (-1); } @@ -1279,7 +1499,7 @@ pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf) return (ret); } -#if !defined(WIN32) && !defined(MSDOS) +#if !defined(_WIN32) && !defined(MSDOS) /* * Set non-blocking mode, under the assumption that it's just the * standard POSIX non-blocking flag. (This can be called by the @@ -1293,7 +1513,7 @@ pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf) fdflags = fcntl(p->fd, F_GETFL, 0); if (fdflags == -1) { - snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", + pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", pcap_strerror(errno)); return (-1); } @@ -1302,7 +1522,7 @@ pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf) else fdflags &= ~O_NONBLOCK; if (fcntl(p->fd, F_SETFL, fdflags) == -1) { - snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s", + pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s", pcap_strerror(errno)); return (-1); } @@ -1310,21 +1530,18 @@ pcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf) } #endif -#ifdef WIN32 +#ifdef _WIN32 /* - * Generate a string for the last Win32-specific error (i.e. an error generated when + * Generate a string for a Win32-specific error (i.e. an error generated when * calling a Win32 API). * For errors occurred during standard C calls, we still use pcap_strerror() */ -char * -pcap_win32strerror(void) +void +pcap_win32_err_to_str(DWORD error, char *errbuf) { - DWORD error; - static char errbuf[PCAP_ERRBUF_SIZE+1]; - int errlen; + size_t errlen; char *p; - error = GetLastError(); FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf, PCAP_ERRBUF_SIZE, NULL); @@ -1338,8 +1555,7 @@ pcap_win32strerror(void) errbuf[errlen - 2] = '\0'; } p = strchr(errbuf, '\0'); - snprintf (p, sizeof(errbuf)-(p-errbuf), " (%lu)", error); - return (errbuf); + pcap_snprintf (p, PCAP_ERRBUF_SIZE+1-(p-errbuf), " (%lu)", error); } #endif @@ -1394,8 +1610,11 @@ pcap_statustostr(int errnum) case PCAP_ERROR_PROMISC_PERM_DENIED: return ("You don't have permission to capture in promiscuous mode on that device"); + + case PCAP_ERROR_TSTAMP_PRECISION_NOTSUP: + return ("That device doesn't support that time stamp precision"); } - (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum); + (void)pcap_snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum); return(ebuf); } @@ -1406,16 +1625,25 @@ const char * pcap_strerror(int errnum) { #ifdef HAVE_STRERROR +#ifdef _WIN32 + static char errbuf[PCAP_ERRBUF_SIZE]; + errno_t errno; + errno = strerror_s(errbuf, PCAP_ERRBUF_SIZE, errnum); + if (errno != 0) /* errno = 0 if successful */ + strlcpy(errbuf, "strerror_s() error", PCAP_ERRBUF_SIZE); + return (errbuf); +#else return (strerror(errnum)); +#endif /* _WIN32 */ #else extern int sys_nerr; extern const char *const sys_errlist[]; - static char ebuf[15+10+1]; + static char errbuf[PCAP_ERRBUF_SIZE]; if ((unsigned int)errnum < sys_nerr) return ((char *)sys_errlist[errnum]); - (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum); - return(ebuf); + (void)pcap_snprintf(errbuf, sizeof errbuf, "Unknown error: %d", errnum); + return (errbuf); #endif } @@ -1435,7 +1663,7 @@ int pcap_setdirection(pcap_t *p, pcap_direction_t d) { if (p->setdirection_op == NULL) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Setting direction is not implemented on this platform"); return (-1); } else @@ -1451,12 +1679,18 @@ pcap_stats(pcap_t *p, struct pcap_stat *ps) static int pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Statistics aren't available from a pcap_open_dead pcap_t"); return (-1); } -#ifdef WIN32 +#ifdef _WIN32 +struct pcap_stat * +pcap_stats_ex(pcap_t *p, int *pcap_stat_size) +{ + return (p->stats_ex_op(p, pcap_stat_size)); +} + int pcap_setbuff(pcap_t *p, int dim) { @@ -1466,7 +1700,7 @@ pcap_setbuff(pcap_t *p, int dim) static int pcap_setbuff_dead(pcap_t *p, int dim) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set on a pcap_open_dead pcap_t"); return (-1); } @@ -1480,7 +1714,7 @@ pcap_setmode(pcap_t *p, int mode) static int pcap_setmode_dead(pcap_t *p, int mode) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode on a pcap_open_dead pcap_t"); return (-1); } @@ -1494,10 +1728,178 @@ pcap_setmintocopy(pcap_t *p, int size) static int pcap_setmintocopy_dead(pcap_t *p, int size) { - snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The mintocopy parameter cannot be set on a pcap_open_dead pcap_t"); return (-1); } + +HANDLE +pcap_getevent(pcap_t *p) +{ + return (p->getevent_op(p)); +} + +static HANDLE +pcap_getevent_dead(pcap_t *p) +{ + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "A pcap_open_dead pcap_t has no event handle"); + return (INVALID_HANDLE_VALUE); +} + +int +pcap_oid_get_request(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp) +{ + return (p->oid_get_request_op(p, oid, data, lenp)); +} + +static int +pcap_oid_get_request_dead(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_, + size_t *lenp _U_) +{ + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "An OID get request cannot be performed on a pcap_open_dead pcap_t"); + return (PCAP_ERROR); +} + +int +pcap_oid_set_request(pcap_t *p, bpf_u_int32 oid, const void *data, size_t *lenp) +{ + return (p->oid_set_request_op(p, oid, data, lenp)); +} + +static int +pcap_oid_set_request_dead(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_, + size_t *lenp _U_) +{ + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "An OID set request cannot be performed on a pcap_open_dead pcap_t"); + return (PCAP_ERROR); +} + +pcap_send_queue * +pcap_sendqueue_alloc(u_int memsize) +{ + pcap_send_queue *tqueue; + + /* Allocate the queue */ + tqueue = (pcap_send_queue *)malloc(sizeof(pcap_send_queue)); + if (tqueue == NULL){ + return (NULL); + } + + /* Allocate the buffer */ + tqueue->buffer = (char *)malloc(memsize); + if (tqueue->buffer == NULL) { + free(tqueue); + return (NULL); + } + + tqueue->maxlen = memsize; + tqueue->len = 0; + + return (tqueue); +} + +void +pcap_sendqueue_destroy(pcap_send_queue *queue) +{ + free(queue->buffer); + free(queue); +} + +int +pcap_sendqueue_queue(pcap_send_queue *queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data) +{ + if (queue->len + sizeof(struct pcap_pkthdr) + pkt_header->caplen > queue->maxlen){ + return (-1); + } + + /* Copy the pcap_pkthdr header*/ + memcpy(queue->buffer + queue->len, pkt_header, sizeof(struct pcap_pkthdr)); + queue->len += sizeof(struct pcap_pkthdr); + + /* copy the packet */ + memcpy(queue->buffer + queue->len, pkt_data, pkt_header->caplen); + queue->len += pkt_header->caplen; + + return (0); +} + +u_int +pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue, int sync) +{ + return (p->sendqueue_transmit_op(p, queue, sync)); +} + +static u_int +pcap_sendqueue_transmit_dead(pcap_t *p, pcap_send_queue *queue, int sync) +{ + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "Packets cannot be transmitted on a pcap_open_dead pcap_t"); + return (0); +} + +int +pcap_setuserbuffer(pcap_t *p, int size) +{ + return (p->setuserbuffer_op(p, size)); +} + +static int +pcap_setuserbuffer_dead(pcap_t *p, int size) +{ + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "The user buffer cannot be set on a pcap_open_dead pcap_t"); + return (-1); +} + +int +pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks) +{ + return (p->live_dump_op(p, filename, maxsize, maxpacks)); +} + +static int +pcap_live_dump_dead(pcap_t *p, char *filename, int maxsize, int maxpacks) +{ + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "Live packet dumping cannot be performed on a pcap_open_dead pcap_t"); + return (-1); +} + +int +pcap_live_dump_ended(pcap_t *p, int sync) +{ + return (p->live_dump_ended_op(p, sync)); +} + +static int +pcap_live_dump_ended_dead(pcap_t *p, int sync) +{ + pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "Live packet dumping cannot be performed on a pcap_open_dead pcap_t"); + return (-1); +} + +PAirpcapHandle +pcap_get_airpcap_handle(pcap_t *p) +{ + PAirpcapHandle handle; + + handle = p->get_airpcap_handle_op(p); + if (handle == NULL) { + (void)pcap_snprintf(p->errbuf, sizeof(p->errbuf), + "This isn't an AirPcap device"); + } + return (handle); +} + +static PAirpcapHandle +pcap_get_airpcap_handle_dead(pcap_t *p) +{ + return (NULL); +} #endif /* @@ -1542,12 +1944,11 @@ pcap_do_addexit(pcap_t *p) * "pcap_close_all()" called when we exit. */ if (!did_atexit) { - if (atexit(pcap_close_all) == -1) { + if (atexit(pcap_close_all) != 0) { /* * "atexit()" failed; let our caller know. */ - strncpy(p->errbuf, "atexit failed", - PCAP_ERRBUF_SIZE); + strlcpy(p->errbuf, "atexit failed", PCAP_ERRBUF_SIZE); return (0); } did_atexit = 1; @@ -1558,7 +1959,7 @@ pcap_do_addexit(pcap_t *p) void pcap_add_to_pcaps_to_close(pcap_t *p) { - p->md.next = pcaps_to_close; + p->next = pcaps_to_close; pcaps_to_close = p; } @@ -1568,7 +1969,7 @@ 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) { + prevpc = pc, pc = pc->next) { if (pc == p) { /* * Found it. Remove it from the list. @@ -1577,12 +1978,12 @@ pcap_remove_from_pcaps_to_close(pcap_t *p) /* * It was at the head of the list. */ - pcaps_to_close = pc->md.next; + pcaps_to_close = pc->next; } else { /* * It was in the middle of the list. */ - prevpc->md.next = pc->md.next; + prevpc->next = pc->next; } break; } @@ -1606,14 +2007,18 @@ pcap_cleanup_live_common(pcap_t *p) p->tstamp_type_list = NULL; p->tstamp_type_count = 0; } + if (p->tstamp_precision_list != NULL) { + free(p->tstamp_precision_list); + p->tstamp_precision_list = NULL; + p->tstamp_precision_count = 0; + } pcap_freecode(&p->fcode); -#if !defined(WIN32) && !defined(MSDOS) +#if !defined(_WIN32) && !defined(MSDOS) if (p->fd >= 0) { close(p->fd); p->fd = -1; } p->selectable_fd = -1; - p->send_fd = -1; #endif } @@ -1624,27 +2029,59 @@ pcap_cleanup_dead(pcap_t *p _U_) } pcap_t * -pcap_open_dead(int linktype, int snaplen) +pcap_open_dead_with_tstamp_precision(int linktype, int snaplen, u_int precision) { pcap_t *p; + switch (precision) { + + case PCAP_TSTAMP_PRECISION_MICRO: + case PCAP_TSTAMP_PRECISION_NANO: + break; + + default: + return NULL; + } p = malloc(sizeof(*p)); if (p == NULL) return NULL; memset (p, 0, sizeof(*p)); p->snapshot = snaplen; p->linktype = linktype; + p->opt.tstamp_precision = precision; p->stats_op = pcap_stats_dead; -#ifdef WIN32 +#ifdef _WIN32 + p->stats_ex_op = (stats_ex_op_t)pcap_not_initialized_ptr; p->setbuff_op = pcap_setbuff_dead; p->setmode_op = pcap_setmode_dead; p->setmintocopy_op = pcap_setmintocopy_dead; + p->getevent_op = pcap_getevent_dead; + p->oid_get_request_op = pcap_oid_get_request_dead; + p->oid_set_request_op = pcap_oid_set_request_dead; + p->sendqueue_transmit_op = pcap_sendqueue_transmit_dead; + p->setuserbuffer_op = pcap_setuserbuffer_dead; + p->live_dump_op = pcap_live_dump_dead; + p->live_dump_ended_op = pcap_live_dump_ended_dead; + p->get_airpcap_handle_op = pcap_get_airpcap_handle_dead; #endif p->cleanup_op = pcap_cleanup_dead; + + /* + * A "dead" pcap_t never requires special BPF code generation. + */ + p->bpf_codegen_flags = 0; + p->activated = 1; return (p); } +pcap_t * +pcap_open_dead(int linktype, int snaplen) +{ + return (pcap_open_dead_with_tstamp_precision(linktype, snaplen, + PCAP_TSTAMP_PRECISION_MICRO)); +} + /* * API compatible with WinPcap's "send a packet" routine - returns -1 * on error, 0 otherwise. @@ -1672,8 +2109,8 @@ pcap_inject(pcap_t *p, const void *buf, size_t size) void pcap_close(pcap_t *p) { - if (p->opt.source != NULL) - free(p->opt.source); + if (p->opt.device != NULL) + free(p->opt.device); p->cleanup_op(p); free(p); } @@ -1696,36 +2133,29 @@ pcap_offline_filter(const struct bpf_program *fp, const struct pcap_pkthdr *h, return (0); } -/* - * We make the version string static, and return a pointer to it, rather - * than exporting the version string directly. On at least some UNIXes, - * if you import data from a shared library into an program, the data is - * bound into the program binary, so if the string in the version of the - * library with which the program was linked isn't the same as the - * string in the version of the library with which the program is being - * run, various undesirable things may happen (warnings, the string - * being the one from the version of the library with which the program - * was linked, or even weirder things, such as the string being the one - * from the library but being truncated). - */ -#ifdef HAVE_VERSION_H -#include "version.h" -#else -static const char pcap_version_string[] = "libpcap version 1.x.y"; -#endif +#include "pcap_version.h" + +#ifdef _WIN32 -#ifdef WIN32 +static char *full_pcap_version_string; + +#ifdef HAVE_VERSION_H /* - * XXX - it'd be nice if we could somehow generate the WinPcap and libpcap - * version numbers when building WinPcap. (It'd be nice to do so for - * the packet.dll version number as well.) + * libpcap being built for Windows, as part of a WinPcap/Npcap source + * tree. Include version.h from that source tree to get the WinPcap/Npcap + * version. + * + * XXX - it'd be nice if we could somehow generate the WinPcap version number + * when building WinPcap. (It'd be nice to do so for the packet.dll version + * number as well.) */ -static const char wpcap_version_string[] = "4.0"; +#include "../../version.h" + +static const char wpcap_version_string[] = WINPCAP_VER_STRING; static const char pcap_version_string_fmt[] = - "WinPcap version %s, based on %s"; + WINPCAP_PRODUCT_NAME " version %s, based on %s"; static const char pcap_version_string_packet_dll_fmt[] = - "WinPcap version %s (packet.dll version %s), based on %s"; -static char *full_pcap_version_string; + WINPCAP_PRODUCT_NAME " version %s (packet.dll version %s), based on %s"; const char * pcap_lib_version(void) @@ -1750,8 +2180,12 @@ pcap_lib_version(void) strlen(pcap_version_string); full_pcap_version_string = malloc(full_pcap_version_string_len); - sprintf(full_pcap_version_string, - pcap_version_string_fmt, wpcap_version_string, + if (full_pcap_version_string == NULL) + return (NULL); + pcap_snprintf(full_pcap_version_string, + full_pcap_version_string_len, + pcap_version_string_fmt, + wpcap_version_string, pcap_version_string); } else { /* @@ -1767,16 +2201,57 @@ pcap_lib_version(void) strlen(packet_version_string) + strlen(pcap_version_string); full_pcap_version_string = malloc(full_pcap_version_string_len); - - sprintf(full_pcap_version_string, + if (full_pcap_version_string == NULL) + return (NULL); + pcap_snprintf(full_pcap_version_string, + full_pcap_version_string_len, pcap_version_string_packet_dll_fmt, - wpcap_version_string, packet_version_string, + wpcap_version_string, + packet_version_string, pcap_version_string); } } return (full_pcap_version_string); } +#else /* HAVE_VERSION_H */ + +/* + * libpcap being built for Windows, not as part of a WinPcap/Npcap source + * tree. + */ +static const char pcap_version_string_packet_dll_fmt[] = + "%s (packet.dll version %s)"; +const char * +pcap_lib_version(void) +{ + char *packet_version_string; + size_t full_pcap_version_string_len; + + if (full_pcap_version_string == NULL) { + /* + * Generate the version string. Report the packet.dll + * version. + */ + packet_version_string = PacketGetVersion(); + full_pcap_version_string_len = + (sizeof pcap_version_string_packet_dll_fmt - 4) + + strlen(pcap_version_string) + + strlen(packet_version_string); + full_pcap_version_string = malloc(full_pcap_version_string_len); + if (full_pcap_version_string == NULL) + return (NULL); + pcap_snprintf(full_pcap_version_string, + full_pcap_version_string_len, + pcap_version_string_packet_dll_fmt, + pcap_version_string, + packet_version_string); + } + return (full_pcap_version_string); +} + +#endif /* HAVE_VERSION_H */ + #elif defined(MSDOS) static char *full_pcap_version_string; @@ -1796,6 +2271,8 @@ pcap_lib_version (void) sizeof dospfx + strlen(pcap_version_string); full_pcap_version_string = malloc(full_pcap_version_string_len); + if (full_pcap_version_string == NULL) + return (NULL); strcpy(full_pcap_version_string, dospfx); strcat(full_pcap_version_string, pcap_version_string); } @@ -1810,3 +2287,51 @@ pcap_lib_version(void) return (pcap_version_string); } #endif + +#ifdef YYDEBUG +/* + * Set the internal "debug printout" flag for the filter expression parser. + * The code to print that stuff is present only if YYDEBUG is defined, so + * the flag, and the routine to set it, are defined only if YYDEBUG is + * defined. + * + * This is intended for libpcap developers, not for general use. + * If you want to set these in a program, you'll have to declare this + * routine yourself, with the appropriate DLL import attribute on Windows; + * it's not declared in any header file, and won't be declared in any + * header file provided by libpcap. + */ +PCAP_API void pcap_set_parser_debug(int value); + +PCAP_API_DEF void +pcap_set_parser_debug(int value) +{ + extern int pcap_debug; + + pcap_debug = value; +} +#endif + +#ifdef BDEBUG +/* + * Set the internal "debug printout" flag for the filter expression optimizer. + * The code to print that stuff is present only if BDEBUG is defined, so + * the flag, and the routine to set it, are defined only if BDEBUG is + * defined. + * + * This is intended for libpcap developers, not for general use. + * If you want to set these in a program, you'll have to declare this + * routine yourself, with the appropriate DLL import attribute on Windows; + * it's not declared in any header file, and won't be declared in any + * header file provided by libpcap. + */ +PCAP_API void pcap_set_optimizer_debug(int value); + +PCAP_API_DEF void +pcap_set_optimizer_debug(int value) +{ + extern int pcap_optimizer_debug; + + pcap_optimizer_debug = value; +} +#endif |