From bd64c25012f4835fbe7f62dc42adfdd90e4c85ec Mon Sep 17 00:00:00 2001 From: christos Date: Tue, 31 Mar 2015 21:39:42 +0000 Subject: [PATCH] merge conflicts --- .../bsd/libpcap/dist/bpf/net/bpf_filter.c | 103 +- external/bsd/libpcap/dist/fad-gifc.c | 16 +- external/bsd/libpcap/dist/fad-win32.c | 24 +- external/bsd/libpcap/dist/gencode.c | 2092 +++++++++-------- external/bsd/libpcap/dist/gencode.h | 10 +- external/bsd/libpcap/dist/grammar.y | 14 +- external/bsd/libpcap/dist/inet.c | 43 +- external/bsd/libpcap/dist/lbl/os-osf4.h | 4 +- external/bsd/libpcap/dist/lbl/os-osf5.h | 4 +- external/bsd/libpcap/dist/optimize.c | 104 +- .../bsd/libpcap/dist/packaging/pcap.spec.in | 77 - external/bsd/libpcap/dist/pcap-bpf.c | 47 +- external/bsd/libpcap/dist/pcap-bpf.h | 4 +- external/bsd/libpcap/dist/pcap-bt-linux.c | 53 +- external/bsd/libpcap/dist/pcap-bt-linux.h | 6 +- .../bsd/libpcap/dist/pcap-bt-monitor-linux.c | 7 +- external/bsd/libpcap/dist/pcap-can-linux.c | 6 +- external/bsd/libpcap/dist/pcap-canusb-linux.c | 70 +- external/bsd/libpcap/dist/pcap-common.c | 89 +- external/bsd/libpcap/dist/pcap-dag.c | 169 +- external/bsd/libpcap/dist/pcap-dbus.c | 16 +- external/bsd/libpcap/dist/pcap-dlpi.c | 6 +- external/bsd/libpcap/dist/pcap-dos.c | 16 +- external/bsd/libpcap/dist/pcap-dos.h | 4 +- external/bsd/libpcap/dist/pcap-int.h | 12 +- external/bsd/libpcap/dist/pcap-linux.c | 727 ++++-- .../bsd/libpcap/dist/pcap-netfilter-linux.c | 47 +- .../bsd/libpcap/dist/pcap-netfilter-linux.h | 6 +- external/bsd/libpcap/dist/pcap-nit.c | 6 +- external/bsd/libpcap/dist/pcap-pf.c | 6 +- external/bsd/libpcap/dist/pcap-septel.c | 12 +- external/bsd/libpcap/dist/pcap-sita.c | 12 +- external/bsd/libpcap/dist/pcap-snf.c | 205 +- external/bsd/libpcap/dist/pcap-snit.c | 6 +- external/bsd/libpcap/dist/pcap-snoop.c | 8 +- external/bsd/libpcap/dist/pcap-usb-linux.c | 92 +- external/bsd/libpcap/dist/pcap-usb-linux.h | 6 +- external/bsd/libpcap/dist/pcap-win32.c | 152 +- external/bsd/libpcap/dist/pcap.3pcap.in | 42 +- external/bsd/libpcap/dist/pcap.c | 25 +- external/bsd/libpcap/dist/pcap/bluetooth.h | 8 +- external/bsd/libpcap/dist/pcap/bpf.h | 57 +- external/bsd/libpcap/dist/pcap/pcap.h | 7 +- external/bsd/libpcap/dist/pcap/usb.h | 10 +- .../bsd/libpcap/dist/pcap_breakloop.3pcap | 4 +- .../dist/pcap_datalink_name_to_val.3pcap | 4 +- external/bsd/libpcap/dist/pcap_dump.3pcap | 6 +- .../bsd/libpcap/dist/pcap_dump_open.3pcap.in | 13 +- .../libpcap/dist/pcap_get_selectable_fd.3pcap | 14 +- external/bsd/libpcap/dist/pcap_loop.3pcap | 9 +- .../bsd/libpcap/dist/pcap_setdirection.3pcap | 4 +- .../bsd/libpcap/dist/pcap_setnonblock.3pcap | 10 +- .../dist/pcap_tstamp_type_name_to_val.3pcap | 4 +- external/bsd/libpcap/dist/savefile.c | 13 +- external/bsd/libpcap/dist/scanner.l | 9 +- external/bsd/libpcap/dist/sf-pcap-ng.c | 39 +- external/bsd/libpcap/dist/sf-pcap.c | 168 +- external/bsd/libpcap/dist/tests/filtertest.c | 42 +- .../bsd/libpcap/dist/tests/findalldevstest.c | 31 +- .../bsd/libpcap/dist/tests/valgrindtest.c | 6 +- external/bsd/libpcap/lib/shlib_version | 4 +- 61 files changed, 3060 insertions(+), 1750 deletions(-) delete mode 100644 external/bsd/libpcap/dist/packaging/pcap.spec.in diff --git a/external/bsd/libpcap/dist/bpf/net/bpf_filter.c b/external/bsd/libpcap/dist/bpf/net/bpf_filter.c index 13be391e3afa..8764baf1f267 100644 --- a/external/bsd/libpcap/dist/bpf/net/bpf_filter.c +++ b/external/bsd/libpcap/dist/bpf/net/bpf_filter.c @@ -1,4 +1,4 @@ -/* $NetBSD: bpf_filter.c,v 1.5 2014/11/19 19:33:31 christos Exp $ */ +/* $NetBSD: bpf_filter.c,v 1.6 2015/03/31 21:39:42 christos Exp $ */ /*- * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 @@ -188,10 +188,25 @@ m_xhalf(const struct mbuf *m, uint32_t k, int *err) } #endif +#ifdef __linux__ +#include +#include +#include +#endif + +enum { + BPF_S_ANC_NONE, + BPF_S_ANC_VLAN_TAG, + BPF_S_ANC_VLAN_TAG_PRESENT, +}; + /* * Execute the filter program starting at pc on the packet p * wirelen is the length of the original packet * buflen is the amount of data present + * aux_data is auxiliary data, currently used only when interpreting + * filters intended for the Linux kernel in cases where the kernel + * rejects the filter; it contains VLAN tag information * For the kernel, p is assumed to be a pointer to an mbuf if buflen is 0, * in all other cases, p is a pointer to a buffer and buflen is its size. */ @@ -199,8 +214,9 @@ u_int bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen, u_int buflen) { - u_int32 A, X, k; - int32 mem[BPF_MEMWORDS]; + register u_int32 A, X; + register bpf_u_int32 k; + u_int32 mem[BPF_MEMWORDS]; #if defined(KERNEL) || defined(_KERNEL) struct mbuf *m, *n; int merr, len; @@ -240,7 +256,7 @@ bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen, case BPF_LD|BPF_W|BPF_ABS: k = pc->k; - if (k + sizeof(int32) > buflen) { + if (k > buflen || sizeof(int32_t) > buflen - k) { #if defined(KERNEL) || defined(_KERNEL) if (m == NULL) return 0; @@ -257,7 +273,7 @@ bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen, case BPF_LD|BPF_H|BPF_ABS: k = pc->k; - if (k + sizeof(short) > buflen) { + if (k > buflen || sizeof(int16_t) > buflen - k) { #if defined(KERNEL) || defined(_KERNEL) if (m == NULL) return 0; @@ -273,22 +289,50 @@ bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen, continue; case BPF_LD|BPF_B|BPF_ABS: - k = pc->k; - if (k >= (int)buflen) { -#if defined(KERNEL) || defined(_KERNEL) - if (m == NULL) - return 0; - n = m; - MINDEX(len, n, k); - A = mtod(n, u_char *)[k]; - continue; -#else - return 0; -#endif - } - A = p[k]; - continue; + { +#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT) + int code = BPF_S_ANC_NONE; +#define ANCILLARY(CODE) case SKF_AD_OFF + SKF_AD_##CODE: \ + code = BPF_S_ANC_##CODE; \ + if (!aux_data) \ + return 0; \ + break; + switch (pc->k) { + ANCILLARY(VLAN_TAG); + ANCILLARY(VLAN_TAG_PRESENT); + default : +#endif + k = pc->k; + if (k >= (int)buflen) { +#if defined(KERNEL) || defined(_KERNEL) + if (m == NULL) + return 0; + n = m; + MINDEX(len, n, k); + A = mtod(n, u_char *)[k]; + continue; +#else + return 0; +#endif + } + A = p[k]; +#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT) + } + switch (code) { + case BPF_S_ANC_VLAN_TAG: + if (aux_data) + A = aux_data->vlan_tag; + break; + + case BPF_S_ANC_VLAN_TAG_PRESENT: + if (aux_data) + A = aux_data->vlan_tag_present; + break; + } +#endif + continue; + } case BPF_LD|BPF_W|BPF_LEN: A = wirelen; continue; @@ -299,7 +343,8 @@ bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen, case BPF_LD|BPF_W|BPF_IND: k = X + pc->k; - if (k + sizeof(int32) > buflen) { + if (pc->k > buflen || X > buflen - pc->k || + sizeof(int32_t) > buflen - k) { #if defined(KERNEL) || defined(_KERNEL) if (m == NULL) return 0; @@ -316,7 +361,8 @@ bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen, case BPF_LD|BPF_H|BPF_IND: k = X + pc->k; - if (k + sizeof(short) > buflen) { + if (X > buflen || pc->k > buflen - X || + sizeof(int16_t) > buflen - k) { #if defined(KERNEL) || defined(_KERNEL) if (m == NULL) return 0; @@ -333,7 +379,7 @@ bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen, case BPF_LD|BPF_B|BPF_IND: k = X + pc->k; - if (k >= (int)buflen) { + if (pc->k >= (int)buflen || X >= buflen - pc->k) { #if defined(KERNEL) || defined(_KERNEL) if (m == NULL) return 0; @@ -535,6 +581,17 @@ bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen, } } +u_int +bpf_filter(pc, p, wirelen, buflen) + register const struct bpf_insn *pc; + register const u_char *p; + u_int wirelen; + register u_int buflen; +{ + return bpf_filter_with_aux_data(pc, p, wirelen, buflen, NULL); +} + + /* * Return true if the 'fcode' is a valid filter program. * The constraints are that each jump be forward and to a valid diff --git a/external/bsd/libpcap/dist/fad-gifc.c b/external/bsd/libpcap/dist/fad-gifc.c index d4f9d8223826..1e25e5bccb9d 100644 --- a/external/bsd/libpcap/dist/fad-gifc.c +++ b/external/bsd/libpcap/dist/fad-gifc.c @@ -1,4 +1,4 @@ -/* $NetBSD: fad-gifc.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: fad-gifc.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* @@ -35,7 +35,7 @@ */ #include -__RCSID("$NetBSD: fad-gifc.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: fad-gifc.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -222,12 +222,12 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) /* * XXX - The 32-bit compatibility layer for Linux on IA-64 * is slightly broken. It correctly converts the structures - * to and from kernel land from 64 bit to 32 bit but - * doesn't update ifc.ifc_len, leaving it larger than the - * amount really used. This means we read off the end - * of the buffer and encounter an interface with an - * "empty" name. Since this is highly unlikely to ever - * occur in a valid case we can just finish looking for + * to and from kernel land from 64 bit to 32 bit but + * doesn't update ifc.ifc_len, leaving it larger than the + * amount really used. This means we read off the end + * of the buffer and encounter an interface with an + * "empty" name. Since this is highly unlikely to ever + * occur in a valid case we can just finish looking for * interfaces if we see an empty name. */ if (!(*ifrp->ifr_name)) diff --git a/external/bsd/libpcap/dist/fad-win32.c b/external/bsd/libpcap/dist/fad-win32.c index d9ec02d7fe9e..7f8db064addd 100644 --- a/external/bsd/libpcap/dist/fad-win32.c +++ b/external/bsd/libpcap/dist/fad-win32.c @@ -1,4 +1,4 @@ -/* $NetBSD: fad-win32.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: fad-win32.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy) @@ -14,9 +14,9 @@ * 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. Neither the name of the Politecnico di Torino, CACE Technologies - * nor the names of its contributors may be used to endorse or promote - * products derived from this software without specific prior written + * 3. Neither the name of the Politecnico di Torino, CACE Technologies + * nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @@ -34,7 +34,7 @@ */ #include -__RCSID("$NetBSD: fad-win32.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: fad-win32.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -132,7 +132,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) char *AdaptersName; ULONG NameLength; char *name; - + /* * Find out how big a buffer we need. * @@ -175,7 +175,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters."); return (-1); - } + } if (!PacketGetAdapterNames(AdaptersName, &NameLength)) { snprintf(errbuf, PCAP_ERRBUF_SIZE, @@ -184,7 +184,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) free(AdaptersName); return (-1); } - + /* * "PacketGetAdapterNames()" returned a list of * null-terminated ASCII interface name strings, @@ -200,7 +200,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) desc = &AdaptersName[0]; while (*desc != '\0' || *(desc + 1) != '\0') desc++; - + /* * Found it - "desc" points to the first of the two * nulls at the end of the list of names, so the @@ -208,7 +208,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) * after it. */ desc += 2; - + /* * Loop over the elements in the first list. */ @@ -236,7 +236,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) if (pcap_platform_finddevs(&devlist, errbuf) < 0) ret = -1; } - + if (ret == -1) { /* * We had an error; free the list we've been constructing. @@ -246,7 +246,7 @@ pcap_findalldevs_interfaces(pcap_if_t **alldevsp, char *errbuf) devlist = NULL; } } - + *alldevsp = devlist; free(AdaptersName); return (ret); diff --git a/external/bsd/libpcap/dist/gencode.c b/external/bsd/libpcap/dist/gencode.c index 9d0d61b27bdd..8efa7a752360 100644 --- a/external/bsd/libpcap/dist/gencode.c +++ b/external/bsd/libpcap/dist/gencode.c @@ -1,4 +1,4 @@ -/* $NetBSD: gencode.c,v 1.7 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: gencode.c,v 1.8 2015/03/31 21:39:42 christos Exp $ */ /*#define CHASE_CHAIN*/ /* @@ -23,7 +23,7 @@ */ #include -__RCSID("$NetBSD: gencode.c,v 1.7 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: gencode.c,v 1.8 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -109,6 +109,10 @@ __RCSID("$NetBSD: gencode.c,v 1.7 2014/11/19 19:33:30 christos Exp $"); #define ETHERMTU 1500 +#ifndef ETHERTYPE_TEB +#define ETHERTYPE_TEB 0x6558 +#endif + #ifndef IPPROTO_HOPOPTS #define IPPROTO_HOPOPTS 0 #endif @@ -125,6 +129,8 @@ __RCSID("$NetBSD: gencode.c,v 1.7 2014/11/19 19:33:30 christos Exp $"); #define IPPROTO_SCTP 132 #endif +#define GENEVE_PORT 6081 + #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif @@ -135,11 +141,11 @@ __RCSID("$NetBSD: gencode.c,v 1.7 2014/11/19 19:33:30 christos Exp $"); static jmp_buf top_ctx; static pcap_t *bpf_pcap; -/* Hack for updating VLAN, MPLS, and PPPoE offsets. */ +/* Hack for handling VLAN and MPLS stacks. */ #ifdef WIN32 -static u_int orig_linktype = (u_int)-1, orig_nl = (u_int)-1, label_stack_depth = (u_int)-1; +static u_int label_stack_depth = (u_int)-1, vlan_stack_depth = (u_int)-1; #else -static u_int orig_linktype = -1U, orig_nl = -1U, label_stack_depth = -1U; +static u_int label_stack_depth = -1U, vlan_stack_depth = -1U; #endif /* XXX */ @@ -168,18 +174,44 @@ static void free_reg(int); static struct block *root; +/* + * Absolute offsets, which are offsets from the beginning of the raw + * packet data, are, in the general case, the sum of a variable value + * and a constant value; the variable value may be absent, in which + * case the offset is only the constant value, and the constant value + * may be zero, in which case the offset is only the variable value. + * + * bpf_abs_offset is a structure containing all that information: + * + * is_variable is 1 if there's a variable part. + * + * constant_part is the constant part of the value, possibly zero; + * + * if is_variable is 1, reg is the register number for a register + * containing the variable value if the register has been assigned, + * and -1 otherwise. + */ +typedef struct { + int is_variable; + u_int constant_part; + int reg; +} bpf_abs_offset; + /* * Value passed to gen_load_a() to indicate what the offset argument - * is relative to. + * is relative to the beginning of. */ enum e_offrel { - OR_PACKET, /* relative to the beginning of the packet */ - OR_LINK, /* relative to the beginning of the link-layer header */ - OR_MACPL, /* relative to the end of the MAC-layer header */ - OR_NET, /* relative to the network-layer header */ - OR_NET_NOSNAP, /* relative to the network-layer header, with no SNAP header at the link layer */ - OR_TRAN_IPV4, /* relative to the transport-layer header, with IPv4 network layer */ - OR_TRAN_IPV6 /* relative to the transport-layer header, with IPv6 network layer */ + OR_PACKET, /* full packet data */ + OR_LINKHDR, /* link-layer header */ + OR_PREVLINKHDR, /* previous link-layer header */ + OR_LLC, /* 802.2 LLC header */ + OR_PREVMPLSHDR, /* previous MPLS header */ + OR_LINKTYPE, /* link-layer type */ + OR_LINKPL, /* link-layer payload */ + OR_LINKPL_NOSNAP, /* link-layer payload, with no SNAP header at the link layer */ + OR_TRAN_IPV4, /* transport-layer header, with IPv4 network layer */ + OR_TRAN_IPV6 /* transport-layer header, with IPv6 network layer */ }; #ifdef INET6 @@ -230,8 +262,7 @@ static struct block *gen_mcmp(enum e_offrel, u_int, u_int, bpf_int32, static struct block *gen_bcmp(enum e_offrel, u_int, u_int, const u_char *); static struct block *gen_ncmp(enum e_offrel, bpf_u_int32, bpf_u_int32, bpf_u_int32, bpf_u_int32, int, bpf_int32); -static struct slist *gen_load_llrel(u_int, u_int); -static struct slist *gen_load_macplrel(u_int, u_int); +static struct slist *gen_load_absoffsetrel(bpf_abs_offset *, u_int, u_int); static struct slist *gen_load_a(enum e_offrel, u_int, u_int); static struct slist *gen_loadx_iphdrlen(void); static struct block *gen_uncond(int); @@ -245,8 +276,7 @@ static struct slist *gen_load_avs_llprefixlen(void); static struct slist *gen_load_radiotap_llprefixlen(void); static struct slist *gen_load_ppi_llprefixlen(void); static void insert_compute_vloffsets(struct block *); -static struct slist *gen_llprefixlen(void); -static struct slist *gen_off_macpl(void); +static struct slist *gen_abs_offset_varpart(bpf_abs_offset *); static int ethertype_to_ppptype(int); static struct block *gen_linktype(int); static struct block *gen_snap(bpf_u_int32, bpf_u_int32); @@ -291,6 +321,7 @@ static struct slist *xfer_to_a(struct arth *); static struct block *gen_mac_multicast(int); static struct block *gen_len(int, int); static struct block *gen_check_802_11_data_frame(void); +static struct block *gen_geneve_ll_check(void); static struct block *gen_ppi_dlt_check(void); static struct block *gen_msg_abbrev(int type); @@ -771,74 +802,62 @@ gen_ncmp(offrel, offset, size, mask, jtype, reverse, v) } /* - * Various code constructs need to know the layout of the data link - * layer. These variables give the necessary offsets from the beginning + * Various code constructs need to know the layout of the packet. + * These variables give the necessary offsets from the beginning * of the packet data. */ /* - * This is the offset of the beginning of the link-layer header from - * the beginning of the raw packet data. - * - * It's usually 0, except for 802.11 with a fixed-length radio header. - * (For 802.11 with a variable-length radio header, we have to generate - * code to compute that offset; off_ll is 0 in that case.) + * Absolute offset of the beginning of the link-layer header. */ -static u_int off_ll; +static bpf_abs_offset off_linkhdr; /* - * If there's a variable-length header preceding the link-layer header, - * "reg_off_ll" is the register number for a register containing the - * length of that header, and therefore the offset of the link-layer - * header from the beginning of the raw packet data. Otherwise, - * "reg_off_ll" is -1. + * If we're checking a link-layer header for a packet encapsulated in + * another protocol layer, this is the equivalent information for the + * previous layers' link-layer header from the beginning of the raw + * packet data. */ -static int reg_off_ll; +static bpf_abs_offset off_prevlinkhdr; /* - * This is the offset of the beginning of the MAC-layer header from - * the beginning of the link-layer header. - * It's usually 0, except for ATM LANE, where it's the offset, relative - * to the beginning of the raw packet data, of the Ethernet header, and - * for Ethernet with various additional information. + * This is the equivalent information for the outermost layers' link-layer + * header. */ -static u_int off_mac; +static bpf_abs_offset off_outermostlinkhdr; /* - * This is the offset of the beginning of the MAC-layer payload, - * from the beginning of the raw packet data. - * - * I.e., it's the sum of the length of the link-layer header (without, - * for example, any 802.2 LLC header, so it's the MAC-layer - * portion of that header), plus any prefix preceding the - * link-layer header. + * "Push" the current value of the link-layer header type and link-layer + * header offset onto a "stack", and set a new value. (It's not a + * full-blown stack; we keep only the top two items.) */ -static u_int off_macpl; +#define PUSH_LINKHDR(new_linktype, new_is_variable, new_constant_part, new_reg) \ +{ \ + prevlinktype = new_linktype; \ + off_prevlinkhdr = off_linkhdr; \ + linktype = new_linktype; \ + off_linkhdr.is_variable = new_is_variable; \ + off_linkhdr.constant_part = new_constant_part; \ + off_linkhdr.reg = new_reg; \ + is_geneve = 0; \ +} /* - * This is 1 if the offset of the beginning of the MAC-layer payload - * from the beginning of the link-layer header is variable-length. + * Absolute offset of the beginning of the link-layer payload. */ -static int off_macpl_is_variable; - -/* - * If the link layer has variable_length headers, "reg_off_macpl" - * is the register number for a register containing the length of the - * link-layer header plus the length of any variable-length header - * preceding the link-layer header. Otherwise, "reg_off_macpl" - * is -1. - */ -static int reg_off_macpl; +static bpf_abs_offset off_linkpl; /* * "off_linktype" is the offset to information in the link-layer header - * giving the packet type. This offset is relative to the beginning - * of the link-layer header (i.e., it doesn't include off_ll). + * giving the packet type. This is an absolute offset from the beginning + * of the packet. * - * For Ethernet, it's the offset of the Ethernet type field. + * For Ethernet, it's the offset of the Ethernet type field; this + * means that it must have a value that skips VLAN tags. * * For link-layer types that always use 802.2 headers, it's the - * offset of the LLC header. + * offset of the LLC header; this means that it must have a value + * that skips VLAN tags. * * For PPP, it's the offset of the PPP type field. * @@ -848,16 +867,10 @@ static int reg_off_macpl; * * For Linux cooked sockets, it's the offset of the type field. * - * It's set to -1 for no encapsulation, in which case, IP is assumed. + * off_linktype.constant_part is set to -1 for no encapsulation, + * in which case, IP is assumed. */ -static u_int off_linktype; - -/* - * TRUE if "pppoes" appeared in the filter; it causes link-layer type - * checks to check the PPP header, assumed to follow a LAN-style link- - * layer header and a PPPoE session header. - */ -static int is_pppoes = 0; +static bpf_abs_offset off_linktype; /* * TRUE if the link layer includes an ATM pseudo-header. @@ -865,10 +878,11 @@ static int is_pppoes = 0; static int is_atm = 0; /* - * TRUE if "lane" appeared in the filter; it causes us to generate - * code that assumes LANE rather than LLC-encapsulated traffic in SunATM. + * TRUE if "geneve" appeared in the filter; it causes us to generate + * code that checks for a Geneve header and assume that later filters + * apply to the encapsulated payload. */ -static int is_lane = 0; +static int is_geneve = 0; /* * These are offsets for the ATM pseudo-header. @@ -899,8 +913,8 @@ static u_int off_payload; /* * These are offsets to the beginning of the network-layer header. - * They are relative to the beginning of the MAC-layer payload (i.e., - * they don't include off_ll or off_macpl). + * They are relative to the beginning of the link-layer payload (i.e., + * they don't include off_linkhdr.constant_part or off_linkpl.constant_part). * * If the link layer never uses 802.2 LLC: * @@ -925,29 +939,57 @@ static u_int off_nl; static u_int off_nl_nosnap; static int linktype; +static int prevlinktype; +static int outermostlinktype; static void init_linktype(p) pcap_t *p; { - linktype = pcap_datalink(p); pcap_fddipad = p->fddipad; + /* + * We start out with only one link-layer header. + */ + outermostlinktype = pcap_datalink(p); + off_outermostlinkhdr.constant_part = 0; + off_outermostlinkhdr.is_variable = 0; + off_outermostlinkhdr.reg = -1; + + prevlinktype = outermostlinktype; + off_prevlinkhdr.constant_part = 0; + off_prevlinkhdr.is_variable = 0; + off_prevlinkhdr.reg = -1; + + linktype = outermostlinktype; + off_linkhdr.constant_part = 0; + off_linkhdr.is_variable = 0; + off_linkhdr.reg = -1; + + /* + * XXX + */ + off_linkpl.constant_part = 0; + off_linkpl.is_variable = 0; + off_linkpl.reg = -1; + + off_linktype.constant_part = 0; + off_linktype.is_variable = 0; + off_linktype.reg = -1; + /* * Assume it's not raw ATM with a pseudo-header, for now. */ - off_mac = 0; is_atm = 0; - is_lane = 0; off_vpi = -1; off_vci = -1; off_proto = -1; off_payload = -1; /* - * And that we're not doing PPPoE. + * And not Geneve. */ - is_pppoes = 0; + is_geneve = 0; /* * And assume we're not doing SS7. @@ -959,105 +1001,94 @@ init_linktype(p) off_dpc = -1; off_sls = -1; - /* - * Also assume it's not 802.11. - */ - off_ll = 0; - off_macpl = 0; - off_macpl_is_variable = 0; - - orig_linktype = -1; - orig_nl = -1; label_stack_depth = 0; - - reg_off_ll = -1; - reg_off_macpl = -1; + vlan_stack_depth = 0; switch (linktype) { case DLT_ARCNET: - off_linktype = 2; - off_macpl = 6; + off_linktype.constant_part = 2; + off_linkpl.constant_part = 6; off_nl = 0; /* XXX in reality, variable! */ off_nl_nosnap = 0; /* no 802.2 LLC */ - return; + break; case DLT_ARCNET_LINUX: - off_linktype = 4; - off_macpl = 8; + off_linktype.constant_part = 4; + off_linkpl.constant_part = 8; off_nl = 0; /* XXX in reality, variable! */ off_nl_nosnap = 0; /* no 802.2 LLC */ - return; + break; case DLT_EN10MB: - off_linktype = 12; - off_macpl = 14; /* Ethernet header length */ + off_linktype.constant_part = 12; + off_linkpl.constant_part = 14; /* Ethernet header length */ off_nl = 0; /* Ethernet II */ off_nl_nosnap = 3; /* 802.3+802.2 */ - return; + break; case DLT_SLIP: /* * SLIP doesn't have a link level type. The 16 byte * header is hacked into our SLIP driver. */ - off_linktype = -1; - off_macpl = 16; + off_linktype.constant_part = -1; + off_linkpl.constant_part = 16; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ - return; + break; case DLT_SLIP_BSDOS: /* XXX this may be the same as the DLT_PPP_BSDOS case */ - off_linktype = -1; + off_linktype.constant_part = -1; /* XXX end */ - off_macpl = 24; + off_linkpl.constant_part = 24; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ - return; + break; case DLT_NULL: case DLT_LOOP: - off_linktype = 0; - off_macpl = 4; + off_linktype.constant_part = 0; + off_linkpl.constant_part = 4; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ - return; + break; case DLT_ENC: - off_linktype = 0; - off_macpl = 12; + off_linktype.constant_part = 0; + off_linkpl.constant_part = 12; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ - return; + break; case DLT_PPP: case DLT_PPP_PPPD: case DLT_C_HDLC: /* BSD/OS Cisco HDLC */ case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */ - off_linktype = 2; - off_macpl = 4; + off_linktype.constant_part = 2; /* skip HDLC-like framing */ + off_linkpl.constant_part = 4; /* skip HDLC-like framing and protocol field */ off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ - return; + break; case DLT_PPP_ETHER: /* * This does no include the Ethernet header, and * only covers session state. */ - off_linktype = 6; - off_macpl = 8; + off_linktype.constant_part = 6; + off_linkpl.constant_part = 8; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ - return; + break; case DLT_PPP_BSDOS: - off_linktype = 5; - off_macpl = 24; + off_linktype.constant_part = 5; + off_linkpl.constant_part = 24; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ - return; + break; case DLT_FDDI: /* @@ -1068,13 +1099,13 @@ init_linktype(p) * is being used and pick out the encapsulated Ethernet type. * XXX - should we generate code to check for SNAP? */ - off_linktype = 13; - off_linktype += pcap_fddipad; - off_macpl = 13; /* FDDI MAC header length */ - off_macpl += pcap_fddipad; + off_linktype.constant_part = 13; + off_linktype.constant_part += pcap_fddipad; + off_linkpl.constant_part = 13; /* FDDI MAC header length */ + off_linkpl.constant_part += pcap_fddipad; off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ - return; + break; case DLT_IEEE802: /* @@ -1100,19 +1131,24 @@ init_linktype(p) * the 16-bit value at an offset of 14 (shifted right * 8 - figure out which byte that is). */ - off_linktype = 14; - off_macpl = 14; /* Token Ring MAC header length */ + off_linktype.constant_part = 14; + off_linkpl.constant_part = 14; /* Token Ring MAC header length */ off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ - return; + break; - case DLT_IEEE802_11: case DLT_PRISM_HEADER: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: + off_linkhdr.is_variable = 1; + /* Fall through, 802.11 doesn't have a variable link + * prefix but is otherwise the same. */ + + case DLT_IEEE802_11: /* * 802.11 doesn't really have a link-level type field. - * We set "off_linktype" to the offset of the LLC header. + * We set "off_linktype.constant_part" to the offset of + * the LLC header. * * To check for Ethernet types, we assume that SSAP = SNAP * is being used and pick out the encapsulated Ethernet type. @@ -1127,12 +1163,12 @@ init_linktype(p) * header or an AVS header, so, in practice, it's * variable-length. */ - off_linktype = 24; - off_macpl = 0; /* link-layer header is variable-length */ - off_macpl_is_variable = 1; + off_linktype.constant_part = 24; + off_linkpl.constant_part = 0; /* link-layer header is variable-length */ + off_linkpl.is_variable = 1; off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ - return; + break; case DLT_PPI: /* @@ -1144,12 +1180,13 @@ init_linktype(p) * the encapsulated DLT should be DLT_IEEE802_11) we * generate code to check for this too. */ - off_linktype = 24; - off_macpl = 0; /* link-layer header is variable-length */ - off_macpl_is_variable = 1; + off_linktype.constant_part = 24; + off_linkpl.constant_part = 0; /* link-layer header is variable-length */ + off_linkpl.is_variable = 1; + off_linkhdr.is_variable = 1; off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ - return; + break; case DLT_ATM_RFC1483: case DLT_ATM_CLIP: /* Linux ATM defines this */ @@ -1164,11 +1201,11 @@ init_linktype(p) * or "pppoa and tcp port 80" and have it check for * PPPo{A,E} and a PPP protocol of IP and.... */ - off_linktype = 0; - off_macpl = 0; /* packet begins with LLC header */ + off_linktype.constant_part = 0; + off_linkpl.constant_part = 0; /* packet begins with LLC header */ off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ - return; + break; case DLT_SUNATM: /* @@ -1179,29 +1216,28 @@ init_linktype(p) off_vpi = SUNATM_VPI_POS; off_vci = SUNATM_VCI_POS; off_proto = PROTO_POS; - off_mac = -1; /* assume LLC-encapsulated, so no MAC-layer header */ off_payload = SUNATM_PKT_BEGIN_POS; - off_linktype = off_payload; - off_macpl = off_payload; /* if LLC-encapsulated */ + off_linktype.constant_part = off_payload; + off_linkpl.constant_part = off_payload; /* if LLC-encapsulated */ off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ - return; + break; case DLT_RAW: case DLT_IPV4: case DLT_IPV6: - off_linktype = -1; - off_macpl = 0; + off_linktype.constant_part = -1; + off_linkpl.constant_part = 0; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ - return; + break; case DLT_LINUX_SLL: /* fake header for Linux cooked socket */ - off_linktype = 14; - off_macpl = 16; + off_linktype.constant_part = 14; + off_linkpl.constant_part = 16; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ - return; + break; case DLT_LTALK: /* @@ -1209,11 +1245,11 @@ init_linktype(p) * but really it just indicates whether there is a "short" or * "long" DDP packet following. */ - off_linktype = -1; - off_macpl = 0; + off_linktype.constant_part = -1; + off_linkpl.constant_part = 0; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ - return; + break; case DLT_IP_OVER_FC: /* @@ -1226,22 +1262,22 @@ init_linktype(p) * XXX - should we generate code to check for SNAP? RFC * 2625 says SNAP should be used. */ - off_linktype = 16; - off_macpl = 16; + off_linktype.constant_part = 16; + off_linkpl.constant_part = 16; off_nl = 8; /* 802.2+SNAP */ off_nl_nosnap = 3; /* 802.2 */ - return; + break; case DLT_FRELAY: /* * XXX - we should set this to handle SNAP-encapsulated * frames (NLPID of 0x80). */ - off_linktype = -1; - off_macpl = 0; + off_linktype.constant_part = -1; + off_linkpl.constant_part = 0; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ - return; + break; /* * the only BPF-interesting FRF.16 frames are non-control frames; @@ -1249,33 +1285,33 @@ init_linktype(p) * so lets start with offset 4 for now and increments later on (FIXME); */ case DLT_MFR: - off_linktype = -1; - off_macpl = 0; + off_linktype.constant_part = -1; + off_linkpl.constant_part = 0; off_nl = 4; off_nl_nosnap = 0; /* XXX - for now -> no 802.2 LLC */ - return; + break; case DLT_APPLE_IP_OVER_IEEE1394: - off_linktype = 16; - off_macpl = 18; + off_linktype.constant_part = 16; + off_linkpl.constant_part = 18; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ - return; + break; case DLT_SYMANTEC_FIREWALL: - off_linktype = 6; - off_macpl = 44; + off_linktype.constant_part = 6; + off_linkpl.constant_part = 44; off_nl = 0; /* Ethernet II */ off_nl_nosnap = 0; /* XXX - what does it do with 802.3 packets? */ - return; + break; #ifdef HAVE_NET_PFVAR_H case DLT_PFLOG: - off_linktype = 0; - off_macpl = PFLOG_HDRLEN; + off_linktype.constant_part = 0; + off_linkpl.constant_part = PFLOG_HDRLEN; off_nl = 0; off_nl_nosnap = 0; /* no 802.2 LLC */ - return; + break; #endif case DLT_JUNIPER_MFR: @@ -1284,108 +1320,108 @@ init_linktype(p) case DLT_JUNIPER_PPP: case DLT_JUNIPER_CHDLC: case DLT_JUNIPER_FRELAY: - off_linktype = 4; - off_macpl = 4; + off_linktype.constant_part = 4; + off_linkpl.constant_part = 4; off_nl = 0; off_nl_nosnap = -1; /* no 802.2 LLC */ - return; + break; case DLT_JUNIPER_ATM1: - off_linktype = 4; /* in reality variable between 4-8 */ - off_macpl = 4; /* in reality variable between 4-8 */ + off_linktype.constant_part = 4; /* in reality variable between 4-8 */ + off_linkpl.constant_part = 4; /* in reality variable between 4-8 */ off_nl = 0; off_nl_nosnap = 10; - return; + break; case DLT_JUNIPER_ATM2: - off_linktype = 8; /* in reality variable between 8-12 */ - off_macpl = 8; /* in reality variable between 8-12 */ + off_linktype.constant_part = 8; /* in reality variable between 8-12 */ + off_linkpl.constant_part = 8; /* in reality variable between 8-12 */ off_nl = 0; off_nl_nosnap = 10; - return; + break; /* frames captured on a Juniper PPPoE service PIC * contain raw ethernet frames */ case DLT_JUNIPER_PPPOE: case DLT_JUNIPER_ETHER: - off_macpl = 14; - off_linktype = 16; + off_linkpl.constant_part = 14; + off_linktype.constant_part = 16; off_nl = 18; /* Ethernet II */ off_nl_nosnap = 21; /* 802.3+802.2 */ - return; + break; case DLT_JUNIPER_PPPOE_ATM: - off_linktype = 4; - off_macpl = 6; + off_linktype.constant_part = 4; + off_linkpl.constant_part = 6; off_nl = 0; off_nl_nosnap = -1; /* no 802.2 LLC */ - return; + break; case DLT_JUNIPER_GGSN: - off_linktype = 6; - off_macpl = 12; + off_linktype.constant_part = 6; + off_linkpl.constant_part = 12; off_nl = 0; off_nl_nosnap = -1; /* no 802.2 LLC */ - return; + break; case DLT_JUNIPER_ES: - off_linktype = 6; - off_macpl = -1; /* not really a network layer but raw IP addresses */ + off_linktype.constant_part = 6; + off_linkpl.constant_part = -1; /* not really a network layer but raw IP addresses */ off_nl = -1; /* not really a network layer but raw IP addresses */ off_nl_nosnap = -1; /* no 802.2 LLC */ - return; + break; case DLT_JUNIPER_MONITOR: - off_linktype = 12; - off_macpl = 12; + off_linktype.constant_part = 12; + off_linkpl.constant_part = 12; off_nl = 0; /* raw IP/IP6 header */ off_nl_nosnap = -1; /* no 802.2 LLC */ - return; + break; case DLT_BACNET_MS_TP: - off_linktype = -1; - off_macpl = -1; + off_linktype.constant_part = -1; + off_linkpl.constant_part = -1; off_nl = -1; off_nl_nosnap = -1; - return; + break; case DLT_JUNIPER_SERVICES: - off_linktype = 12; - off_macpl = -1; /* L3 proto location dep. on cookie type */ + off_linktype.constant_part = 12; + off_linkpl.constant_part = -1; /* L3 proto location dep. on cookie type */ off_nl = -1; /* L3 proto location dep. on cookie type */ off_nl_nosnap = -1; /* no 802.2 LLC */ - return; + break; case DLT_JUNIPER_VP: - off_linktype = 18; - off_macpl = -1; + off_linktype.constant_part = 18; + off_linkpl.constant_part = -1; off_nl = -1; off_nl_nosnap = -1; - return; + break; case DLT_JUNIPER_ST: - off_linktype = 18; - off_macpl = -1; + off_linktype.constant_part = 18; + off_linkpl.constant_part = -1; off_nl = -1; off_nl_nosnap = -1; - return; + break; case DLT_JUNIPER_ISM: - off_linktype = 8; - off_macpl = -1; + off_linktype.constant_part = 8; + off_linkpl.constant_part = -1; off_nl = -1; off_nl_nosnap = -1; - return; + break; case DLT_JUNIPER_VS: case DLT_JUNIPER_SRX_E2E: case DLT_JUNIPER_FIBRECHANNEL: case DLT_JUNIPER_ATM_CEMIC: - off_linktype = 8; - off_macpl = -1; + off_linktype.constant_part = 8; + off_linkpl.constant_part = -1; off_nl = -1; off_nl_nosnap = -1; - return; + break; case DLT_MTP2: off_li = 2; @@ -1394,11 +1430,11 @@ init_linktype(p) off_opc = 4; off_dpc = 4; off_sls = 7; - off_linktype = -1; - off_macpl = -1; + off_linktype.constant_part = -1; + off_linkpl.constant_part = -1; off_nl = -1; off_nl_nosnap = -1; - return; + break; case DLT_MTP2_WITH_PHDR: off_li = 6; @@ -1407,11 +1443,11 @@ init_linktype(p) off_opc = 8; off_dpc = 8; off_sls = 11; - off_linktype = -1; - off_macpl = -1; + off_linktype.constant_part = -1; + off_linkpl.constant_part = -1; off_nl = -1; off_nl_nosnap = -1; - return; + break; case DLT_ERF: off_li = 22; @@ -1420,52 +1456,51 @@ init_linktype(p) off_opc = 24; off_dpc = 24; off_sls = 27; - off_linktype = -1; - off_macpl = -1; + off_linktype.constant_part = -1; + off_linkpl.constant_part = -1; off_nl = -1; off_nl_nosnap = -1; - return; + break; case DLT_PFSYNC: - off_linktype = -1; - off_macpl = 4; + off_linktype.constant_part = -1; + off_linkpl.constant_part = 4; off_nl = 0; off_nl_nosnap = 0; - return; + break; case DLT_AX25_KISS: /* * Currently, only raw "link[N:M]" filtering is supported. */ - off_linktype = -1; /* variable, min 15, max 71 steps of 7 */ - off_macpl = -1; + off_linktype.constant_part = -1; /* variable, min 15, max 71 steps of 7 */ + off_linkpl.constant_part = -1; off_nl = -1; /* variable, min 16, max 71 steps of 7 */ off_nl_nosnap = -1; /* no 802.2 LLC */ - off_mac = 1; /* step over the kiss length byte */ - return; + break; case DLT_IPNET: - off_linktype = 1; - off_macpl = 24; /* ipnet header length */ + off_linktype.constant_part = 1; + off_linkpl.constant_part = 24; /* ipnet header length */ off_nl = 0; off_nl_nosnap = -1; - return; + break; case DLT_NETANALYZER: - off_mac = 4; /* MAC header is past 4-byte pseudo-header */ - off_linktype = 16; /* includes 4-byte pseudo-header */ - off_macpl = 18; /* pseudo-header+Ethernet header length */ + off_linkhdr.constant_part = 4; /* Ethernet header is past 4-byte pseudo-header */ + off_linktype.constant_part = off_linkhdr.constant_part + 12; + off_linkpl.constant_part = off_linkhdr.constant_part + 14; /* pseudo-header+Ethernet header length */ off_nl = 0; /* Ethernet II */ off_nl_nosnap = 3; /* 802.3+802.2 */ - return; + break; case DLT_NETANALYZER_TRANSPARENT: - off_mac = 12; /* MAC header is past 4-byte pseudo-header, preamble, and SFD */ - off_linktype = 24; /* includes 4-byte pseudo-header+preamble+SFD */ - off_macpl = 26; /* pseudo-header+preamble+SFD+Ethernet header length */ + off_linkhdr.constant_part = 12; /* MAC header is past 4-byte pseudo-header, preamble, and SFD */ + off_linktype.constant_part = off_linkhdr.constant_part + 12; + off_linkpl.constant_part = off_linkhdr.constant_part + 14; /* pseudo-header+preamble+SFD+Ethernet header length */ off_nl = 0; /* Ethernet II */ off_nl_nosnap = 3; /* 802.3+802.2 */ - return; + break; default: /* @@ -1474,99 +1509,54 @@ init_linktype(p) */ if (linktype >= DLT_MATCHING_MIN && linktype <= DLT_MATCHING_MAX) { - off_linktype = -1; - off_macpl = -1; + off_linktype.constant_part = -1; + off_linkpl.constant_part = -1; off_nl = -1; off_nl_nosnap = -1; - return; + } else { + bpf_error("unknown data link type %d", linktype); } - + break; } - bpf_error("unknown data link type %d", linktype); - /* NOTREACHED */ + + off_outermostlinkhdr = off_prevlinkhdr = off_linkhdr; } /* - * Load a value relative to the beginning of the link-layer header. - * The link-layer header doesn't necessarily begin at the beginning - * of the packet data; there might be a variable-length prefix containing - * radio information. + * Load a value relative to the specified absolute offset. */ static struct slist * -gen_load_llrel(offset, size) - u_int offset, size; +gen_load_absoffsetrel(bpf_abs_offset *abs_offset, u_int offset, u_int size) { struct slist *s, *s2; - s = gen_llprefixlen(); + s = gen_abs_offset_varpart(abs_offset); /* * If "s" is non-null, it has code to arrange that the X register - * contains the length of the prefix preceding the link-layer - * header. + * contains the variable part of the absolute offset, so we + * generate a load relative to that, with an offset of + * abs_offset->constant_part + offset. * - * Otherwise, the length of the prefix preceding the link-layer - * header is "off_ll". + * Otherwise, we can do an absolute load with an offset of + * abs_offset->constant_part + offset. */ if (s != NULL) { /* - * There's a variable-length prefix preceding the - * link-layer header. "s" points to a list of statements - * that put the length of that prefix into the X register. - * do an indirect load, to use the X register as an offset. + * "s" points to a list of statements that puts the + * variable part of the absolute offset into the X register. + * Do an indirect load, to use the X register as an offset. */ s2 = new_stmt(BPF_LD|BPF_IND|size); - s2->s.k = offset; + s2->s.k = abs_offset->constant_part + offset; sappend(s, s2); } else { /* - * There is no variable-length header preceding the - * link-layer header; add in off_ll, which, if there's - * a fixed-length header preceding the link-layer header, - * is the length of that header. + * There is no variable part of the absolute offset, so + * just do an absolute load. */ s = new_stmt(BPF_LD|BPF_ABS|size); - s->s.k = offset + off_ll; - } - return s; -} - -/* - * Load a value relative to the beginning of the MAC-layer payload. - */ -static struct slist * -gen_load_macplrel(offset, size) - u_int offset, size; -{ - struct slist *s, *s2; - - s = gen_off_macpl(); - - /* - * If s is non-null, the offset of the MAC-layer payload is - * variable, and s points to a list of instructions that - * arrange that the X register contains that offset. - * - * Otherwise, the offset of the MAC-layer payload is constant, - * and is in off_macpl. - */ - if (s != NULL) { - /* - * The offset of the MAC-layer payload is in the X - * register. Do an indirect load, to use the X register - * as an offset. - */ - s2 = new_stmt(BPF_LD|BPF_IND|size); - s2->s.k = offset; - sappend(s, s2); - } else { - /* - * The offset of the MAC-layer payload is constant, - * and is in off_macpl; load the value at that offset - * plus the specified offset. - */ - s = new_stmt(BPF_LD|BPF_ABS|size); - s->s.k = off_macpl + offset; + s->s.k = abs_offset->constant_part + offset; } return s; } @@ -1588,20 +1578,32 @@ gen_load_a(offrel, offset, size) s->s.k = offset; break; - case OR_LINK: - s = gen_load_llrel(offset, size); + case OR_LINKHDR: + s = gen_load_absoffsetrel(&off_linkhdr, offset, size); break; - case OR_MACPL: - s = gen_load_macplrel(offset, size); + case OR_PREVLINKHDR: + s = gen_load_absoffsetrel(&off_prevlinkhdr, offset, size); break; - case OR_NET: - s = gen_load_macplrel(off_nl + offset, size); + case OR_LLC: + s = gen_load_absoffsetrel(&off_linkpl, offset, size); break; - case OR_NET_NOSNAP: - s = gen_load_macplrel(off_nl_nosnap + offset, size); + case OR_PREVMPLSHDR: + s = gen_load_absoffsetrel(&off_linkpl, off_nl - 4 + offset, size); + break; + + case OR_LINKPL: + s = gen_load_absoffsetrel(&off_linkpl, off_nl + offset, size); + break; + + case OR_LINKPL_NOSNAP: + s = gen_load_absoffsetrel(&off_linkpl, off_nl_nosnap + offset, size); + break; + + case OR_LINKTYPE: + s = gen_load_absoffsetrel(&off_linktype, offset, size); break; case OR_TRAN_IPV4: @@ -1614,22 +1616,23 @@ gen_load_a(offrel, offset, size) s = gen_loadx_iphdrlen(); /* - * Load the item at {offset of the MAC-layer payload} + - * {offset, relative to the start of the MAC-layer + * Load the item at {offset of the link-layer payload} + + * {offset, relative to the start of the link-layer * paylod, of the IPv4 header} + {length of the IPv4 header} + * {specified offset}. * - * (If the offset of the MAC-layer payload is variable, - * it's included in the value in the X register, and - * off_macpl is 0.) + * If the offset of the link-layer payload is variable, + * the variable part of that offset is included in the + * value in the X register, and we include the constant + * part in the offset of the load. */ s2 = new_stmt(BPF_LD|BPF_IND|size); - s2->s.k = off_macpl + off_nl + offset; + s2->s.k = off_linkpl.constant_part + off_nl + offset; sappend(s, s2); break; case OR_TRAN_IPV6: - s = gen_load_macplrel(off_nl + 40 + offset, size); + s = gen_load_absoffsetrel(&off_linkpl, off_nl + 40 + offset, size); break; default: @@ -1641,22 +1644,20 @@ gen_load_a(offrel, offset, size) /* * Generate code to load into the X register the sum of the length of - * the IPv4 header and any variable-length header preceding the link-layer - * header. + * the IPv4 header and the variable part of the offset of the link-layer + * payload. */ static struct slist * gen_loadx_iphdrlen() { struct slist *s, *s2; - s = gen_off_macpl(); + s = gen_abs_offset_varpart(&off_linkpl); if (s != NULL) { /* - * There's a variable-length prefix preceding the - * link-layer header, or the link-layer header is itself - * variable-length. "s" points to a list of statements - * that put the offset of the MAC-layer payload into - * the X register. + * The offset of the link-layer payload has a variable + * part. "s" points to a list of statements that put + * the variable part of that offset into the X register. * * The 4*([k]&0xf) addressing mode can't be used, as we * don't have a constant offset, so we have to load the @@ -1664,7 +1665,7 @@ gen_loadx_iphdrlen() * the value from the X register. */ s2 = new_stmt(BPF_LD|BPF_IND|BPF_B); - s2->s.k = off_nl; + s2->s.k = off_linkpl.constant_part + off_nl; sappend(s, s2); s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K); s2->s.k = 0xf; @@ -1674,25 +1675,28 @@ gen_loadx_iphdrlen() sappend(s, s2); /* - * The A register now contains the length of the - * IP header. We need to add to it the offset of - * the MAC-layer payload, which is still in the X + * The A register now contains the length of the IP header. + * We need to add to it the variable part of the offset of + * the link-layer payload, which is still in the X * register, and move the result into the X register. */ sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); sappend(s, new_stmt(BPF_MISC|BPF_TAX)); } else { /* - * There is no variable-length header preceding the - * link-layer header, and the link-layer header is - * fixed-length; load the length of the IPv4 header, - * which is at an offset of off_nl from the beginning - * of the MAC-layer payload, and thus at an offset - * of off_mac_pl + off_nl from the beginning of the - * raw packet data. + * The offset of the link-layer payload is a constant, + * so no code was generated to load the (non-existent) + * variable part of that offset. + * + * This means we can use the 4*([k]&0xf) addressing + * mode. Load the length of the IPv4 header, which + * is at an offset of off_nl from the beginning of + * the link-layer payload, and thus at an offset of + * off_linkpl.constant_part + off_nl from the beginning + * of the raw packet data, using that addressing mode. */ s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); - s->s.k = off_macpl + off_nl; + s->s.k = off_linkpl.constant_part + off_nl; } return s; } @@ -1764,9 +1768,9 @@ gen_ether_linktype(proto) * DSAP, as we do for other types <= ETHERMTU * (i.e., other SAP values)? */ - b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); + b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU); gen_not(b0); - b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32) + b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32) ((proto << 8) | proto)); gen_and(b0, b1); return b1; @@ -1804,8 +1808,8 @@ gen_ether_linktype(proto) * This generates code to check both for the * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3. */ - b0 = gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)LLCSAP_IPX); - b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)0xFFFF); + b0 = gen_cmp(OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX); + b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF); gen_or(b0, b1); /* @@ -1819,7 +1823,7 @@ gen_ether_linktype(proto) * Now we generate code to check for 802.3 * frames in general. */ - b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); + b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU); gen_not(b0); /* @@ -1835,8 +1839,7 @@ gen_ether_linktype(proto) * do that before checking for the other frame * types. */ - b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, - (bpf_int32)ETHERTYPE_IPX); + b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX); gen_or(b0, b1); return b1; @@ -1852,7 +1855,7 @@ gen_ether_linktype(proto) * we check for an Ethernet type field less than * 1500, which means it's an 802.3 length field. */ - b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); + b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU); gen_not(b0); /* @@ -1877,7 +1880,7 @@ gen_ether_linktype(proto) * phase 1?); we just check for the Ethernet * protocol type. */ - b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); + b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto); gen_or(b0, b1); return b1; @@ -1892,10 +1895,9 @@ gen_ether_linktype(proto) * a length field, <= ETHERMTU) and * then check the DSAP. */ - b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); + b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU); gen_not(b0); - b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, - (bpf_int32)proto); + b1 = gen_cmp(OR_LINKTYPE, 2, BPF_B, (bpf_int32)proto); gen_and(b0, b1); return b1; } else { @@ -1908,7 +1910,7 @@ gen_ether_linktype(proto) * will fail and the frame won't match, * which is what we want). */ - return gen_cmp(OR_LINK, off_linktype, BPF_H, + return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto); } } @@ -1925,12 +1927,11 @@ gen_ipnet_linktype(proto) switch (proto) { case ETHERTYPE_IP: - return gen_cmp(OR_LINK, off_linktype, BPF_B, - (bpf_int32)IPH_AF_INET); + return gen_cmp(OR_LINKTYPE, 0, BPF_B, (bpf_int32)IPH_AF_INET); /* NOTREACHED */ case ETHERTYPE_IPV6: - return gen_cmp(OR_LINK, off_linktype, BPF_B, + return gen_cmp(OR_LINKTYPE, 0, BPF_B, (bpf_int32)IPH_AF_INET6); /* NOTREACHED */ @@ -1972,8 +1973,8 @@ gen_linux_sll_linktype(proto) * DSAP, as we do for other types <= ETHERMTU * (i.e., other SAP values)? */ - b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); - b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32) + b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2); + b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32) ((proto << 8) | proto)); gen_and(b0, b1); return b1; @@ -2004,17 +2005,17 @@ gen_linux_sll_linktype(proto) * then put a check for LINUX_SLL_P_802_2 frames * before it. */ - b0 = gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)LLCSAP_IPX); + b0 = gen_cmp(OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX); b1 = gen_snap(0x000000, ETHERTYPE_IPX); gen_or(b0, b1); - b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); + b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2); gen_and(b0, b1); /* * Now check for 802.3 frames and OR that with * the previous test. */ - b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_3); + b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_3); gen_or(b0, b1); /* @@ -2022,8 +2023,7 @@ gen_linux_sll_linktype(proto) * do that before checking for the other frame * types. */ - b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, - (bpf_int32)ETHERTYPE_IPX); + b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX); gen_or(b0, b1); return b1; @@ -2039,7 +2039,7 @@ gen_linux_sll_linktype(proto) * we check for the 802.2 protocol type in the * "Ethernet type" field. */ - b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2); + b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2); /* * 802.2-encapsulated ETHERTYPE_ATALK packets are @@ -2063,7 +2063,7 @@ gen_linux_sll_linktype(proto) * phase 1?); we just check for the Ethernet * protocol type. */ - b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); + b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto); gen_or(b0, b1); return b1; @@ -2077,9 +2077,8 @@ gen_linux_sll_linktype(proto) * in the "Ethernet type" field, and * then check the DSAP. */ - b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, - LINUX_SLL_P_802_2); - b1 = gen_cmp(OR_LINK, off_macpl, BPF_B, + b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2); + b1 = gen_cmp(OR_LINKHDR, off_linkpl.constant_part, BPF_B, (bpf_int32)proto); gen_and(b0, b1); return b1; @@ -2093,8 +2092,7 @@ gen_linux_sll_linktype(proto) * will fail and the frame won't match, * which is what we want). */ - return gen_cmp(OR_LINK, off_linktype, BPF_H, - (bpf_int32)proto); + return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto); } } } @@ -2132,7 +2130,7 @@ gen_load_prism_llprefixlen() * but no known software generates headers that aren't 144 * bytes long. */ - if (reg_off_ll != -1) { + if (off_linkhdr.reg != -1) { /* * Load the cookie. */ @@ -2194,7 +2192,7 @@ gen_load_prism_llprefixlen() * loading the length of the AVS header. */ s2 = new_stmt(BPF_ST); - s2->s.k = reg_off_ll; + s2->s.k = off_linkhdr.reg; sappend(s1, s2); sjcommon->s.jf = s2; @@ -2221,7 +2219,7 @@ gen_load_avs_llprefixlen() * generated uses that prefix, so we don't need to generate any * code to load it.) */ - if (reg_off_ll != -1) { + if (off_linkhdr.reg != -1) { /* * The 4 bytes at an offset of 4 from the beginning of * the AVS header are the length of the AVS header. @@ -2235,7 +2233,7 @@ gen_load_avs_llprefixlen() * it. */ s2 = new_stmt(BPF_ST); - s2->s.k = reg_off_ll; + s2->s.k = off_linkhdr.reg; sappend(s1, s2); /* @@ -2261,7 +2259,7 @@ gen_load_radiotap_llprefixlen() * generated uses that prefix, so we don't need to generate any * code to load it.) */ - if (reg_off_ll != -1) { + if (off_linkhdr.reg != -1) { /* * The 2 bytes at offsets of 2 and 3 from the beginning * of the radiotap header are the length of the radiotap @@ -2296,7 +2294,7 @@ gen_load_radiotap_llprefixlen() * it. */ s2 = new_stmt(BPF_ST); - s2->s.k = reg_off_ll; + s2->s.k = off_linkhdr.reg; sappend(s1, s2); /* @@ -2329,7 +2327,7 @@ gen_load_ppi_llprefixlen() * into the register assigned to hold that length, if one has * been assigned. */ - if (reg_off_ll != -1) { + if (off_linkhdr.reg != -1) { /* * The 2 bytes at offsets of 2 and 3 from the beginning * of the radiotap header are the length of the radiotap @@ -2364,7 +2362,7 @@ gen_load_ppi_llprefixlen() * it. */ s2 = new_stmt(BPF_ST); - s2->s.k = reg_off_ll; + s2->s.k = off_linkhdr.reg; sappend(s1, s2); /* @@ -2397,10 +2395,10 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext) struct slist *sjset_tsft_datapad, *sjset_notsft_datapad; struct slist *s_roundup; - if (reg_off_macpl == -1) { + if (off_linkpl.reg == -1) { /* * No register has been assigned to the offset of - * the MAC-layer payload, which means nobody needs + * the link-layer payload, which means nobody needs * it; don't bother computing it - just return * what we already have. */ @@ -2420,7 +2418,7 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext) * header. * * Otherwise, the length of the prefix preceding the link-layer - * header is "off_ll". + * header is "off_outermostlinkhdr.constant_part". */ if (s == NULL) { /* @@ -2429,18 +2427,18 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext) * * Load the length of the fixed-length prefix preceding * the link-layer header (if any) into the X register, - * and store it in the reg_off_macpl register. - * That length is off_ll. + * and store it in the off_linkpl.reg register. + * That length is off_outermostlinkhdr.constant_part. */ s = new_stmt(BPF_LDX|BPF_IMM); - s->s.k = off_ll; + s->s.k = off_outermostlinkhdr.constant_part; } /* * The X register contains the offset of the beginning of the * link-layer header; add 24, which is the minimum length * of the MAC header for a data frame, to that, and store it - * in reg_off_macpl, and then load the Frame Control field, + * in off_linkpl.reg, and then load the Frame Control field, * which is at the offset in the X register, with an indexed load. */ s2 = new_stmt(BPF_MISC|BPF_TXA); @@ -2449,7 +2447,7 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext) s2->s.k = 24; sappend(s, s2); s2 = new_stmt(BPF_ST); - s2->s.k = reg_off_macpl; + s2->s.k = off_linkpl.reg; sappend(s, s2); s2 = new_stmt(BPF_LD|BPF_IND|BPF_B); @@ -2485,19 +2483,19 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext) sappend(s, sjset_qos); /* - * If it's set, add 2 to reg_off_macpl, to skip the QoS + * If it's set, add 2 to off_linkpl.reg, to skip the QoS * field. * Otherwise, go to the first statement of the rest of the * program. */ sjset_qos->s.jt = s2 = new_stmt(BPF_LD|BPF_MEM); - s2->s.k = reg_off_macpl; + s2->s.k = off_linkpl.reg; sappend(s, s2); s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM); s2->s.k = 2; sappend(s, s2); s2 = new_stmt(BPF_ST); - s2->s.k = reg_off_macpl; + s2->s.k = off_linkpl.reg; sappend(s, s2); /* @@ -2577,7 +2575,7 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext) * ANDing with ~3. */ s_roundup = new_stmt(BPF_LD|BPF_MEM); - s_roundup->s.k = reg_off_macpl; + s_roundup->s.k = off_linkpl.reg; sappend(s, s_roundup); s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM); s2->s.k = 3; @@ -2586,7 +2584,7 @@ gen_load_802_11_header_len(struct slist *s, struct slist *snext) s2->s.k = ~3; sappend(s, s2); s2 = new_stmt(BPF_ST); - s2->s.k = reg_off_macpl; + s2->s.k = off_linkpl.reg; sappend(s, s2); sjset_tsft_datapad->s.jt = s_roundup; @@ -2605,13 +2603,27 @@ insert_compute_vloffsets(b) { struct slist *s; + /* There is an implicit dependency between the link + * payload and link header since the payload computation + * includes the variable part of the header. Therefore, + * if nobody else has allocated a register for the link + * header and we need it, do it now. */ + if (off_linkpl.reg != -1 && off_linkhdr.is_variable && + off_linkhdr.reg == -1) + off_linkhdr.reg = alloc_reg(); + /* * For link-layer types that have a variable-length header * preceding the link-layer header, generate code to load * the offset of the link-layer header into the register * assigned to that offset, if any. + * + * XXX - this, and the next switch statement, won't handle + * encapsulation of 802.11 or 802.11+radio information in + * some other protocol stack. That's significantly more + * complicated. */ - switch (linktype) { + switch (outermostlinktype) { case DLT_PRISM_HEADER: s = gen_load_prism_llprefixlen(); @@ -2636,10 +2648,10 @@ insert_compute_vloffsets(b) /* * For link-layer types that have a variable-length link-layer - * header, generate code to load the offset of the MAC-layer + * header, generate code to load the offset of the link-layer * payload into the register assigned to that offset, if any. */ - switch (linktype) { + switch (outermostlinktype) { case DLT_IEEE802_11: case DLT_PRISM_HEADER: @@ -2688,160 +2700,45 @@ gen_ppi_dlt_check(void) return b; } -static struct slist * -gen_prism_llprefixlen(void) -{ - struct slist *s; - - if (reg_off_ll == -1) { - /* - * We haven't yet assigned a register for the length - * of the radio header; allocate one. - */ - reg_off_ll = alloc_reg(); - } - - /* - * Load the register containing the radio length - * into the X register. - */ - s = new_stmt(BPF_LDX|BPF_MEM); - s->s.k = reg_off_ll; - return s; -} - -static struct slist * -gen_avs_llprefixlen(void) -{ - struct slist *s; - - if (reg_off_ll == -1) { - /* - * We haven't yet assigned a register for the length - * of the AVS header; allocate one. - */ - reg_off_ll = alloc_reg(); - } - - /* - * Load the register containing the AVS length - * into the X register. - */ - s = new_stmt(BPF_LDX|BPF_MEM); - s->s.k = reg_off_ll; - return s; -} - -static struct slist * -gen_radiotap_llprefixlen(void) -{ - struct slist *s; - - if (reg_off_ll == -1) { - /* - * We haven't yet assigned a register for the length - * of the radiotap header; allocate one. - */ - reg_off_ll = alloc_reg(); - } - - /* - * Load the register containing the radiotap length - * into the X register. - */ - s = new_stmt(BPF_LDX|BPF_MEM); - s->s.k = reg_off_ll; - return s; -} - /* - * At the moment we treat PPI as normal Radiotap encoded - * packets. The difference is in the function that generates - * the code at the beginning to compute the header length. - * Since this code generator of PPI supports bare 802.11 - * encapsulation only (i.e. the encapsulated DLT should be - * DLT_IEEE802_11) we generate code to check for this too. + * Take an absolute offset, and: + * + * if it has no variable part, return NULL; + * + * if it has a variable part, generate code to load the register + * containing that variable part into the X register, returning + * a pointer to that code - if no register for that offset has + * been allocated, allocate it first. + * + * (The code to set that register will be generated later, but will + * be placed earlier in the code sequence.) */ static struct slist * -gen_ppi_llprefixlen(void) +gen_abs_offset_varpart(bpf_abs_offset *off) { struct slist *s; - if (reg_off_ll == -1) { - /* - * We haven't yet assigned a register for the length - * of the radiotap header; allocate one. - */ - reg_off_ll = alloc_reg(); - } - - /* - * Load the register containing the PPI length - * into the X register. - */ - s = new_stmt(BPF_LDX|BPF_MEM); - s->s.k = reg_off_ll; - return s; -} - -/* - * Generate code to compute the link-layer header length, if necessary, - * putting it into the X register, and to return either a pointer to a - * "struct slist" for the list of statements in that code, or NULL if - * no code is necessary. - */ -static struct slist * -gen_llprefixlen(void) -{ - switch (linktype) { - - case DLT_PRISM_HEADER: - return gen_prism_llprefixlen(); - - case DLT_IEEE802_11_RADIO_AVS: - return gen_avs_llprefixlen(); - - case DLT_IEEE802_11_RADIO: - return gen_radiotap_llprefixlen(); - - case DLT_PPI: - return gen_ppi_llprefixlen(); - - default: - return NULL; - } -} - -/* - * Generate code to load the register containing the offset of the - * MAC-layer payload into the X register; if no register for that offset - * has been allocated, allocate it first. - */ -static struct slist * -gen_off_macpl(void) -{ - struct slist *s; - - if (off_macpl_is_variable) { - if (reg_off_macpl == -1) { + if (off->is_variable) { + if (off->reg == -1) { /* - * We haven't yet assigned a register for the offset - * of the MAC-layer payload; allocate one. + * We haven't yet assigned a register for the + * variable part of the offset of the link-layer + * header; allocate one. */ - reg_off_macpl = alloc_reg(); + off->reg = alloc_reg(); } /* - * Load the register containing the offset of the MAC-layer - * payload into the X register. + * Load the register containing the variable part of the + * offset of the link-layer header into the X register. */ s = new_stmt(BPF_LDX|BPF_MEM); - s->s.k = reg_off_macpl; + s->s.k = off->reg; return s; } else { /* - * That offset isn't variable, so we don't need to - * generate any code. + * That offset isn't variable, there's no variable part, + * so we don't need to generate any code. */ return NULL; } @@ -2896,6 +2793,43 @@ ethertype_to_ppptype(proto) return (proto); } +/* + * Generate any tests that, for encapsulation of a link-layer packet + * inside another protocol stack, need to be done to check for those + * link-layer packets (and that haven't already been done by a check + * for that encapsulation). + */ +static struct block * +gen_prevlinkhdr_check(void) +{ + struct block *b0; + + if (is_geneve) + return gen_geneve_ll_check(); + + switch (prevlinktype) { + + case DLT_SUNATM: + /* + * This is LANE-encapsulated Ethernet; check that the LANE + * packet doesn't begin with an LE Control marker, i.e. + * that it's data, not a control message. + * + * (We've already generated a test for LANE.) + */ + b0 = gen_cmp(OR_PREVLINKHDR, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); + gen_not(b0); + return b0; + + default: + /* + * No such tests are necessary. + */ + return NULL; + } + /*NOTREACHED*/ +} + /* * Generate code to match a particular packet type by matching the * link-layer type field or fields in the 802.2 LLC header. @@ -2929,31 +2863,22 @@ gen_linktype(proto) } } - /* - * Are we testing PPPoE packets? - */ - if (is_pppoes) { - /* - * The PPPoE session header is part of the - * MAC-layer payload, so all references - * should be relative to the beginning of - * that payload. - */ - - /* - * We use Ethernet protocol types inside libpcap; - * map them to the corresponding PPP protocol types. - */ - proto = ethertype_to_ppptype(proto); - return gen_cmp(OR_MACPL, off_linktype, BPF_H, (bpf_int32)proto); - } - switch (linktype) { case DLT_EN10MB: case DLT_NETANALYZER: case DLT_NETANALYZER_TRANSPARENT: - return gen_ether_linktype(proto); + /* Geneve has an EtherType regardless of whether there is an + * L2 header. */ + if (!is_geneve) + b0 = gen_prevlinkhdr_check(); + else + b0 = NULL; + + b1 = gen_ether_linktype(proto); + if (b0 != NULL) + gen_and(b0, b1); + return b1; /*NOTREACHED*/ break; @@ -2965,8 +2890,7 @@ gen_linktype(proto) /* fall through */ default: - return gen_cmp(OR_LINK, off_linktype, BPF_H, - (bpf_int32)proto); + return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto); /*NOTREACHED*/ break; } @@ -3016,38 +2940,16 @@ gen_linktype(proto) case DLT_SUNATM: /* - * If "is_lane" is set, check for a LANE-encapsulated - * version of this protocol, otherwise check for an - * LLC-encapsulated version of this protocol. + * Check for an LLC-encapsulated version of this protocol; + * if we were checking for LANE, linktype would no longer + * be DLT_SUNATM. * - * We assume LANE means Ethernet, not Token Ring. + * Check for LLC encapsulation and then check the protocol. */ - if (is_lane) { - /* - * Check that the packet doesn't begin with an - * LE Control marker. (We've already generated - * a test for LANE.) - */ - b0 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, - 0xFF00); - gen_not(b0); - - /* - * Now generate an Ethernet test. - */ - b1 = gen_ether_linktype(proto); - gen_and(b0, b1); - return b1; - } else { - /* - * Check for LLC encapsulation and then check the - * protocol. - */ - b0 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0); - b1 = gen_llc_linktype(proto); - gen_and(b0, b1); - return b1; - } + b0 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0); + b1 = gen_llc_linktype(proto); + gen_and(b0, b1); + return b1; /*NOTREACHED*/ break; @@ -3070,11 +2972,11 @@ gen_linktype(proto) case ETHERTYPE_IP: /* Check for a version number of 4. */ - return gen_mcmp(OR_LINK, 0, BPF_B, 0x40, 0xF0); + return gen_mcmp(OR_LINKHDR, 0, BPF_B, 0x40, 0xF0); case ETHERTYPE_IPV6: /* Check for a version number of 6. */ - return gen_mcmp(OR_LINK, 0, BPF_B, 0x60, 0xF0); + return gen_mcmp(OR_LINKHDR, 0, BPF_B, 0x60, 0xF0); default: return gen_false(); /* always false */ @@ -3115,7 +3017,7 @@ gen_linktype(proto) * map them to the corresponding PPP protocol types. */ proto = ethertype_to_ppptype(proto); - return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); + return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto); /*NOTREACHED*/ break; @@ -3131,16 +3033,16 @@ gen_linktype(proto) * Also check for Van Jacobson-compressed IP. * XXX - do this for other forms of PPP? */ - b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_IP); - b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJC); + b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, PPP_IP); + b1 = gen_cmp(OR_LINKTYPE, 0, BPF_H, PPP_VJC); gen_or(b0, b1); - b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJNC); + b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, PPP_VJNC); gen_or(b1, b0); return b0; default: proto = ethertype_to_ppptype(proto); - return gen_cmp(OR_LINK, off_linktype, BPF_H, + return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto); } /*NOTREACHED*/ @@ -3209,7 +3111,7 @@ gen_linktype(proto) proto = SWAPLONG(proto); proto = htonl(proto); } - return (gen_cmp(OR_LINK, 0, BPF_W, (bpf_int32)proto)); + return (gen_cmp(OR_LINKHDR, 0, BPF_W, (bpf_int32)proto)); #ifdef HAVE_NET_PFVAR_H case DLT_PFLOG: @@ -3218,10 +3120,10 @@ gen_linktype(proto) * the packet. */ if (proto == ETHERTYPE_IP) - return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af), + return (gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, af), BPF_B, (bpf_int32)AF_INET)); else if (proto == ETHERTYPE_IPV6) - return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af), + return (gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, af), BPF_B, (bpf_int32)AF_INET6)); else return gen_false(); @@ -3241,31 +3143,31 @@ gen_linktype(proto) return gen_false(); case ETHERTYPE_IPV6: - return (gen_cmp(OR_LINK, off_linktype, BPF_B, + return (gen_cmp(OR_LINKTYPE, 0, BPF_B, (bpf_int32)ARCTYPE_INET6)); case ETHERTYPE_IP: - b0 = gen_cmp(OR_LINK, off_linktype, BPF_B, + b0 = gen_cmp(OR_LINKTYPE, 0, BPF_B, (bpf_int32)ARCTYPE_IP); - b1 = gen_cmp(OR_LINK, off_linktype, BPF_B, + b1 = gen_cmp(OR_LINKTYPE, 0, BPF_B, (bpf_int32)ARCTYPE_IP_OLD); gen_or(b0, b1); return (b1); case ETHERTYPE_ARP: - b0 = gen_cmp(OR_LINK, off_linktype, BPF_B, + b0 = gen_cmp(OR_LINKTYPE, 0, BPF_B, (bpf_int32)ARCTYPE_ARP); - b1 = gen_cmp(OR_LINK, off_linktype, BPF_B, + b1 = gen_cmp(OR_LINKTYPE, 0, BPF_B, (bpf_int32)ARCTYPE_ARP_OLD); gen_or(b0, b1); return (b1); case ETHERTYPE_REVARP: - return (gen_cmp(OR_LINK, off_linktype, BPF_B, + return (gen_cmp(OR_LINKTYPE, 0, BPF_B, (bpf_int32)ARCTYPE_REVARP)); case ETHERTYPE_ATALK: - return (gen_cmp(OR_LINK, off_linktype, BPF_B, + return (gen_cmp(OR_LINKTYPE, 0, BPF_B, (bpf_int32)ARCTYPE_ATALK)); } /*NOTREACHED*/ @@ -3292,13 +3194,13 @@ gen_linktype(proto) /* * Check for the special NLPID for IP. */ - return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0xcc); + return gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0xcc); case ETHERTYPE_IPV6: /* * Check for the special NLPID for IPv6. */ - return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0x8e); + return gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0x8e); case LLCSAP_ISONS: /* @@ -3312,9 +3214,9 @@ gen_linktype(proto) * control field of UI, i.e. 0x03 followed * by the NLPID. */ - b0 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO8473_CLNP); - b1 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO9542_ESIS); - b2 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO10589_ISIS); + b0 = gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO8473_CLNP); + b1 = gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO9542_ESIS); + b2 = gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO10589_ISIS); gen_or(b1, b2); gen_or(b0, b2); return b2; @@ -3358,10 +3260,10 @@ gen_linktype(proto) * * FIXME encapsulation specific BPF_ filters */ - return gen_mcmp(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */ + return gen_mcmp(OR_LINKHDR, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */ case DLT_BACNET_MS_TP: - return gen_mcmp(OR_LINK, 0, BPF_W, 0x55FF0000, 0xffff0000); + return gen_mcmp(OR_LINKHDR, 0, BPF_W, 0x55FF0000, 0xffff0000); case DLT_IPNET: return gen_ipnet_linktype(proto); @@ -3430,16 +3332,16 @@ gen_linktype(proto) /* * Does this link-layer header type have a field * indicating the type of the next protocol? If - * so, off_linktype will be the offset of that + * so, off_linktype.constant_part will be the offset of that * field in the packet; if not, it will be -1. */ - if (off_linktype != (u_int)-1) { + if (off_linktype.constant_part != (u_int)-1) { /* * Yes; assume it's an Ethernet type. (If * it's not, it needs to be handled specially * above.) */ - return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto); + return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto); } else { /* * No; report an error. @@ -3479,7 +3381,7 @@ gen_snap(orgcode, ptype) snapblock[5] = (orgcode >> 0); /* lower 8 bits of organization code */ snapblock[6] = (ptype >> 8); /* upper 8 bits of protocol type */ snapblock[7] = (ptype >> 0); /* lower 8 bits of protocol type */ - return gen_bcmp(OR_MACPL, 0, 8, snapblock); + return gen_bcmp(OR_LLC, 0, 8, snapblock); } /* @@ -3497,14 +3399,14 @@ gen_llc(void) * We check for an Ethernet type field less than * 1500, which means it's an 802.3 length field. */ - b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU); + b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU); gen_not(b0); /* * Now check for the purported DSAP and SSAP not being * 0xFF, to rule out NetWare-over-802.3. */ - b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)0xFFFF); + b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF); gen_not(b1); gen_and(b0, b1); return b1; @@ -3571,7 +3473,7 @@ gen_llc_i(void) * Load the control byte and test the low-order bit; it must * be clear for I frames. */ - s = gen_load_a(OR_MACPL, 2, BPF_B); + s = gen_load_a(OR_LLC, 2, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x01; b1->stmts = s; @@ -3594,7 +3496,7 @@ gen_llc_s(void) * Now compare the low-order 2 bit of the control byte against * the appropriate value for S frames. */ - b1 = gen_mcmp(OR_MACPL, 2, BPF_B, LLC_S_FMT, 0x03); + b1 = gen_mcmp(OR_LLC, 2, BPF_B, LLC_S_FMT, 0x03); gen_and(b0, b1); return b1; } @@ -3613,7 +3515,7 @@ gen_llc_u(void) * Now compare the low-order 2 bit of the control byte against * the appropriate value for U frames. */ - b1 = gen_mcmp(OR_MACPL, 2, BPF_B, LLC_U_FMT, 0x03); + b1 = gen_mcmp(OR_LLC, 2, BPF_B, LLC_U_FMT, 0x03); gen_and(b0, b1); return b1; } @@ -3631,7 +3533,7 @@ gen_llc_s_subtype(bpf_u_int32 subtype) /* * Now check for an S frame with the appropriate type. */ - b1 = gen_mcmp(OR_MACPL, 2, BPF_B, subtype, LLC_S_CMD_MASK); + b1 = gen_mcmp(OR_LLC, 2, BPF_B, subtype, LLC_S_CMD_MASK); gen_and(b0, b1); return b1; } @@ -3649,7 +3551,7 @@ gen_llc_u_subtype(bpf_u_int32 subtype) /* * Now check for a U frame with the appropriate type. */ - b1 = gen_mcmp(OR_MACPL, 2, BPF_B, subtype, LLC_U_CMD_MASK); + b1 = gen_mcmp(OR_LLC, 2, BPF_B, subtype, LLC_U_CMD_MASK); gen_and(b0, b1); return b1; } @@ -3681,10 +3583,9 @@ gen_llc_linktype(proto) /* * XXX - should we check both the DSAP and the * SSAP, like this, or should we check just the - * DSAP, as we do for other types <= ETHERMTU - * (i.e., other SAP values)? + * DSAP, as we do for other SAP values? */ - return gen_cmp(OR_MACPL, 0, BPF_H, (bpf_u_int32) + return gen_cmp(OR_LLC, 0, BPF_H, (bpf_u_int32) ((proto << 8) | proto)); case LLCSAP_IPX: @@ -3692,7 +3593,7 @@ gen_llc_linktype(proto) * XXX - are there ever SNAP frames for IPX on * non-Ethernet 802.x networks? */ - return gen_cmp(OR_MACPL, 0, BPF_B, + return gen_cmp(OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX); case ETHERTYPE_ATALK: @@ -3717,7 +3618,7 @@ gen_llc_linktype(proto) * This is an LLC SAP value, so check * the DSAP. */ - return gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)proto); + return gen_cmp(OR_LLC, 0, BPF_B, (bpf_int32)proto); } else { /* * This is an Ethernet type; we assume that it's @@ -3738,7 +3639,7 @@ gen_llc_linktype(proto) * I don't know whether it's worth the extra CPU * time to do the right check or not. */ - return gen_cmp(OR_MACPL, 6, BPF_H, (bpf_int32)proto); + return gen_cmp(OR_LLC, 6, BPF_H, (bpf_int32)proto); } } } @@ -3780,7 +3681,7 @@ gen_hostop(addr, mask, dir, proto, src_off, dst_off) abort(); } b0 = gen_linktype(proto); - b1 = gen_mcmp(OR_NET, offset, BPF_W, (bpf_int32)addr, mask); + b1 = gen_mcmp(OR_LINKPL, offset, BPF_W, (bpf_int32)addr, mask); gen_and(b0, b1); return b1; } @@ -3826,12 +3727,12 @@ gen_hostop6(addr, mask, dir, proto, src_off, dst_off) /* this order is important */ a = (u_int32_t *)addr; m = (u_int32_t *)mask; - b1 = gen_mcmp(OR_NET, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3])); - b0 = gen_mcmp(OR_NET, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2])); + b1 = gen_mcmp(OR_LINKPL, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3])); + b0 = gen_mcmp(OR_LINKPL, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2])); gen_and(b0, b1); - b0 = gen_mcmp(OR_NET, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1])); + b0 = gen_mcmp(OR_LINKPL, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1])); gen_and(b0, b1); - b0 = gen_mcmp(OR_NET, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0])); + b0 = gen_mcmp(OR_LINKPL, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0])); gen_and(b0, b1); b0 = gen_linktype(proto); gen_and(b0, b1); @@ -3848,10 +3749,10 @@ gen_ehostop(eaddr, dir) switch (dir) { case Q_SRC: - return gen_bcmp(OR_LINK, off_mac + 6, 6, eaddr); + return gen_bcmp(OR_LINKHDR, 6, 6, eaddr); case Q_DST: - return gen_bcmp(OR_LINK, off_mac + 0, 6, eaddr); + return gen_bcmp(OR_LINKHDR, 0, 6, eaddr); case Q_AND: b0 = gen_ehostop(eaddr, Q_SRC); @@ -3906,10 +3807,10 @@ gen_fhostop(eaddr, dir) switch (dir) { case Q_SRC: - return gen_bcmp(OR_LINK, 6 + 1 + pcap_fddipad, 6, eaddr); + return gen_bcmp(OR_LINKHDR, 6 + 1 + pcap_fddipad, 6, eaddr); case Q_DST: - return gen_bcmp(OR_LINK, 0 + 1 + pcap_fddipad, 6, eaddr); + return gen_bcmp(OR_LINKHDR, 0 + 1 + pcap_fddipad, 6, eaddr); case Q_AND: b0 = gen_fhostop(eaddr, Q_SRC); @@ -3964,10 +3865,10 @@ gen_thostop(eaddr, dir) switch (dir) { case Q_SRC: - return gen_bcmp(OR_LINK, 8, 6, eaddr); + return gen_bcmp(OR_LINKHDR, 8, 6, eaddr); case Q_DST: - return gen_bcmp(OR_LINK, 2, 6, eaddr); + return gen_bcmp(OR_LINKHDR, 2, 6, eaddr); case Q_AND: b0 = gen_thostop(eaddr, Q_SRC); @@ -4059,7 +3960,7 @@ gen_wlanhostop(eaddr, dir) * * First, check for To DS set, i.e. check "link[1] & 0x01". */ - s = gen_load_a(OR_LINK, 1, BPF_B); + s = gen_load_a(OR_LINKHDR, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x01; /* To DS */ b1->stmts = s; @@ -4067,14 +3968,14 @@ gen_wlanhostop(eaddr, dir) /* * If To DS is set, the SA is at 24. */ - b0 = gen_bcmp(OR_LINK, 24, 6, eaddr); + b0 = gen_bcmp(OR_LINKHDR, 24, 6, eaddr); gen_and(b1, b0); /* * Now, check for To DS not set, i.e. check * "!(link[1] & 0x01)". */ - s = gen_load_a(OR_LINK, 1, BPF_B); + s = gen_load_a(OR_LINKHDR, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x01; /* To DS */ b2->stmts = s; @@ -4083,7 +3984,7 @@ gen_wlanhostop(eaddr, dir) /* * If To DS is not set, the SA is at 16. */ - b1 = gen_bcmp(OR_LINK, 16, 6, eaddr); + b1 = gen_bcmp(OR_LINKHDR, 16, 6, eaddr); gen_and(b2, b1); /* @@ -4097,7 +3998,7 @@ gen_wlanhostop(eaddr, dir) * Now check for From DS being set, and AND that with * the ORed-together checks. */ - s = gen_load_a(OR_LINK, 1, BPF_B); + s = gen_load_a(OR_LINKHDR, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x02; /* From DS */ b1->stmts = s; @@ -4106,7 +4007,7 @@ gen_wlanhostop(eaddr, dir) /* * Now check for data frames with From DS not set. */ - s = gen_load_a(OR_LINK, 1, BPF_B); + s = gen_load_a(OR_LINKHDR, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x02; /* From DS */ b2->stmts = s; @@ -4115,7 +4016,7 @@ gen_wlanhostop(eaddr, dir) /* * If From DS isn't set, the SA is at 10. */ - b1 = gen_bcmp(OR_LINK, 10, 6, eaddr); + b1 = gen_bcmp(OR_LINKHDR, 10, 6, eaddr); gen_and(b2, b1); /* @@ -4129,7 +4030,7 @@ gen_wlanhostop(eaddr, dir) * Now check for a data frame. * I.e, check "link[0] & 0x08". */ - s = gen_load_a(OR_LINK, 0, BPF_B); + s = gen_load_a(OR_LINKHDR, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; @@ -4144,7 +4045,7 @@ gen_wlanhostop(eaddr, dir) * is a management frame. * I.e, check "!(link[0] & 0x08)". */ - s = gen_load_a(OR_LINK, 0, BPF_B); + s = gen_load_a(OR_LINKHDR, 0, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x08; b2->stmts = s; @@ -4153,7 +4054,7 @@ gen_wlanhostop(eaddr, dir) /* * For management frames, the SA is at 10. */ - b1 = gen_bcmp(OR_LINK, 10, 6, eaddr); + b1 = gen_bcmp(OR_LINKHDR, 10, 6, eaddr); gen_and(b2, b1); /* @@ -4171,7 +4072,7 @@ gen_wlanhostop(eaddr, dir) * * I.e., check "!(link[0] & 0x04)". */ - s = gen_load_a(OR_LINK, 0, BPF_B); + s = gen_load_a(OR_LINKHDR, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; @@ -4206,7 +4107,7 @@ gen_wlanhostop(eaddr, dir) * * First, check for To DS set, i.e. "link[1] & 0x01". */ - s = gen_load_a(OR_LINK, 1, BPF_B); + s = gen_load_a(OR_LINKHDR, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x01; /* To DS */ b1->stmts = s; @@ -4214,14 +4115,14 @@ gen_wlanhostop(eaddr, dir) /* * If To DS is set, the DA is at 16. */ - b0 = gen_bcmp(OR_LINK, 16, 6, eaddr); + b0 = gen_bcmp(OR_LINKHDR, 16, 6, eaddr); gen_and(b1, b0); /* * Now, check for To DS not set, i.e. check * "!(link[1] & 0x01)". */ - s = gen_load_a(OR_LINK, 1, BPF_B); + s = gen_load_a(OR_LINKHDR, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x01; /* To DS */ b2->stmts = s; @@ -4230,7 +4131,7 @@ gen_wlanhostop(eaddr, dir) /* * If To DS is not set, the DA is at 4. */ - b1 = gen_bcmp(OR_LINK, 4, 6, eaddr); + b1 = gen_bcmp(OR_LINKHDR, 4, 6, eaddr); gen_and(b2, b1); /* @@ -4243,7 +4144,7 @@ gen_wlanhostop(eaddr, dir) * Now check for a data frame. * I.e, check "link[0] & 0x08". */ - s = gen_load_a(OR_LINK, 0, BPF_B); + s = gen_load_a(OR_LINKHDR, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; @@ -4258,7 +4159,7 @@ gen_wlanhostop(eaddr, dir) * is a management frame. * I.e, check "!(link[0] & 0x08)". */ - s = gen_load_a(OR_LINK, 0, BPF_B); + s = gen_load_a(OR_LINKHDR, 0, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x08; b2->stmts = s; @@ -4267,7 +4168,7 @@ gen_wlanhostop(eaddr, dir) /* * For management frames, the DA is at 4. */ - b1 = gen_bcmp(OR_LINK, 4, 6, eaddr); + b1 = gen_bcmp(OR_LINKHDR, 4, 6, eaddr); gen_and(b2, b1); /* @@ -4285,7 +4186,7 @@ gen_wlanhostop(eaddr, dir) * * I.e., check "!(link[0] & 0x04)". */ - s = gen_load_a(OR_LINK, 0, BPF_B); + s = gen_load_a(OR_LINKHDR, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; @@ -4309,7 +4210,7 @@ gen_wlanhostop(eaddr, dir) * is a management frame. * I.e, check "(link[0] & 0x08)". */ - s = gen_load_a(OR_LINK, 0, BPF_B); + s = gen_load_a(OR_LINKHDR, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; @@ -4317,7 +4218,7 @@ gen_wlanhostop(eaddr, dir) /* * Check addr1. */ - b0 = gen_bcmp(OR_LINK, 4, 6, eaddr); + b0 = gen_bcmp(OR_LINKHDR, 4, 6, eaddr); /* * AND that with the check of addr1. @@ -4334,13 +4235,13 @@ gen_wlanhostop(eaddr, dir) /* * Not present in CTS or ACK control frames. */ - b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL, + b0 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL, IEEE80211_FC0_TYPE_MASK); gen_not(b0); - b1 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS, + b1 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS, IEEE80211_FC0_SUBTYPE_MASK); gen_not(b1); - b2 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK, + b2 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK, IEEE80211_FC0_SUBTYPE_MASK); gen_not(b2); gen_and(b1, b2); @@ -4351,7 +4252,7 @@ gen_wlanhostop(eaddr, dir) * is a management frame. * I.e, check "(link[0] & 0x08)". */ - s = gen_load_a(OR_LINK, 0, BPF_B); + s = gen_load_a(OR_LINKHDR, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; @@ -4365,7 +4266,7 @@ gen_wlanhostop(eaddr, dir) /* * Check addr2. */ - b1 = gen_bcmp(OR_LINK, 10, 6, eaddr); + b1 = gen_bcmp(OR_LINKHDR, 10, 6, eaddr); gen_and(b2, b1); return b1; @@ -4373,24 +4274,24 @@ gen_wlanhostop(eaddr, dir) * XXX - add BSSID keyword? */ case Q_ADDR1: - return (gen_bcmp(OR_LINK, 4, 6, eaddr)); + return (gen_bcmp(OR_LINKHDR, 4, 6, eaddr)); case Q_ADDR2: /* * Not present in CTS or ACK control frames. */ - b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL, + b0 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL, IEEE80211_FC0_TYPE_MASK); gen_not(b0); - b1 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS, + b1 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS, IEEE80211_FC0_SUBTYPE_MASK); gen_not(b1); - b2 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK, + b2 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK, IEEE80211_FC0_SUBTYPE_MASK); gen_not(b2); gen_and(b1, b2); gen_or(b0, b2); - b1 = gen_bcmp(OR_LINK, 10, 6, eaddr); + b1 = gen_bcmp(OR_LINKHDR, 10, 6, eaddr); gen_and(b2, b1); return b1; @@ -4398,10 +4299,10 @@ gen_wlanhostop(eaddr, dir) /* * Not present in control frames. */ - b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL, + b0 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL, IEEE80211_FC0_TYPE_MASK); gen_not(b0); - b1 = gen_bcmp(OR_LINK, 16, 6, eaddr); + b1 = gen_bcmp(OR_LINKHDR, 16, 6, eaddr); gen_and(b0, b1); return b1; @@ -4412,9 +4313,9 @@ gen_wlanhostop(eaddr, dir) * frames should have both of those set, so we don't * check the frame type. */ - b0 = gen_mcmp(OR_LINK, 1, BPF_B, + b0 = gen_mcmp(OR_LINKHDR, 1, BPF_B, IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK); - b1 = gen_bcmp(OR_LINK, 24, 6, eaddr); + b1 = gen_bcmp(OR_LINKHDR, 24, 6, eaddr); gen_and(b0, b1); return b1; @@ -4449,10 +4350,10 @@ gen_ipfchostop(eaddr, dir) switch (dir) { case Q_SRC: - return gen_bcmp(OR_LINK, 10, 6, eaddr); + return gen_bcmp(OR_LINKHDR, 10, 6, eaddr); case Q_DST: - return gen_bcmp(OR_LINK, 2, 6, eaddr); + return gen_bcmp(OR_LINKHDR, 2, 6, eaddr); case Q_AND: b0 = gen_ipfchostop(eaddr, Q_SRC); @@ -4557,25 +4458,25 @@ gen_dnhostop(addr, dir) } b0 = gen_linktype(ETHERTYPE_DN); /* Check for pad = 1, long header case */ - tmp = gen_mcmp(OR_NET, 2, BPF_H, + tmp = gen_mcmp(OR_LINKPL, 2, BPF_H, (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF)); - b1 = gen_cmp(OR_NET, 2 + 1 + offset_lh, + b1 = gen_cmp(OR_LINKPL, 2 + 1 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr)); gen_and(tmp, b1); /* Check for pad = 0, long header case */ - tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7); - b2 = gen_cmp(OR_NET, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr)); + tmp = gen_mcmp(OR_LINKPL, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7); + b2 = gen_cmp(OR_LINKPL, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr)); gen_and(tmp, b2); gen_or(b2, b1); /* Check for pad = 1, short header case */ - tmp = gen_mcmp(OR_NET, 2, BPF_H, + tmp = gen_mcmp(OR_LINKPL, 2, BPF_H, (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF)); - b2 = gen_cmp(OR_NET, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr)); + b2 = gen_cmp(OR_LINKPL, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr)); gen_and(tmp, b2); gen_or(b2, b1); /* Check for pad = 0, short header case */ - tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7); - b2 = gen_cmp(OR_NET, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr)); + tmp = gen_mcmp(OR_LINKPL, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7); + b2 = gen_cmp(OR_LINKPL, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr)); gen_and(tmp, b2); gen_or(b2, b1); @@ -4599,17 +4500,17 @@ gen_mpls_linktype(proto) case Q_IP: /* match the bottom-of-stack bit */ - b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01); + b0 = gen_mcmp(OR_LINKPL, -2, BPF_B, 0x01, 0x01); /* match the IPv4 version number */ - b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x40, 0xf0); + b1 = gen_mcmp(OR_LINKPL, 0, BPF_B, 0x40, 0xf0); gen_and(b0, b1); return b1; case Q_IPV6: /* match the bottom-of-stack bit */ - b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01); + b0 = gen_mcmp(OR_LINKPL, -2, BPF_B, 0x01, 0x01); /* match the IPv4 version number */ - b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x60, 0xf0); + b1 = gen_mcmp(OR_LINKPL, 0, BPF_B, 0x60, 0xf0); gen_and(b0, b1); return b1; @@ -4895,7 +4796,10 @@ gen_gateway(eaddr, alist, proto, dir) case DLT_EN10MB: case DLT_NETANALYZER: case DLT_NETANALYZER_TRANSPARENT: + b1 = gen_prevlinkhdr_check(); b0 = gen_ehostop(eaddr, Q_OR); + if (b1 != NULL) + gen_and(b1, b0); break; case DLT_FDDI: b0 = gen_fhostop(eaddr, Q_OR); @@ -4911,23 +4815,13 @@ gen_gateway(eaddr, alist, proto, dir) b0 = gen_wlanhostop(eaddr, Q_OR); break; case DLT_SUNATM: - if (!is_lane) - bpf_error( - "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel"); /* - * Check that the packet doesn't begin with an - * LE Control marker. (We've already generated - * a test for LANE.) + * This is LLC-multiplexed traffic; if it were + * LANE, linktype would have been set to + * DLT_EN10MB. */ - b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, - BPF_H, 0xFF00); - gen_not(b1); - - /* - * Now check the MAC address. - */ - b0 = gen_ehostop(eaddr, Q_OR); - gen_and(b1, b0); + bpf_error( + "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel"); break; case DLT_IP_OVER_FC: b0 = gen_ipfchostop(eaddr, Q_OR); @@ -5200,7 +5094,7 @@ gen_ipfrag() struct block *b; /* not IPv4 frag other than the first frag */ - s = gen_load_a(OR_NET, 6, BPF_H); + s = gen_load_a(OR_LINKPL, 6, BPF_H); b = new_block(JMP(BPF_JSET)); b->s.k = 0x1fff; b->stmts = s; @@ -5241,7 +5135,7 @@ gen_portop(port, proto, dir) struct block *b0, *b1, *tmp; /* ip proto 'proto' and not a fragment other than the first fragment */ - tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto); + tmp = gen_cmp(OR_LINKPL, 9, BPF_B, (bpf_int32)proto); b0 = gen_ipfrag(); gen_and(tmp, b0); @@ -5332,7 +5226,7 @@ gen_portop6(port, proto, dir) /* ip6 proto 'proto' */ /* XXX - catch the first fragment of a fragmented packet? */ - b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto); + b0 = gen_cmp(OR_LINKPL, 6, BPF_B, (bpf_int32)proto); switch (dir) { case Q_SRC: @@ -5433,7 +5327,7 @@ gen_portrangeop(port1, port2, proto, dir) struct block *b0, *b1, *tmp; /* ip proto 'proto' and not a fragment other than the first fragment */ - tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto); + tmp = gen_cmp(OR_LINKPL, 9, BPF_B, (bpf_int32)proto); b0 = gen_ipfrag(); gen_and(tmp, b0); @@ -5536,7 +5430,7 @@ gen_portrangeop6(port1, port2, proto, dir) /* ip6 proto 'proto' */ /* XXX - catch the first fragment of a fragmented packet? */ - b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto); + b0 = gen_cmp(OR_LINKPL, 6, BPF_B, (bpf_int32)proto); switch (dir) { case Q_SRC: @@ -5700,15 +5594,8 @@ gen_protochain(v, proto, dir) * branches, and backward branch support is unlikely to appear * in kernel BPF engines.) */ - switch (linktype) { - - case DLT_IEEE802_11: - case DLT_PRISM_HEADER: - case DLT_IEEE802_11_RADIO_AVS: - case DLT_IEEE802_11_RADIO: - case DLT_PPI: - bpf_error("'protochain' not supported with 802.11"); - } + if (off_linkpl.is_variable) + bpf_error("'protochain' not supported with variable length headers"); no_optimize = 1; /*this code is not compatible with optimzer yet */ @@ -5727,11 +5614,11 @@ gen_protochain(v, proto, dir) /* A = ip->ip_p */ s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B); - s[i]->s.k = off_macpl + off_nl + 9; + s[i]->s.k = off_linkpl.constant_part + off_nl + 9; i++; /* X = ip->ip_hl << 2 */ s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B); - s[i]->s.k = off_macpl + off_nl; + s[i]->s.k = off_linkpl.constant_part + off_nl; i++; break; @@ -5740,7 +5627,7 @@ gen_protochain(v, proto, dir) /* A = ip6->ip_nxt */ s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B); - s[i]->s.k = off_macpl + off_nl + 6; + s[i]->s.k = off_linkpl.constant_part + off_nl + 6; i++; /* X = sizeof(struct ip6_hdr) */ s[i] = new_stmt(BPF_LDX|BPF_IMM); @@ -5816,7 +5703,7 @@ gen_protochain(v, proto, dir) */ /* A = P[X + packet head] */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); - s[i]->s.k = off_macpl + off_nl; + s[i]->s.k = off_linkpl.constant_part + off_nl; i++; /* MEM[reg2] = A */ s[i] = new_stmt(BPF_ST); @@ -5824,7 +5711,7 @@ gen_protochain(v, proto, dir) i++; /* A = P[X + packet head + 1]; */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); - s[i]->s.k = off_macpl + off_nl + 1; + s[i]->s.k = off_linkpl.constant_part + off_nl + 1; i++; /* A += 1 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); @@ -5885,7 +5772,7 @@ gen_protochain(v, proto, dir) i++; /* A = P[X + packet head]; */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); - s[i]->s.k = off_macpl + off_nl; + s[i]->s.k = off_linkpl.constant_part + off_nl; i++; /* MEM[reg2] = A */ s[i] = new_stmt(BPF_ST); @@ -5903,7 +5790,7 @@ gen_protochain(v, proto, dir) i++; /* A = P[X + packet head] */ s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); - s[i]->s.k = off_macpl + off_nl; + s[i]->s.k = off_linkpl.constant_part + off_nl; i++; /* A += 2 */ s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); @@ -5967,12 +5854,12 @@ gen_check_802_11_data_frame() * A data frame has the 0x08 bit (b3) in the frame control field set * and the 0x04 bit (b2) clear. */ - s = gen_load_a(OR_LINK, 0, BPF_B); + s = gen_load_a(OR_LINKHDR, 0, BPF_B); b0 = new_block(JMP(BPF_JSET)); b0->s.k = 0x08; b0->stmts = s; - s = gen_load_a(OR_LINK, 0, BPF_B); + s = gen_load_a(OR_LINKHDR, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; @@ -6031,7 +5918,7 @@ gen_proto(v, proto, dir) */ b0 = gen_linktype(ETHERTYPE_IP); #ifndef CHASE_CHAIN - b1 = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)v); + b1 = gen_cmp(OR_LINKPL, 9, BPF_B, (bpf_int32)v); #else b1 = gen_protochain(v, Q_IP); #endif @@ -6060,7 +5947,7 @@ gen_proto(v, proto, dir) * * XXX - what about SNAP-encapsulated frames? */ - return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | v); + return gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | v); /*NOTREACHED*/ break; @@ -6071,13 +5958,13 @@ gen_proto(v, proto, dir) */ b0 = gen_linktype(LLCSAP_ISONS<<8 | LLCSAP_ISONS); /* OSI in C-HDLC is stuffed with a fudge byte */ - b1 = gen_cmp(OR_NET_NOSNAP, 1, BPF_B, (long)v); + b1 = gen_cmp(OR_LINKPL_NOSNAP, 1, BPF_B, (long)v); gen_and(b0, b1); return b1; default: b0 = gen_linktype(LLCSAP_ISONS); - b1 = gen_cmp(OR_NET_NOSNAP, 0, BPF_B, (long)v); + b1 = gen_cmp(OR_LINKPL_NOSNAP, 0, BPF_B, (long)v); gen_and(b0, b1); return b1; } @@ -6088,7 +5975,7 @@ gen_proto(v, proto, dir) * 4 is the offset of the PDU type relative to the IS-IS * header. */ - b1 = gen_cmp(OR_NET_NOSNAP, 4, BPF_B, (long)v); + b1 = gen_cmp(OR_LINKPL_NOSNAP, 4, BPF_B, (long)v); gen_and(b0, b1); return b1; @@ -6170,10 +6057,10 @@ gen_proto(v, proto, dir) * Also check for a fragment header before the final * header. */ - b2 = gen_cmp(OR_NET, 6, BPF_B, IPPROTO_FRAGMENT); - b1 = gen_cmp(OR_NET, 40, BPF_B, (bpf_int32)v); + b2 = gen_cmp(OR_LINKPL, 6, BPF_B, IPPROTO_FRAGMENT); + b1 = gen_cmp(OR_LINKPL, 40, BPF_B, (bpf_int32)v); gen_and(b2, b1); - b2 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v); + b2 = gen_cmp(OR_LINKPL, 6, BPF_B, (bpf_int32)v); gen_or(b2, b1); #else b1 = gen_protochain(v, Q_IPV6); @@ -6258,7 +6145,10 @@ gen_scode(name, q) if (eaddr == NULL) bpf_error( "unknown ether host '%s'", name); + tmp = gen_prevlinkhdr_check(); b = gen_ehostop(eaddr, dir); + if (tmp != NULL) + gen_and(tmp, b); free(eaddr); return b; @@ -6301,28 +6191,6 @@ gen_scode(name, q) b = gen_ipfchostop(eaddr, dir); free(eaddr); return b; - - case DLT_SUNATM: - if (!is_lane) - break; - - /* - * Check that the packet doesn't begin - * with an LE Control marker. (We've - * already generated a test for LANE.) - */ - tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, - BPF_H, 0xFF00); - gen_not(tmp); - - eaddr = pcap_ether_hostton(name); - if (eaddr == NULL) - bpf_error( - "unknown ether host '%s'", name); - b = gen_ehostop(eaddr, dir); - gen_and(tmp, b); - free(eaddr); - return b; } bpf_error("only ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel supports link-level host name"); @@ -6339,7 +6207,8 @@ gen_scode(name, q) if (alist == NULL || *alist == NULL) bpf_error("unknown host '%s'", name); tproto = proto; - if (off_linktype == (u_int)-1 && tproto == Q_DEFAULT) + if (off_linktype.constant_part == (u_int)-1 && + tproto == Q_DEFAULT) tproto = Q_IP; b = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr); while (*alist) { @@ -6357,7 +6226,8 @@ gen_scode(name, q) ai = res; b = tmp = NULL; tproto = tproto6 = proto; - if (off_linktype == (u_int)-1 && tproto == Q_DEFAULT) { + if (off_linktype.constant_part == (u_int)-1 && + tproto == Q_DEFAULT) { tproto = Q_IP; tproto6 = Q_IPV6; } @@ -6530,7 +6400,7 @@ gen_scode(name, q) struct block * gen_mcode(s1, s2, masklen, q) register const char *s1, *s2; - register int masklen; + register unsigned int masklen; struct qual q; { register int nlen, mlen; @@ -6689,7 +6559,7 @@ gen_ncode(s, v, q) struct block * gen_mcode6(s1, s2, masklen, q) register const char *s1, *s2; - register int masklen; + register unsigned int masklen; struct qual q; { struct addrinfo *res; @@ -6759,7 +6629,11 @@ gen_ecode(eaddr, q) case DLT_EN10MB: case DLT_NETANALYZER: case DLT_NETANALYZER_TRANSPARENT: - return gen_ehostop(eaddr, (int)q.dir); + tmp = gen_prevlinkhdr_check(); + b = gen_ehostop(eaddr, (int)q.dir); + if (tmp != NULL) + gen_and(tmp, b); + return b; case DLT_FDDI: return gen_fhostop(eaddr, (int)q.dir); case DLT_IEEE802: @@ -6770,25 +6644,6 @@ gen_ecode(eaddr, q) case DLT_IEEE802_11_RADIO: case DLT_PPI: return gen_wlanhostop(eaddr, (int)q.dir); - case DLT_SUNATM: - if (is_lane) { - /* - * Check that the packet doesn't begin with an - * LE Control marker. (We've already generated - * a test for LANE.) - */ - tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, - 0xFF00); - gen_not(tmp); - - /* - * Now check the MAC address. - */ - b = gen_ehostop(eaddr, (int)q.dir); - gen_and(tmp, b); - return b; - } - break; case DLT_IP_OVER_FC: return gen_ipfchostop(eaddr, (int)q.dir); default: @@ -6912,7 +6767,7 @@ gen_load(proto, inst, size) * frame, so that 0 refers, for Ethernet LANE, to * the beginning of the destination address? */ - s = gen_llprefixlen(); + s = gen_abs_offset_varpart(&off_linkhdr); /* * If "s" is non-null, it has code to arrange that the @@ -6938,7 +6793,7 @@ gen_load(proto, inst, size) * into the X register and then added to the index). */ tmp = new_stmt(BPF_LD|BPF_IND|size); - tmp->s.k = off_ll; + tmp->s.k = off_linkhdr.constant_part; sappend(s, tmp); sappend(inst->s, s); break; @@ -6959,16 +6814,16 @@ gen_load(proto, inst, size) * XXX - are there any cases where we want * off_nl_nosnap? */ - s = gen_off_macpl(); + s = gen_abs_offset_varpart(&off_linkpl); /* * If "s" is non-null, it has code to arrange that the - * X register contains the offset of the MAC-layer - * payload. Add to it the offset computed into the - * register specified by "index", and move that into - * the X register. Otherwise, just load into the X - * register the offset computed into the register specified - * by "index". + * X register contains the variable part of the offset + * of the link-layer payload. Add to it the offset + * computed into the register specified by "index", + * and move that into the X register. Otherwise, just + * load into the X register the offset computed into + * the register specified by "index". */ if (s != NULL) { sappend(s, xfer_to_a(inst)); @@ -6980,17 +6835,12 @@ gen_load(proto, inst, size) /* * Load the item at the sum of the offset we've put in the * X register, the offset of the start of the network - * layer header from the beginning of the MAC-layer - * payload, and the purported offset of the start of the - * MAC-layer payload (which might be 0 if there's a - * variable-length prefix before the link-layer header - * or the link-layer header itself is variable-length; - * the variable-length offset of the start of the - * MAC-layer payload is what we put into the X register - * and then added to the index). + * layer header from the beginning of the link-layer + * payload, and the constant part of the offset of the + * start of the link-layer payload. */ tmp = new_stmt(BPF_LD|BPF_IND|size); - tmp->s.k = off_macpl + off_nl; + tmp->s.k = off_linkpl.constant_part + off_nl; sappend(s, tmp); sappend(inst->s, s); @@ -7030,26 +6880,24 @@ gen_load(proto, inst, size) s = gen_loadx_iphdrlen(); /* - * The X register now contains the sum of the length - * of any variable-length header preceding the link-layer - * header, any variable-length link-layer header, and the + * The X register now contains the sum of the variable + * part of the offset of the link-layer payload and the * length of the network-layer header. * * Load into the A register the offset relative to * the beginning of the transport layer header, * add the X register to that, move that to the * X register, and load with an offset from the - * X register equal to the offset of the network - * layer header relative to the beginning of - * the MAC-layer payload plus the fixed-length - * portion of the offset of the MAC-layer payload - * from the beginning of the raw packet data. + * X register equal to the sum of the constant part of + * the offset of the link-layer payload and the offset, + * relative to the beginning of the link-layer payload, + * of the network-layer header. */ sappend(s, xfer_to_a(inst)); sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); sappend(s, new_stmt(BPF_MISC|BPF_TAX)); sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size)); - tmp->s.k = off_macpl + off_nl; + tmp->s.k = off_linkpl.constant_part + off_nl; sappend(inst->s, s); /* @@ -7312,14 +7160,14 @@ gen_byteop(op, idx, val) abort(); case '=': - return gen_cmp(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val); + return gen_cmp(OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val); case '<': - b = gen_cmp_lt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val); + b = gen_cmp_lt(OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val); return b; case '>': - b = gen_cmp_gt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val); + b = gen_cmp_gt(OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val); return b; case '|': @@ -7359,7 +7207,11 @@ gen_broadcast(proto) case DLT_EN10MB: case DLT_NETANALYZER: case DLT_NETANALYZER_TRANSPARENT: - return gen_ehostop(ebroadcast, Q_DST); + b1 = gen_prevlinkhdr_check(); + b0 = gen_ehostop(ebroadcast, Q_DST); + if (b1 != NULL) + gen_and(b1, b0); + return b0; case DLT_FDDI: return gen_fhostop(ebroadcast, Q_DST); case DLT_IEEE802: @@ -7372,25 +7224,6 @@ gen_broadcast(proto) return gen_wlanhostop(ebroadcast, Q_DST); case DLT_IP_OVER_FC: return gen_ipfchostop(ebroadcast, Q_DST); - case DLT_SUNATM: - if (is_lane) { - /* - * Check that the packet doesn't begin with an - * LE Control marker. (We've already generated - * a test for LANE.) - */ - b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, - BPF_H, 0xFF00); - gen_not(b1); - - /* - * Now check the MAC address. - */ - b0 = gen_ehostop(ebroadcast, Q_DST); - gen_and(b1, b0); - return b0; - } - break; default: bpf_error("not a broadcast link"); } @@ -7406,8 +7239,8 @@ gen_broadcast(proto) bpf_error("netmask not known, so 'ip broadcast' not supported"); b0 = gen_linktype(ETHERTYPE_IP); hostmask = ~netmask; - b1 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32)0, hostmask); - b2 = gen_mcmp(OR_NET, 16, BPF_W, + b1 = gen_mcmp(OR_LINKPL, 16, BPF_W, (bpf_int32)0, hostmask); + b2 = gen_mcmp(OR_LINKPL, 16, BPF_W, (bpf_int32)(~0 & hostmask), hostmask); gen_or(b1, b2); gen_and(b0, b2); @@ -7430,7 +7263,7 @@ gen_mac_multicast(offset) register struct slist *s; /* link[offset] & 1 != 0 */ - s = gen_load_a(OR_LINK, offset, BPF_B); + s = gen_load_a(OR_LINKHDR, offset, BPF_B); b0 = new_block(JMP(BPF_JSET)); b0->s.k = 1; b0->stmts = s; @@ -7456,8 +7289,12 @@ gen_multicast(proto) case DLT_EN10MB: case DLT_NETANALYZER: case DLT_NETANALYZER_TRANSPARENT: + b1 = gen_prevlinkhdr_check(); /* ether[0] & 1 != 0 */ - return gen_mac_multicast(0); + b0 = gen_mac_multicast(0); + if (b1 != NULL) + gen_and(b1, b0); + return b0; case DLT_FDDI: /* * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX @@ -7495,7 +7332,7 @@ gen_multicast(proto) * * First, check for To DS set, i.e. "link[1] & 0x01". */ - s = gen_load_a(OR_LINK, 1, BPF_B); + s = gen_load_a(OR_LINKHDR, 1, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x01; /* To DS */ b1->stmts = s; @@ -7510,7 +7347,7 @@ gen_multicast(proto) * Now, check for To DS not set, i.e. check * "!(link[1] & 0x01)". */ - s = gen_load_a(OR_LINK, 1, BPF_B); + s = gen_load_a(OR_LINKHDR, 1, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x01; /* To DS */ b2->stmts = s; @@ -7532,7 +7369,7 @@ gen_multicast(proto) * Now check for a data frame. * I.e, check "link[0] & 0x08". */ - s = gen_load_a(OR_LINK, 0, BPF_B); + s = gen_load_a(OR_LINKHDR, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x08; b1->stmts = s; @@ -7547,7 +7384,7 @@ gen_multicast(proto) * is a management frame. * I.e, check "!(link[0] & 0x08)". */ - s = gen_load_a(OR_LINK, 0, BPF_B); + s = gen_load_a(OR_LINKHDR, 0, BPF_B); b2 = new_block(JMP(BPF_JSET)); b2->s.k = 0x08; b2->stmts = s; @@ -7574,7 +7411,7 @@ gen_multicast(proto) * * I.e., check "!(link[0] & 0x04)". */ - s = gen_load_a(OR_LINK, 0, BPF_B); + s = gen_load_a(OR_LINKHDR, 0, BPF_B); b1 = new_block(JMP(BPF_JSET)); b1->s.k = 0x04; b1->stmts = s; @@ -7589,23 +7426,6 @@ gen_multicast(proto) case DLT_IP_OVER_FC: b0 = gen_mac_multicast(2); return b0; - case DLT_SUNATM: - if (is_lane) { - /* - * Check that the packet doesn't begin with an - * LE Control marker. (We've already generated - * a test for LANE.) - */ - b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, - BPF_H, 0xFF00); - gen_not(b1); - - /* ether[off_mac] & 1 != 0 */ - b0 = gen_mac_multicast(off_mac); - gen_and(b1, b0); - return b0; - } - break; default: break; } @@ -7614,13 +7434,13 @@ gen_multicast(proto) case Q_IP: b0 = gen_linktype(ETHERTYPE_IP); - b1 = gen_cmp_ge(OR_NET, 16, BPF_B, (bpf_int32)224); + b1 = gen_cmp_ge(OR_LINKPL, 16, BPF_B, (bpf_int32)224); gen_and(b0, b1); return b1; case Q_IPV6: b0 = gen_linktype(ETHERTYPE_IPV6); - b1 = gen_cmp(OR_NET, 24, BPF_B, (bpf_int32)255); + b1 = gen_cmp(OR_LINKPL, 24, BPF_B, (bpf_int32)255); gen_and(b0, b1); return b1; } @@ -7658,16 +7478,16 @@ gen_inbound(dir) case DLT_IPNET: if (dir) { /* match outgoing packets */ - b0 = gen_cmp(OR_LINK, 2, BPF_H, IPNET_OUTBOUND); + b0 = gen_cmp(OR_LINKHDR, 2, BPF_H, IPNET_OUTBOUND); } else { /* match incoming packets */ - b0 = gen_cmp(OR_LINK, 2, BPF_H, IPNET_INBOUND); + b0 = gen_cmp(OR_LINKHDR, 2, BPF_H, IPNET_INBOUND); } break; case DLT_LINUX_SLL: /* match outgoing packets */ - b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING); + b0 = gen_cmp(OR_LINKHDR, 0, BPF_H, LINUX_SLL_OUTGOING); if (!dir) { /* to filter on inbound traffic, invert the match */ gen_not(b0); @@ -7676,7 +7496,7 @@ gen_inbound(dir) #ifdef HAVE_NET_PFVAR_H case DLT_PFLOG: - b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, dir), BPF_B, + b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, dir), BPF_B, (bpf_int32)((dir == 0) ? PF_IN : PF_OUT)); break; #endif @@ -7684,10 +7504,10 @@ gen_inbound(dir) case DLT_PPP_PPPD: if (dir) { /* match outgoing packets */ - b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_OUT); + b0 = gen_cmp(OR_LINKHDR, 0, BPF_B, PPP_PPPD_OUT); } else { /* match incoming packets */ - b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_IN); + b0 = gen_cmp(OR_LINKHDR, 0, BPF_B, PPP_PPPD_IN); } break; @@ -7718,10 +7538,10 @@ gen_inbound(dir) * the byte after the 3-byte magic number */ if (dir) { /* match outgoing packets */ - b0 = gen_mcmp(OR_LINK, 3, BPF_B, 0, 0x01); + b0 = gen_mcmp(OR_LINKHDR, 3, BPF_B, 0, 0x01); } else { /* match incoming packets */ - b0 = gen_mcmp(OR_LINK, 3, BPF_B, 1, 0x01); + b0 = gen_mcmp(OR_LINKHDR, 3, BPF_B, 1, 0x01); } break; @@ -7746,7 +7566,7 @@ gen_inbound(dir) /* NOTREACHED */ } /* match outgoing packets */ - b0 = gen_cmp(OR_LINK, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H, + b0 = gen_cmp(OR_LINKHDR, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H, PACKET_OUTGOING); if (!dir) { /* to filter on inbound traffic, invert the match */ @@ -7781,7 +7601,7 @@ gen_pf_ifname(const char *ifname) len-1); /* NOTREACHED */ } - b0 = gen_bcmp(OR_LINK, off, strlen(ifname), (const u_char *)ifname); + b0 = gen_bcmp(OR_LINKHDR, off, strlen(ifname), (const u_char *)ifname); return (b0); } @@ -7802,7 +7622,7 @@ gen_pf_ruleset(char *ruleset) /* NOTREACHED */ } - b0 = gen_bcmp(OR_LINK, offsetof(struct pfloghdr, ruleset), + b0 = gen_bcmp(OR_LINKHDR, offsetof(struct pfloghdr, ruleset), strlen(ruleset), (const u_char *)ruleset); return (b0); } @@ -7818,7 +7638,7 @@ gen_pf_rnr(int rnr) /* NOTREACHED */ } - b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, rulenr), BPF_W, + b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, rulenr), BPF_W, (bpf_int32)rnr); return (b0); } @@ -7834,7 +7654,7 @@ gen_pf_srnr(int srnr) /* NOTREACHED */ } - b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, subrulenr), BPF_W, + b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, subrulenr), BPF_W, (bpf_int32)srnr); return (b0); } @@ -7850,7 +7670,7 @@ gen_pf_reason(int reason) /* NOTREACHED */ } - b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, reason), BPF_B, + b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, reason), BPF_B, (bpf_int32)reason); return (b0); } @@ -7866,7 +7686,7 @@ gen_pf_action(int action) /* NOTREACHED */ } - b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, action), BPF_B, + b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, action), BPF_B, (bpf_int32)action); return (b0); } @@ -7932,7 +7752,7 @@ gen_p80211_type(int type, int mask) case DLT_PRISM_HEADER: case DLT_IEEE802_11_RADIO_AVS: case DLT_IEEE802_11_RADIO: - b0 = gen_mcmp(OR_LINK, 0, BPF_B, (bpf_int32)type, + b0 = gen_mcmp(OR_LINKHDR, 0, BPF_B, (bpf_int32)type, (bpf_int32)mask); break; @@ -7962,7 +7782,7 @@ gen_p80211_fcdir(int fcdir) /* NOTREACHED */ } - b0 = gen_mcmp(OR_LINK, 1, BPF_B, (bpf_int32)fcdir, + b0 = gen_mcmp(OR_LINKHDR, 1, BPF_B, (bpf_int32)fcdir, (bpf_u_int32)IEEE80211_FC1_DIR_MASK); return (b0); @@ -8005,10 +7825,10 @@ gen_ahostop(eaddr, dir) switch (dir) { /* src comes first, different from Ethernet */ case Q_SRC: - return gen_bcmp(OR_LINK, 0, 1, eaddr); + return gen_bcmp(OR_LINKHDR, 0, 1, eaddr); case Q_DST: - return gen_bcmp(OR_LINK, 1, 1, eaddr); + return gen_bcmp(OR_LINKHDR, 1, 1, eaddr); case Q_AND: b0 = gen_ahostop(eaddr, Q_SRC); @@ -8051,6 +7871,72 @@ gen_ahostop(eaddr, dir) /* NOTREACHED */ } +#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT) +static struct block * +gen_vlan_bpf_extensions(int vlan_num) +{ + struct block *b0, *b1; + struct slist *s; + + /* generate new filter code based on extracting packet + * metadata */ + s = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT; + + b0 = new_block(JMP(BPF_JEQ)); + b0->stmts = s; + b0->s.k = 1; + + if (vlan_num >= 0) { + s = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG; + + b1 = new_block(JMP(BPF_JEQ)); + b1->stmts = s; + b1->s.k = (bpf_int32) vlan_num; + + gen_and(b0,b1); + b0 = b1; + } + + return b0; +} +#endif + +static struct block * +gen_vlan_no_bpf_extensions(int vlan_num) +{ + struct block *b0, *b1; + + /* check for VLAN, including QinQ */ + b0 = gen_linktype(ETHERTYPE_8021Q); + b1 = gen_linktype(ETHERTYPE_8021QINQ); + gen_or(b0,b1); + b0 = b1; + + /* If a specific VLAN is requested, check VLAN id */ + if (vlan_num >= 0) { + b1 = gen_mcmp(OR_LINKPL, 0, BPF_H, + (bpf_int32)vlan_num, 0x0fff); + gen_and(b0, b1); + b0 = b1; + } + + /* + * The payload follows the full header, including the + * VLAN tags, so skip past this VLAN tag. + */ + off_linkpl.constant_part += 4; + + /* + * The link-layer type information follows the VLAN tags, so + * skip past this VLAN tag. + */ + off_linktype.constant_part += 4; + + return b0; +} + /* * support IEEE 802.1Q VLAN trunk over ethernet */ @@ -8058,7 +7944,7 @@ struct block * gen_vlan(vlan_num) int vlan_num; { - struct block *b0, *b1; + struct block *b0; /* can't check for VLAN-encapsulated packets inside MPLS */ if (label_stack_depth > 0) @@ -8095,35 +7981,34 @@ gen_vlan(vlan_num) * be done assuming a VLAN, even though the "or" could be viewed * as meaning "or, if this isn't a VLAN packet...". */ - orig_nl = off_nl; - switch (linktype) { case DLT_EN10MB: case DLT_NETANALYZER: case DLT_NETANALYZER_TRANSPARENT: - /* check for VLAN, including QinQ */ - b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, - (bpf_int32)ETHERTYPE_8021Q); - b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, - (bpf_int32)ETHERTYPE_8021QINQ); - gen_or(b0,b1); - b0 = b1; - - /* If a specific VLAN is requested, check VLAN id */ - if (vlan_num >= 0) { - b1 = gen_mcmp(OR_MACPL, 0, BPF_H, - (bpf_int32)vlan_num, 0x0fff); - gen_and(b0, b1); - b0 = b1; - } - - off_macpl += 4; - off_linktype += 4; -#if 0 - off_nl_nosnap += 4; - off_nl += 4; +#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT) + /* Verify that this is the outer part of the packet and + * not encapsulated somehow. */ + if (vlan_stack_depth == 0 && !off_linkhdr.is_variable && + off_linkhdr.constant_part == + off_outermostlinkhdr.constant_part) { + /* + * Do we need special VLAN handling? + */ + if (bpf_pcap->bpf_codegen_flags & BPF_SPECIAL_VLAN_HANDLING) + b0 = gen_vlan_bpf_extensions(vlan_num); + else + b0 = gen_vlan_no_bpf_extensions(vlan_num); + } else #endif + b0 = gen_vlan_no_bpf_extensions(vlan_num); + break; + + case DLT_IEEE802_11: + case DLT_PRISM_HEADER: + case DLT_IEEE802_11_RADIO_AVS: + case DLT_IEEE802_11_RADIO: + b0 = gen_vlan_no_bpf_extensions(vlan_num); break; default: @@ -8132,6 +8017,8 @@ gen_vlan(vlan_num) /*NOTREACHED*/ } + vlan_stack_depth++; + return (b0); } @@ -8142,28 +8029,15 @@ struct block * gen_mpls(label_num) int label_num; { - struct block *b0,*b1; - - /* - * Change the offsets to point to the type and data fields within - * the MPLS packet. Just increment the offsets, so that we - * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to - * capture packets with an outer label of 100000 and an inner - * label of 1024. - * - * XXX - this is a bit of a kludge. See comments in gen_vlan(). - */ - orig_nl = off_nl; + struct block *b0, *b1; if (label_stack_depth > 0) { /* just match the bottom-of-stack bit clear */ - b0 = gen_mcmp(OR_MACPL, orig_nl-2, BPF_B, 0, 0x01); + b0 = gen_mcmp(OR_PREVMPLSHDR, 2, BPF_B, 0, 0x01); } else { /* - * Indicate that we're checking MPLS-encapsulated headers, - * to make sure higher level code generators don't try to - * match against IP-related protocols such as Q_ARP, Q_RARP - * etc. + * We're not in an MPLS stack yet, so check the link-layer + * type against MPLS. */ switch (linktype) { @@ -8194,12 +8068,26 @@ gen_mpls(label_num) /* If a specific MPLS label is requested, check it */ if (label_num >= 0) { label_num = label_num << 12; /* label is shifted 12 bits on the wire */ - b1 = gen_mcmp(OR_MACPL, orig_nl, BPF_W, (bpf_int32)label_num, + b1 = gen_mcmp(OR_LINKPL, 0, BPF_W, (bpf_int32)label_num, 0xfffff000); /* only compare the first 20 bits */ gen_and(b0, b1); b0 = b1; } + /* + * Change the offsets to point to the type and data fields within + * the MPLS packet. Just increment the offsets, so that we + * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to + * capture packets with an outer label of 100000 and an inner + * label of 1024. + * + * Increment the MPLS stack depth as well; this indicates that + * we're checking MPLS-encapsulated headers, to make sure higher + * level code generators don't try to match against IP-related + * protocols such as Q_ARP, Q_RARP etc. + * + * XXX - this is a bit of a kludge. See comments in gen_vlan(). + */ off_nl_nosnap += 4; off_nl += 4; label_stack_depth++; @@ -8227,6 +8115,14 @@ gen_pppoes(sess_num) */ b0 = gen_linktype((bpf_int32)ETHERTYPE_PPPOES); + /* If a specific session is requested, check PPPoE session id */ + if (sess_num >= 0) { + b1 = gen_mcmp(OR_LINKPL, 0, BPF_W, + (bpf_int32)sess_num, 0x0000ffff); + gen_and(b0, b1); + b0 = b1; + } + /* * Change the offsets to point to the type and data fields within * the PPP packet, and note that this is PPPoE rather than @@ -8255,20 +8151,7 @@ gen_pppoes(sess_num) * as all the "or ..." tests would be done assuming PPPoE, even * though the "or" could be viewed as meaning "or, if this isn't * a PPPoE packet...". - */ - orig_linktype = off_linktype; /* save original values */ - orig_nl = off_nl; - is_pppoes = 1; - - /* If a specific session is requested, check PPPoE session id */ - if (sess_num >= 0) { - b1 = gen_mcmp(OR_MACPL, orig_nl, BPF_W, - (bpf_int32)sess_num, 0x0000ffff); - gen_and(b0, b1); - b0 = b1; - } - - /* + * * The "network-layer" protocol is PPPoE, which has a 6-byte * PPPoE header, followed by a PPP packet. * @@ -8279,15 +8162,309 @@ gen_pppoes(sess_num) * link-layer payload, including any 802.2 LLC header, so * it's 6 bytes past off_nl. */ - off_linktype = off_nl + 6; + PUSH_LINKHDR(DLT_PPP, off_linkpl.is_variable, + off_linkpl.constant_part + off_nl + 6, /* 6 bytes past the PPPoE header */ + off_linkpl.reg); - /* - * The network-layer offsets are relative to the beginning - * of the MAC-layer payload; that's past the 6-byte - * PPPoE header and the 2-byte PPP header. - */ - off_nl = 6+2; - off_nl_nosnap = 6+2; + off_linktype = off_linkhdr; + off_linkpl.constant_part = off_linkhdr.constant_part + 2; + + off_nl = 0; + off_nl_nosnap = 0; /* no 802.2 LLC */ + + return b0; +} + +/* Check that this is Geneve and the VNI is correct if + * specified. Parameterized to handle both IPv4 and IPv6. */ +static struct block * +gen_geneve_check(struct block *(*gen_portfn)(int, int, int), + enum e_offrel offrel, int vni) +{ + struct block *b0, *b1; + + b0 = gen_portfn(GENEVE_PORT, IPPROTO_UDP, Q_DST); + + /* Check that we are operating on version 0. Otherwise, we + * can't decode the rest of the fields. The version is 2 bits + * in the first byte of the Geneve header. */ + b1 = gen_mcmp(offrel, 8, BPF_B, (bpf_int32)0, 0xc0); + gen_and(b0, b1); + b0 = b1; + + if (vni >= 0) { + vni <<= 8; /* VNI is in the upper 3 bytes */ + b1 = gen_mcmp(offrel, 12, BPF_W, (bpf_int32)vni, + 0xffffff00); + gen_and(b0, b1); + b0 = b1; + } + + return b0; +} + +/* The IPv4 and IPv6 Geneve checks need to do two things: + * - Verify that this actually is Geneve with the right VNI. + * - Place the IP header length (plus variable link prefix if + * needed) into register A to be used later to compute + * the inner packet offsets. */ +static struct block * +gen_geneve4(int vni) +{ + struct block *b0, *b1; + struct slist *s, *s1; + + b0 = gen_geneve_check(gen_port, OR_TRAN_IPV4, vni); + + /* Load the IP header length into A. */ + s = gen_loadx_iphdrlen(); + + s1 = new_stmt(BPF_MISC|BPF_TXA); + sappend(s, s1); + + /* Forcibly append these statements to the true condition + * of the protocol check by creating a new block that is + * always true and ANDing them. */ + b1 = new_block(BPF_JMP|BPF_JEQ|BPF_X); + b1->stmts = s; + b1->s.k = 0; + + gen_and(b0, b1); + + return b1; +} + +static struct block * +gen_geneve6(int vni) +{ + struct block *b0, *b1; + struct slist *s, *s1; + + b0 = gen_geneve_check(gen_port6, OR_TRAN_IPV6, vni); + + /* Load the IP header length. We need to account for a + * variable length link prefix if there is one. */ + s = gen_abs_offset_varpart(&off_linkpl); + if (s) { + s1 = new_stmt(BPF_LD|BPF_IMM); + s1->s.k = 40; + sappend(s, s1); + + s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_X); + s1->s.k = 0; + sappend(s, s1); + } else { + s = new_stmt(BPF_LD|BPF_IMM); + s->s.k = 40;; + } + + /* Forcibly append these statements to the true condition + * of the protocol check by creating a new block that is + * always true and ANDing them. */ + s1 = new_stmt(BPF_MISC|BPF_TAX); + sappend(s, s1); + + b1 = new_block(BPF_JMP|BPF_JEQ|BPF_X); + b1->stmts = s; + b1->s.k = 0; + + gen_and(b0, b1); + + return b1; +} + +/* We need to store three values based on the Geneve header:: + * - The offset of the linktype. + * - The offset of the end of the Geneve header. + * - The offset of the end of the encapsulated MAC header. */ +static struct slist * +gen_geneve_offsets(void) +{ + struct slist *s, *s1, *s_proto; + + /* First we need to calculate the offset of the Geneve header + * itself. This is composed of the IP header previously calculated + * (include any variable link prefix) and stored in A plus the + * fixed sized headers (fixed link prefix, MAC length, and UDP + * header). */ + s = new_stmt(BPF_ALU|BPF_ADD|BPF_K); + s->s.k = off_linkpl.constant_part + off_nl + 8; + + /* Stash this in X since we'll need it later. */ + s1 = new_stmt(BPF_MISC|BPF_TAX); + sappend(s, s1); + + /* The EtherType in Geneve is 2 bytes in. Calculate this and + * store it. */ + s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_K); + s1->s.k = 2; + sappend(s, s1); + + off_linktype.reg = alloc_reg(); + off_linktype.is_variable = 1; + off_linktype.constant_part = 0; + + s1 = new_stmt(BPF_ST); + s1->s.k = off_linktype.reg; + sappend(s, s1); + + /* Load the Geneve option length and mask and shift to get the + * number of bytes. It is stored in the first byte of the Geneve + * header. */ + s1 = new_stmt(BPF_LD|BPF_IND|BPF_B); + s1->s.k = 0; + sappend(s, s1); + + s1 = new_stmt(BPF_ALU|BPF_AND|BPF_K); + s1->s.k = 0x3f; + sappend(s, s1); + + s1 = new_stmt(BPF_ALU|BPF_MUL|BPF_K); + s1->s.k = 4; + sappend(s, s1); + + /* Add in the rest of the Geneve base header. */ + s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_K); + s1->s.k = 8; + sappend(s, s1); + + /* Add the Geneve header length to its offset and store. */ + s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_X); + s1->s.k = 0; + sappend(s, s1); + + /* Set the encapsulated type as Ethernet. Even though we may + * not actually have Ethernet inside there are two reasons this + * is useful: + * - The linktype field is always in EtherType format regardless + * of whether it is in Geneve or an inner Ethernet frame. + * - The only link layer that we have specific support for is + * Ethernet. We will confirm that the packet actually is + * Ethernet at runtime before executing these checks. */ + PUSH_LINKHDR(DLT_EN10MB, 1, 0, alloc_reg()); + + s1 = new_stmt(BPF_ST); + s1->s.k = off_linkhdr.reg; + sappend(s, s1); + + /* Calculate whether we have an Ethernet header or just raw IP/ + * MPLS/etc. If we have Ethernet, advance the end of the MAC offset + * and linktype by 14 bytes so that the network header can be found + * seamlessly. Otherwise, keep what we've calculated already. */ + + /* We have a bare jmp so we can't use the optimizer. */ + no_optimize = 1; + + /* Load the EtherType in the Geneve header, 2 bytes in. */ + s1 = new_stmt(BPF_LD|BPF_IND|BPF_H); + s1->s.k = 2; + sappend(s, s1); + + /* Load X with the end of the Geneve header. */ + s1 = new_stmt(BPF_LDX|BPF_MEM); + s1->s.k = off_linkhdr.reg; + sappend(s, s1); + + /* Check if the EtherType is Transparent Ethernet Bridging. At the + * end of this check, we should have the total length in X. In + * the non-Ethernet case, it's already there. */ + s_proto = new_stmt(JMP(BPF_JEQ)); + s_proto->s.k = ETHERTYPE_TEB; + sappend(s, s_proto); + + s1 = new_stmt(BPF_MISC|BPF_TXA); + sappend(s, s1); + s_proto->s.jt = s1; + + /* Since this is Ethernet, use the EtherType of the payload + * directly as the linktype. Overwrite what we already have. */ + s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_K); + s1->s.k = 12; + sappend(s, s1); + + s1 = new_stmt(BPF_ST); + s1->s.k = off_linktype.reg; + sappend(s, s1); + + /* Advance two bytes further to get the end of the Ethernet + * header. */ + s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_K); + s1->s.k = 2; + sappend(s, s1); + + /* Move the result to X. */ + s1 = new_stmt(BPF_MISC|BPF_TAX); + sappend(s, s1); + + /* Store the final result of our linkpl calculation. */ + off_linkpl.reg = alloc_reg(); + off_linkpl.is_variable = 1; + off_linkpl.constant_part = 0; + + s1 = new_stmt(BPF_STX); + s1->s.k = off_linkpl.reg; + sappend(s, s1); + s_proto->s.jf = s1; + + off_nl = 0; + + return s; +} + +/* Check to see if this is a Geneve packet. */ +struct block * +gen_geneve(int vni) +{ + struct block *b0, *b1; + struct slist *s; + + b0 = gen_geneve4(vni); + b1 = gen_geneve6(vni); + + gen_or(b0, b1); + b0 = b1; + + /* Later filters should act on the payload of the Geneve frame, + * update all of the header pointers. Attach this code so that + * it gets executed in the event that the Geneve filter matches. */ + s = gen_geneve_offsets(); + + b1 = gen_true(); + sappend(s, b1->stmts); + b1->stmts = s; + + gen_and(b0, b1); + + is_geneve = 1; + + return b1; +} + +/* Check that the encapsulated frame has a link layer header + * for Ethernet filters. */ +static struct block * +gen_geneve_ll_check() +{ + struct block *b0; + struct slist *s, *s1; + + /* The easiest way to see if there is a link layer present + * is to check if the link layer header and payload are not + * the same. */ + + /* Geneve always generates pure variable offsets so we can + * compare only the registers. */ + s = new_stmt(BPF_LD|BPF_MEM); + s->s.k = off_linkhdr.reg; + + s1 = new_stmt(BPF_LDX|BPF_MEM); + s1->s.k = off_linkpl.reg; + sappend(s, s1); + + b0 = new_block(BPF_JMP|BPF_JEQ|BPF_X); + b0->stmts = s; + b0->s.k = 0; + gen_not(b0); return b0; } @@ -8308,7 +8485,7 @@ gen_atmfield_code(atmfield, jvalue, jtype, reverse) bpf_error("'vpi' supported only on raw ATM"); if (off_vpi == (u_int)-1) abort(); - b0 = gen_ncmp(OR_LINK, off_vpi, BPF_B, 0xffffffff, jtype, + b0 = gen_ncmp(OR_LINKHDR, off_vpi, BPF_B, 0xffffffff, jtype, reverse, jvalue); break; @@ -8317,21 +8494,21 @@ gen_atmfield_code(atmfield, jvalue, jtype, reverse) bpf_error("'vci' supported only on raw ATM"); if (off_vci == (u_int)-1) abort(); - b0 = gen_ncmp(OR_LINK, off_vci, BPF_H, 0xffffffff, jtype, + b0 = gen_ncmp(OR_LINKHDR, off_vci, BPF_H, 0xffffffff, jtype, reverse, jvalue); break; case A_PROTOTYPE: if (off_proto == (u_int)-1) abort(); /* XXX - this isn't on FreeBSD */ - b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0x0f, jtype, + b0 = gen_ncmp(OR_LINKHDR, off_proto, BPF_B, 0x0f, jtype, reverse, jvalue); break; case A_MSGTYPE: if (off_payload == (u_int)-1) abort(); - b0 = gen_ncmp(OR_LINK, off_payload + MSG_TYPE_POS, BPF_B, + b0 = gen_ncmp(OR_LINKHDR, off_payload + MSG_TYPE_POS, BPF_B, 0xffffffff, jtype, reverse, jvalue); break; @@ -8340,7 +8517,7 @@ gen_atmfield_code(atmfield, jvalue, jtype, reverse) bpf_error("'callref' supported only on raw ATM"); if (off_proto == (u_int)-1) abort(); - b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0xffffffff, + b0 = gen_ncmp(OR_LINKHDR, off_proto, BPF_B, 0xffffffff, jtype, reverse, jvalue); break; @@ -8424,16 +8601,13 @@ gen_atmtype_abbrev(type) * the offsets appropriately for LANE-encapsulated * Ethernet. * - * "off_mac" is the offset of the Ethernet header, - * which is 2 bytes past the ATM pseudo-header - * (skipping the pseudo-header and 2-byte LE Client - * field). The other offsets are Ethernet offsets - * relative to "off_mac". + * We assume LANE means Ethernet, not Token Ring. */ - is_lane = 1; - off_mac = off_payload + 2; /* MAC header */ - off_linktype = off_mac + 12; - off_macpl = off_mac + 14; /* Ethernet */ + PUSH_LINKHDR(DLT_EN10MB, 0, + off_payload + 2, /* Ethernet header */ + -1); + off_linktype.constant_part = off_linkhdr.constant_part + 12; + off_linkpl.constant_part = off_linkhdr.constant_part + 14; /* Ethernet */ off_nl = 0; /* Ethernet II */ off_nl_nosnap = 3; /* 802.3+802.2 */ break; @@ -8443,7 +8617,7 @@ gen_atmtype_abbrev(type) if (!is_atm) bpf_error("'llc' supported only on raw ATM"); b1 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0); - is_lane = 0; + linktype = prevlinktype; break; default: diff --git a/external/bsd/libpcap/dist/gencode.h b/external/bsd/libpcap/dist/gencode.h index ef723dc2d251..ed352d1f74ab 100644 --- a/external/bsd/libpcap/dist/gencode.h +++ b/external/bsd/libpcap/dist/gencode.h @@ -1,4 +1,4 @@ -/* $NetBSD: gencode.h,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: gencode.h,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 @@ -163,7 +163,7 @@ #define A_CONNECTACK 44 /* Connect Ack message */ #define A_RELEASE 45 /* Release message */ #define A_RELEASE_DONE 46 /* Release message */ - + /* ATM field types */ #define A_VPI 51 #define A_VCI 52 @@ -296,9 +296,9 @@ void gen_not(struct block *); struct block *gen_scode(const char *, struct qual); struct block *gen_ecode(const u_char *, struct qual); struct block *gen_acode(const u_char *, struct qual); -struct block *gen_mcode(const char *, const char *, int, struct qual); +struct block *gen_mcode(const char *, const char *, unsigned int, struct qual); #ifdef INET6 -struct block *gen_mcode6(const char *, const char *, int, struct qual); +struct block *gen_mcode6(const char *, const char *, unsigned int, struct qual); #endif struct block *gen_ncode(const char *, bpf_u_int32, struct qual); struct block *gen_proto_abbrev(int); @@ -323,6 +323,8 @@ struct block *gen_mpls(int); struct block *gen_pppoed(void); struct block *gen_pppoes(int); +struct block *gen_geneve(int); + struct block *gen_atmfield_code(int atmfield, bpf_int32 jvalue, bpf_u_int32 jtype, int reverse); struct block *gen_atmtype_abbrev(int type); struct block *gen_atmmulti_abbrev(int type); diff --git a/external/bsd/libpcap/dist/grammar.y b/external/bsd/libpcap/dist/grammar.y index 005dc9a897e4..3f3ec29ed6b4 100644 --- a/external/bsd/libpcap/dist/grammar.y +++ b/external/bsd/libpcap/dist/grammar.y @@ -1,4 +1,4 @@ -/* $NetBSD: grammar.y,v 1.5 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: grammar.y,v 1.6 2015/03/31 21:39:42 christos Exp $ */ %{ /* @@ -23,7 +23,7 @@ * */ #include -__RCSID("$NetBSD: grammar.y,v 1.5 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: grammar.y,v 1.6 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -303,8 +303,8 @@ pfaction_to_num(const char *action) %token LEN %token IPV6 ICMPV6 AH ESP %token VLAN MPLS -%token PPPOED PPPOES -%token ISO ESIS CLNP ISIS L1 L2 IIH LSP SNP CSNP PSNP +%token PPPOED PPPOES GENEVE +%token ISO ESIS CLNP ISIS L1 L2 IIH LSP SNP CSNP PSNP %token STP %token IPX %token NETBEUI @@ -314,7 +314,7 @@ pfaction_to_num(const char *action) %token RADIO %token FISU LSSU MSU HFISU HLSSU HMSU %token SIO OPC DPC SLS HSIO HOPC HDPC HSLS - + %type ID %type EID @@ -390,7 +390,7 @@ nid: ID { $$.b = gen_scode($1, $$.q = $0.q); } "in this configuration"); #endif /*INET6*/ } - | EID { + | EID { $$.b = gen_ecode($1, $$.q = $0.q); /* * $1 was allocated by "pcap_ether_aton()", @@ -527,6 +527,8 @@ other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } | PPPOED { $$ = gen_pppoed(); } | PPPOES pnum { $$ = gen_pppoes($2); } | PPPOES { $$ = gen_pppoes(-1); } + | GENEVE pnum { $$ = gen_geneve($2); } + | GENEVE { $$ = gen_geneve(-1); } | pfvar { $$ = $1; } | pqual p80211 { $$ = $2; } | pllc { $$ = $1; } diff --git a/external/bsd/libpcap/dist/inet.c b/external/bsd/libpcap/dist/inet.c index f3fc836d19fd..f14ea1d1735d 100644 --- a/external/bsd/libpcap/dist/inet.c +++ b/external/bsd/libpcap/dist/inet.c @@ -1,4 +1,4 @@ -/* $NetBSD: inet.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: inet.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* @@ -35,7 +35,7 @@ */ #include -__RCSID("$NetBSD: inet.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: inet.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -577,7 +577,8 @@ get_if_description(const char *name) * Try to get a description for a given device, and then look for that * device in the specified list of devices. * - * If we find it, add the specified address to it and return 0. + * If we find it, then, if the specified address isn't null, add it to + * the list of addresses for the device and return 0. * * If we don't find it, check whether we can open it: * @@ -588,9 +589,17 @@ get_if_description(const char *name) * * Otherwise, attempt to add an entry for it, with the specified * ifnet flags and description, and, if that succeeds, add the - * specified address to it, set *curdev_ret to point to the new - * entry, and return 0, otherwise return PCAP_ERROR and set errbuf - * to an error message. + * specified address to its list of addresses if that address is + * non-null, set *curdev_ret to point to the new entry, and + * return 0, otherwise return PCAP_ERROR and set errbuf to an + * error message. + * + * (We can get called with a null address because we might get a list + * of interface name/address combinations from the underlying OS, with + * the address being absent in some cases, rather than a list of + * interfaces with each interface having a list of addresses, so this + * call may be the only call made to add to the list, and we want to + * add interfaces even if they have no addresses.) */ int add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags, @@ -621,14 +630,24 @@ add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags, return (0); } + if (addr == NULL) { + /* + * There's no address to add; this entry just meant + * "here's a new interface". + */ + return (0); + } + /* - * "curdev" is an entry for this interface; add an entry for this - * address to its list of addresses. + * "curdev" is an entry for this interface, and we have an + * address for it; add an entry for that address to the + * interface's list of addresses. * * Allocate the new entry and fill it in. */ - return (add_addr_to_dev(curdev, addr, addr_size, netmask, netmask_size, - broadaddr, broadaddr_size, dstaddr, dstaddr_size, errbuf)); + return (add_addr_to_dev(curdev, addr, addr_size, netmask, + netmask_size, broadaddr, broadaddr_size, dstaddr, + dstaddr_size, errbuf)); } /* @@ -910,7 +929,7 @@ pcap_lookupnet(device, netp, maskp, errbuf) /* XXX Work around Linux kernel bug */ ifr.ifr_addr.sa_family = AF_INET; #endif - (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + (void)strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { if (errno == EADDRNOTAVAIL) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, @@ -930,7 +949,7 @@ pcap_lookupnet(device, netp, maskp, errbuf) /* XXX Work around Linux kernel bug */ ifr.ifr_addr.sa_family = AF_INET; #endif - (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + (void)strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) { (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno)); diff --git a/external/bsd/libpcap/dist/lbl/os-osf4.h b/external/bsd/libpcap/dist/lbl/os-osf4.h index 48e07c2a473a..0909cd6b9063 100644 --- a/external/bsd/libpcap/dist/lbl/os-osf4.h +++ b/external/bsd/libpcap/dist/lbl/os-osf4.h @@ -1,4 +1,4 @@ -/* $NetBSD: os-osf4.h,v 1.2 2014/11/19 19:33:31 christos Exp $ */ +/* $NetBSD: os-osf4.h,v 1.3 2015/03/31 21:39:43 christos Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 @@ -25,4 +25,4 @@ int snprintf(char *, size_t, const char *, ...); int vsnprintf(char *, size_t, const char *, va_list); int pfopen(char *, int); - + diff --git a/external/bsd/libpcap/dist/lbl/os-osf5.h b/external/bsd/libpcap/dist/lbl/os-osf5.h index c0fc493e6de6..ef841773d4c4 100644 --- a/external/bsd/libpcap/dist/lbl/os-osf5.h +++ b/external/bsd/libpcap/dist/lbl/os-osf5.h @@ -1,4 +1,4 @@ -/* $NetBSD: os-osf5.h,v 1.2 2014/11/19 19:33:31 christos Exp $ */ +/* $NetBSD: os-osf5.h,v 1.3 2015/03/31 21:39:43 christos Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 @@ -29,4 +29,4 @@ int snprintf(char *, size_t, const char *, ...); int vsnprintf(char *, size_t, const char *, va_list); int pfopen(char *, int); - + diff --git a/external/bsd/libpcap/dist/optimize.c b/external/bsd/libpcap/dist/optimize.c index 326cf0e1167f..b60ca327e072 100644 --- a/external/bsd/libpcap/dist/optimize.c +++ b/external/bsd/libpcap/dist/optimize.c @@ -1,4 +1,4 @@ -/* $NetBSD: optimize.c,v 1.7 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: optimize.c,v 1.8 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996 @@ -24,7 +24,7 @@ */ #include -__RCSID("$NetBSD: optimize.c,v 1.7 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: optimize.c,v 1.8 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -2249,7 +2249,92 @@ install_bpf_program(pcap_t *p, struct bpf_program *fp) #ifdef BDEBUG static void -opt_dump(struct block *root) +dot_dump_node(struct block *block, struct bpf_program *prog, FILE *out) +{ + int icount, noffset; + int i; + + if (block == NULL || isMarked(block)) + return; + Mark(block); + + icount = slength(block->stmts) + 1 + block->longjt + block->longjf; + noffset = min(block->offset + icount, (int)prog->bf_len); + + fprintf(out, "\tblock%d [shape=ellipse, id=\"block-%d\" label=\"BLOCK%d\\n", block->id, block->id, block->id); + for (i = block->offset; i < noffset; i++) { + fprintf(out, "\\n%s", bpf_image(prog->bf_insns + i, i)); + } + fprintf(out, "\" tooltip=\""); + for (i = 0; i < BPF_MEMWORDS; i++) + if (block->val[i] != 0) + fprintf(out, "val[%d]=%d ", i, block->val[i]); + fprintf(out, "val[A]=%d ", block->val[A_ATOM]); + fprintf(out, "val[X]=%d", block->val[X_ATOM]); + fprintf(out, "\""); + if (JT(block) == NULL) + fprintf(out, ", peripheries=2"); + fprintf(out, "];\n"); + + dot_dump_node(JT(block), prog, out); + dot_dump_node(JF(block), prog, out); +} +static void +dot_dump_edge(struct block *block, FILE *out) +{ + if (block == NULL || isMarked(block)) + return; + Mark(block); + + if (JT(block)) { + fprintf(out, "\t\"block%d\":se -> \"block%d\":n [label=\"T\"]; \n", + block->id, JT(block)->id); + fprintf(out, "\t\"block%d\":sw -> \"block%d\":n [label=\"F\"]; \n", + block->id, JF(block)->id); + } + dot_dump_edge(JT(block), out); + dot_dump_edge(JF(block), out); +} +/* Output the block CFG using graphviz/DOT language + * In the CFG, block's code, value index for each registers at EXIT, + * and the jump relationship is show. + * + * example DOT for BPF `ip src host 1.1.1.1' is: + digraph BPF { + block0 [shape=ellipse, id="block-0" label="BLOCK0\n\n(000) ldh [12]\n(001) jeq #0x800 jt 2 jf 5" tooltip="val[A]=0 val[X]=0"]; + block1 [shape=ellipse, id="block-1" label="BLOCK1\n\n(002) ld [26]\n(003) jeq #0x1010101 jt 4 jf 5" tooltip="val[A]=0 val[X]=0"]; + block2 [shape=ellipse, id="block-2" label="BLOCK2\n\n(004) ret #68" tooltip="val[A]=0 val[X]=0", peripheries=2]; + block3 [shape=ellipse, id="block-3" label="BLOCK3\n\n(005) ret #0" tooltip="val[A]=0 val[X]=0", peripheries=2]; + "block0":se -> "block1":n [label="T"]; + "block0":sw -> "block3":n [label="F"]; + "block1":se -> "block2":n [label="T"]; + "block1":sw -> "block3":n [label="F"]; + } + * + * After install graphviz on http://www.graphviz.org/, save it as bpf.dot + * and run `dot -Tpng -O bpf.dot' to draw the graph. + */ +static void +dot_dump(struct block *root) +{ + struct bpf_program f; + FILE *out = stdout; + + memset(bids, 0, sizeof bids); + f.bf_insns = icode_to_fcode(root, &f.bf_len); + + fprintf(out, "digraph BPF {\n"); + unMarkAll(); + dot_dump_node(root, &f, out); + unMarkAll(); + dot_dump_edge(root, out); + fprintf(out, "}\n"); + + free((char *)f.bf_insns); +} + +static void +plain_dump(struct block *root) { struct bpf_program f; @@ -2259,4 +2344,17 @@ opt_dump(struct block *root) putchar('\n'); free((char *)f.bf_insns); } +static void +opt_dump(struct block *root) +{ + /* if optimizer debugging is enabled, output DOT graph + * `dflag=4' is equivalent to -dddd to follow -d/-dd/-ddd + * convention in tcpdump command line + */ + if (dflag > 3) + dot_dump(root); + else + plain_dump(root); +} + #endif diff --git a/external/bsd/libpcap/dist/packaging/pcap.spec.in b/external/bsd/libpcap/dist/packaging/pcap.spec.in deleted file mode 100644 index ff7b996eca64..000000000000 --- a/external/bsd/libpcap/dist/packaging/pcap.spec.in +++ /dev/null @@ -1,77 +0,0 @@ -%define prefix /usr -%define version @VERSION@ - -Summary: A system-independent interface for user-level packet capture -Name: libpcap -Version: %version -Release: 1 -Group: Development/Libraries -License: BSD with advertising -Source: @NAME@.tar.gz -BuildRoot: /tmp/%{name}-buildroot -URL: http://www.tcpdump.org - -Source: http://www.tcpdump.org/release/%{name}-%{version}.tar.gz - -%description -Libpcap provides a portable framework for low-level network -monitoring. Libpcap can provide network statistics collection, -security monitoring and network debugging. Since almost every system -vendor provides a different interface for packet capture, the libpcap -authors created this system-independent API to ease in porting and to -alleviate the need for several system-dependent packet capture modules -in each application. - -Install libpcap if you need to do low-level network traffic monitoring -on your network. - -%package devel -Summary: Libraries and header files for the libpcap library -Group: Development/Libraries - -%description devel -Libpcap provides a portable framework for low-level network -monitoring. Libpcap can provide network statistics collection, -security monitoring and network debugging. Since almost every system -vendor provides a different interface for packet capture, the libpcap -authors created this system-independent API to ease in porting and to -alleviate the need for several system-dependent packet capture modules -in each application. - -This package provides the libraries, include files, and other -resources needed for developing libpcap applications. - -%prep -%setup -q - -%build -export CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing" -%configure -make %{?_smp_mflags} - -%install -rm -rf $RPM_BUILD_ROOT - -make DESTDIR=$RPM_BUILD_ROOT install - -%clean -rm -rf $RPM_BUILD_ROOT - -%files -%defattr(-,root,root) -%doc LICENSE README CHANGES INSTALL.txt README.linux TODO VERSION CREDITS packaging/pcap.spec -%{_libdir}/libpcap.so.* -%{_mandir}/man7/pcap*.7* - -%files devel -%defattr(-,root,root) -%{_bindir}/pcap-config -%{_includedir}/pcap/*.h -%{_includedir}/pcap.h -%{_includedir}/pcap-bpf.h -%{_includedir}/pcap-namedb.h -%{_libdir}/libpcap.so -%{_libdir}/libpcap.a -%{_mandir}/man1/pcap-config.1* -%{_mandir}/man3/pcap*.3* -%{_mandir}/man5/pcap*.5* diff --git a/external/bsd/libpcap/dist/pcap-bpf.c b/external/bsd/libpcap/dist/pcap-bpf.c index 4a03fcdfd3fa..94db4d882906 100644 --- a/external/bsd/libpcap/dist/pcap-bpf.c +++ b/external/bsd/libpcap/dist/pcap-bpf.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-bpf.c,v 1.5 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-bpf.c,v 1.6 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1998 @@ -22,7 +22,7 @@ */ #include -__RCSID("$NetBSD: pcap-bpf.c,v 1.5 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-bpf.c,v 1.6 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -243,7 +243,7 @@ static int pcap_set_datalink_bpf(pcap_t *p, int dlt); */ static int pcap_getnonblock_bpf(pcap_t *p, char *errbuf) -{ +{ #ifdef HAVE_ZEROCOPY_BPF struct pcap_bpf *pb = p->priv; @@ -255,7 +255,7 @@ pcap_getnonblock_bpf(pcap_t *p, char *errbuf) static int pcap_setnonblock_bpf(pcap_t *p, int nonblock, char *errbuf) -{ +{ #ifdef HAVE_ZEROCOPY_BPF struct pcap_bpf *pb = p->priv; @@ -1546,22 +1546,43 @@ pcap_activate_bpf(pcap_t *p) #if defined(LIFNAMSIZ) && defined(ZONENAME_MAX) && defined(lifr_zoneid) /* - * Check if the given source network device has a '/' separated - * zonename prefix string. The zonename prefixed source device - * can be used by libpcap consumers to capture network traffic - * in non-global zones from the global zone on Solaris 11 and - * above. If the zonename prefix is present then we strip the - * prefix and pass the zone ID as part of lifr_zoneid. + * Retrieve the zoneid of the zone we are currently executing in. + */ + if ((ifr.lifr_zoneid = getzoneid()) == -1) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "getzoneid(): %s", + pcap_strerror(errno)); + status = PCAP_ERROR; + goto bad; + } + /* + * Check if the given source datalink name has a '/' separated + * zonename prefix string. The zonename prefixed source datalink can + * be used by pcap consumers in the Solaris global zone to capture + * traffic on datalinks in non-global zones. Non-global zones + * do not have access to datalinks outside of their own namespace. */ if ((zonesep = strchr(p->opt.source, '/')) != NULL) { - char zonename[ZONENAME_MAX]; + char path_zname[ZONENAME_MAX]; int znamelen; char *lnamep; + if (ifr.lifr_zoneid != GLOBAL_ZONEID) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "zonename/linkname only valid in global zone."); + status = PCAP_ERROR; + goto bad; + } znamelen = zonesep - p->opt.source; - (void) strlcpy(zonename, p->opt.source, znamelen + 1); + (void) strlcpy(path_zname, p->opt.source, znamelen + 1); + ifr.lifr_zoneid = getzoneidbyname(path_zname); + if (ifr.lifr_zoneid == -1) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "getzoneidbyname(%s): %s", path_zname, + pcap_strerror(errno)); + status = PCAP_ERROR; + goto bad; + } lnamep = strdup(zonesep + 1); - ifr.lifr_zoneid = getzoneidbyname(zonename); free(p->opt.source); p->opt.source = lnamep; } diff --git a/external/bsd/libpcap/dist/pcap-bpf.h b/external/bsd/libpcap/dist/pcap-bpf.h index 9601b519e7c4..64b803e602b3 100644 --- a/external/bsd/libpcap/dist/pcap-bpf.h +++ b/external/bsd/libpcap/dist/pcap-bpf.h @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-bpf.h,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-bpf.h,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /*- * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 @@ -6,7 +6,7 @@ * * This code is derived from the Stanford/CMU enet packet filter, * (net/enet.c) distributed as part of 4.3BSD, and code contributed - * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence * Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without diff --git a/external/bsd/libpcap/dist/pcap-bt-linux.c b/external/bsd/libpcap/dist/pcap-bt-linux.c index bd8837f1f624..33c48a929e64 100644 --- a/external/bsd/libpcap/dist/pcap-bt-linux.c +++ b/external/bsd/libpcap/dist/pcap-bt-linux.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-bt-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-bt-linux.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 2006 Paolo Abeni (Italy) @@ -13,8 +13,8 @@ * 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. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @@ -33,9 +33,8 @@ * By Paolo Abeni * */ - #include -__RCSID("$NetBSD: pcap-bt-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-bt-linux.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -78,7 +77,7 @@ struct pcap_bt { int dev_id; /* device ID of device we're bound to */ }; -int +int bt_findalldevs(pcap_if_t **alldevsp, char *err_str) { struct hci_dev_list_req *dev_list; @@ -89,7 +88,7 @@ bt_findalldevs(pcap_if_t **alldevsp, char *err_str) sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (sock < 0) { - /* if bluetooth is not supported this this is not fatal*/ + /* if bluetooth is not supported this this is not fatal*/ if (errno == EAFNOSUPPORT) return 0; snprintf(err_str, PCAP_ERRBUF_SIZE, @@ -98,7 +97,7 @@ bt_findalldevs(pcap_if_t **alldevsp, char *err_str) } dev_list = malloc(HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list)); - if (!dev_list) + if (!dev_list) { snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't allocate %zu bytes for Bluetooth device list", HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list)); @@ -108,7 +107,7 @@ bt_findalldevs(pcap_if_t **alldevsp, char *err_str) dev_list->dev_num = HCI_MAX_DEV; - if (ioctl(sock, HCIGETDEVLIST, (void *) dev_list) < 0) + if (ioctl(sock, HCIGETDEVLIST, (void *) dev_list) < 0) { snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't get Bluetooth device list via ioctl: %s", @@ -120,11 +119,11 @@ bt_findalldevs(pcap_if_t **alldevsp, char *err_str) dev_req = dev_list->dev_req; for (i = 0; i < dev_list->dev_num; i++, dev_req++) { char dev_name[20], dev_descr[30]; - + snprintf(dev_name, 20, BT_IFACE"%d", dev_req->dev_id); snprintf(dev_descr, 30, "Bluetooth adapter number %d", i); - - if (pcap_add_if(alldevsp, dev_name, 0, + + if (pcap_add_if(alldevsp, dev_name, 0, dev_descr, err_str) < 0) { ret = -1; @@ -198,7 +197,7 @@ bt_activate(pcap_t* handle) if (sscanf(handle->opt.source, BT_IFACE"%d", &dev_id) != 1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, - "Can't get Bluetooth device index from %s", + "Can't get Bluetooth device index from %s", handle->opt.source); return PCAP_ERROR; } @@ -217,7 +216,7 @@ bt_activate(pcap_t* handle) handle->setnonblock_op = pcap_setnonblock_fd; handle->stats_op = bt_stats_linux; handlep->dev_id = dev_id; - + /* Create HCI socket */ handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); if (handle->fd < 0) { @@ -247,10 +246,10 @@ bt_activate(pcap_t* handle) goto close_fail; } - /* Setup filter, do not call hci function to avoid dependence on + /* Setup filter, do not call hci function to avoid dependence on * external libs */ memset(&flt, 0, sizeof(flt)); - memset((void *) &flt.type_mask, 0xff, sizeof(flt.type_mask)); + memset((void *) &flt.type_mask, 0xff, sizeof(flt.type_mask)); memset((void *) &flt.event_mask, 0xff, sizeof(flt.event_mask)); if (setsockopt(handle->fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, @@ -314,7 +313,7 @@ bt_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *us bthdr = (pcap_bluetooth_h4_header*) &handle->buffer[handle->offset]; iv.iov_base = &handle->buffer[handle->offset+sizeof(pcap_bluetooth_h4_header)]; iv.iov_len = handle->snapshot; - + memset(&msg, 0, sizeof(msg)); msg.msg_iov = &iv; msg.msg_iovlen = 1; @@ -339,7 +338,7 @@ bt_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *us pkth.caplen = ret; - /* get direction and timestamp*/ + /* get direction and timestamp*/ cmsg = CMSG_FIRSTHDR(&msg); int in=0; while (cmsg) { @@ -354,7 +353,7 @@ bt_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *us } cmsg = CMSG_NXTHDR(&msg, cmsg); } - if ((in && (handle->direction == PCAP_D_OUT)) || + if ((in && (handle->direction == PCAP_D_OUT)) || ((!in) && (handle->direction == PCAP_D_IN))) return 0; @@ -376,10 +375,10 @@ bt_inject_linux(pcap_t *handle, const void *buf, size_t size) snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on " "bluetooth devices"); return (-1); -} +} -static int +static int bt_stats_linux(pcap_t *handle, struct pcap_stat *stats) { struct pcap_bt *handlep = handle->priv; @@ -387,28 +386,28 @@ bt_stats_linux(pcap_t *handle, struct pcap_stat *stats) struct hci_dev_info dev_info; struct hci_dev_stats * s = &dev_info.stat; dev_info.dev_id = handlep->dev_id; - + /* ignore eintr */ do { ret = ioctl(handle->fd, HCIGETDEVINFO, (void *)&dev_info); } while ((ret == -1) && (errno == EINTR)); - + if (ret < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get stats via ioctl: %s", strerror(errno)); return (-1); - + } - /* we receive both rx and tx frames, so comulate all stats */ - stats->ps_recv = s->evt_rx + s->acl_rx + s->sco_rx + s->cmd_tx + + /* we receive both rx and tx frames, so comulate all stats */ + stats->ps_recv = s->evt_rx + s->acl_rx + s->sco_rx + s->cmd_tx + s->acl_tx +s->sco_tx; stats->ps_drop = s->err_rx + s->err_tx; stats->ps_ifdrop = 0; return 0; } -static int +static int bt_setdirection_linux(pcap_t *p, pcap_direction_t d) { p->direction = d; diff --git a/external/bsd/libpcap/dist/pcap-bt-linux.h b/external/bsd/libpcap/dist/pcap-bt-linux.h index 971603365c68..0f367237692d 100644 --- a/external/bsd/libpcap/dist/pcap-bt-linux.h +++ b/external/bsd/libpcap/dist/pcap-bt-linux.h @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-bt-linux.h,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-bt-linux.h,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 2006 Paolo Abeni (Italy) @@ -13,8 +13,8 @@ * 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. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS diff --git a/external/bsd/libpcap/dist/pcap-bt-monitor-linux.c b/external/bsd/libpcap/dist/pcap-bt-monitor-linux.c index 18127188d128..c18ed4b9cd39 100644 --- a/external/bsd/libpcap/dist/pcap-bt-monitor-linux.c +++ b/external/bsd/libpcap/dist/pcap-bt-monitor-linux.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-bt-monitor-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-bt-monitor-linux.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 2014 Michal Labedzki for Tieto Corporation @@ -32,7 +32,7 @@ */ #include -__RCSID("$NetBSD: pcap-bt-monitor-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-bt-monitor-linux.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -49,6 +49,8 @@ __RCSID("$NetBSD: pcap-bt-monitor-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp #include "pcap/bluetooth.h" #include "pcap-int.h" +#include "pcap-bt-monitor-linux.h" + #define BT_CONTROL_SIZE 32 #define INTERFACE_NAME "bluetooth-monitor" @@ -76,7 +78,6 @@ bt_monitor_read(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_ch struct pcap_pkthdr pkth; pcap_bluetooth_linux_monitor_header *bthdr; struct mgmt_hdr hdr; - int in = 0; bthdr = (pcap_bluetooth_linux_monitor_header*) &handle->buffer[handle->offset]; diff --git a/external/bsd/libpcap/dist/pcap-can-linux.c b/external/bsd/libpcap/dist/pcap-can-linux.c index 98ae7cf902f7..79b621c45e67 100644 --- a/external/bsd/libpcap/dist/pcap-can-linux.c +++ b/external/bsd/libpcap/dist/pcap-can-linux.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-can-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-can-linux.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 2009 Felix Obenhuber @@ -35,7 +35,7 @@ */ #include -__RCSID("$NetBSD: pcap-can-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-can-linux.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -176,7 +176,7 @@ can_activate(pcap_t* handle) /* get interface index */ memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name)); + strlcpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name)); if (ioctl(handle->fd, SIOCGIFINDEX, &ifr) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, diff --git a/external/bsd/libpcap/dist/pcap-canusb-linux.c b/external/bsd/libpcap/dist/pcap-canusb-linux.c index 5cd8a8e6fcbc..eabf78cd4301 100644 --- a/external/bsd/libpcap/dist/pcap-canusb-linux.c +++ b/external/bsd/libpcap/dist/pcap-canusb-linux.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-canusb-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-canusb-linux.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 2009 Felix Obenhuber @@ -35,7 +35,7 @@ */ #include -__RCSID("$NetBSD: pcap-canusb-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-canusb-linux.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -46,6 +46,7 @@ __RCSID("$NetBSD: pcap-canusb-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $") #include #include #include +#include #include #include @@ -97,7 +98,7 @@ int canusb_findalldevs(pcap_if_t **alldevsp, char *err_str) libusb_device** devs; unsigned char sernum[65]; int cnt, i; - + if (libusb_init(&fdctx) != 0) { /* * XXX - if this doesn't just mean "no USB file system mounted", @@ -105,7 +106,7 @@ int canusb_findalldevs(pcap_if_t **alldevsp, char *err_str) * saying "no CANUSB devices". */ return 0; - } + } cnt = libusb_get_device_list(fdctx,&devs); @@ -116,24 +117,24 @@ int canusb_findalldevs(pcap_if_t **alldevsp, char *err_str) struct libusb_device_descriptor desc; libusb_get_device_descriptor(devs[i],&desc); - if ((desc.idVendor != CANUSB_VID) || (desc.idProduct != CANUSB_PID)) + if ((desc.idVendor != CANUSB_VID) || (desc.idProduct != CANUSB_PID)) continue; //It is not, check next device - + //It is! libusb_device_handle *dh = NULL; if ((ret = libusb_open(devs[i],&dh)) == 0) { char dev_name[30]; - char dev_descr[50]; + char dev_descr[50]; int n = libusb_get_string_descriptor_ascii(dh,desc.iSerialNumber,sernum,64); sernum[n] = 0; snprintf(dev_name, 30, CANUSB_IFACE"%s", sernum); snprintf(dev_descr, 50, "CanUSB [%s]", sernum); - + libusb_close(dh); - + if (pcap_add_if(alldevsp, dev_name, 0, dev_descr, err_str) < 0) { libusb_free_device_list(devs,1); @@ -153,18 +154,18 @@ static libusb_device_handle* canusb_opendevice(struct libusb_context *ctx, char* libusb_device** devs; unsigned char serial[65]; int cnt,i,n; - + cnt = libusb_get_device_list(ctx,&devs); for(i=0;iwrpipe, F_SETFL, O_NONBLOCK); + + fcntl(canusb->wrpipe, F_SETFL, O_NONBLOCK); while(canusb->loop) { int sz; struct CAN_Msg msg; - + + libusb_interrupt_transfer(canusb->dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100); + //HACK!!!!! -> drop buffered data, read new one by reading twice. libusb_interrupt_transfer(canusb->dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100); - //HACK!!!!! -> drop buffered data, read new one by reading twice. - libusb_interrupt_transfer(canusb->dev, 0x81, (unsigned char*)&status, sizeof(status), &sz, 100); for(i = 0; idev, 0x85, (unsigned char*)&msg, sizeof(msg), &sz, 100); - write(canusb->wrpipe, &msg, sizeof(msg)); + libusb_bulk_transfer(canusb->dev, 0x85, (unsigned char*)&msg, sizeof(msg), &sz, 100); + if(write(canusb->wrpipe, &msg, sizeof(msg)) < 0) + fprintf(stderr,"write() error: %s\n", strerror(errno)); } } - + return NULL; } @@ -300,7 +302,7 @@ static int canusb_startcapture(struct pcap_canusb* this) this->rdpipe = pipefd[0]; this->wrpipe = pipefd[1]; - this->loop = 1; + this->loop = 1; pthread_create(&this->worker, NULL, canusb_capture_thread, this); return this->rdpipe; @@ -315,7 +317,7 @@ static void canusb_clearbufs(struct pcap_canusb* this) cmd[1] = 1; //Empty outgoing buffer cmd[3] = 0; //Not a write to serial number memset(&cmd[4],0,16-4); - + libusb_interrupt_transfer(this->dev, 0x1,cmd,16,&al,100); } @@ -331,7 +333,7 @@ static void canusb_close(pcap_t* handle) { libusb_close(canusb->dev); canusb->dev = NULL; - } + } if (canusb->ctx) { libusb_exit(canusb->ctx); @@ -350,9 +352,9 @@ static int canusb_activate(pcap_t* handle) /* * XXX - what causes this to fail? */ - snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "libusb_init() failed"); + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "libusb_init() failed"); return PCAP_ERROR; - } + } handle->read_op = canusb_read_linux; @@ -376,7 +378,7 @@ static int canusb_activate(pcap_t* handle) if (!canusb->dev) { libusb_exit(canusb->ctx); - snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't open USB Device"); + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't open USB Device"); return PCAP_ERROR; } @@ -398,7 +400,7 @@ canusb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char int i = 0; struct CAN_Msg msg; struct pcap_pkthdr pkth; - + while(i < max_packets) { int n; @@ -409,10 +411,10 @@ canusb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char pkth.caplen = pkth.len = n; pkth.caplen -= 4; pkth.caplen -= 8 - msg.length; - + if ((firstpacket.tv_sec == -1) && (firstpacket.tv_usec == -1)) gettimeofday(&firstpacket, NULL); - + pkth.ts.tv_usec = firstpacket.tv_usec + (msg.timestamp % 100) * 10000; pkth.ts.tv_sec = firstpacket.tv_usec + (msg.timestamp / 100); if (pkth.ts.tv_usec > 1000000) @@ -424,7 +426,7 @@ canusb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char callback(user, &pkth, (void*)&msg.id); i++; } - + return i; } diff --git a/external/bsd/libpcap/dist/pcap-common.c b/external/bsd/libpcap/dist/pcap-common.c index 1a55b3c22b13..fe275fed90ae 100644 --- a/external/bsd/libpcap/dist/pcap-common.c +++ b/external/bsd/libpcap/dist/pcap-common.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-common.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-common.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 @@ -24,7 +24,7 @@ */ #include -__RCSID("$NetBSD: pcap-common.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-common.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -391,7 +391,7 @@ __RCSID("$NetBSD: pcap-common.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); /* * Juniper-private data link type, as per request from - * Hannes Gredler . + * Hannes Gredler . * The Link Types are used for prepending meta-information * like interface index, interface name * before standard Ethernet, PPP, Frelay & C-HDLC Frames @@ -408,7 +408,7 @@ __RCSID("$NetBSD: pcap-common.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); /* * Juniper-private data link type, as per request from - * Hannes Gredler . + * Hannes Gredler . * The DLT_ is used for internal communication with a * voice Adapter Card (PIC) */ @@ -483,7 +483,7 @@ __RCSID("$NetBSD: pcap-common.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); /* * Juniper-private data link type, as per request from - * Hannes Gredler . + * Hannes Gredler . * The DLT_ is used for internal communication with a * integrated service module (ISM). */ @@ -524,7 +524,7 @@ __RCSID("$NetBSD: pcap-common.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); /* * Juniper-private data link type, as per request from - * Hannes Gredler . + * Hannes Gredler . * The DLT_ is used for capturing data on a secure tunnel interface. */ #define LINKTYPE_JUNIPER_ST 200 @@ -616,11 +616,11 @@ __RCSID("$NetBSD: pcap-common.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); */ #define LINKTYPE_IEEE802_15_4_NONASK_PHY 215 -/* +/* * David Gibson requested this for * captures from the Linux kernel /dev/input/eventN devices. This * is used to communicate keystrokes and mouse movements from the - * Linux kernel to display systems, such as Xorg. + * Linux kernel to display systems, such as Xorg. */ #define LINKTYPE_LINUX_EVDEV 216 @@ -782,7 +782,7 @@ __RCSID("$NetBSD: pcap-common.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); /* * Juniper-private data link type, as per request from - * Hannes Gredler . + * Hannes Gredler . */ #define LINKTYPE_JUNIPER_VS 232 #define LINKTYPE_JUNIPER_SRX_E2E 233 @@ -814,12 +814,12 @@ __RCSID("$NetBSD: pcap-common.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); /* * Juniper-private data link type, as per request from - * Hannes Gredler . + * Hannes Gredler . */ #define LINKTYPE_JUNIPER_ATM_CEMIC 238 /* - * NetFilter LOG messages + * NetFilter LOG messages * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets) * * Requested by Jakub Zawadzki @@ -927,7 +927,7 @@ __RCSID("$NetBSD: pcap-common.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); /* * Link-layer header type for upper-protocol layer PDU saves from wireshark. - * + * * the actual contents are determined by two TAGs stored with each * packet: * EXP_PDU_TAG_LINKTYPE the link type (LINKTYPE_ value) of the @@ -999,7 +999,13 @@ __RCSID("$NetBSD: pcap-common.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); */ #define LINKTYPE_IPMI_HPM_2 260 -#define LINKTYPE_MATCHING_MAX 260 /* highest value in the "matching" range */ +/* + * per Joshua Wright , formats for Zwave captures. + */ +#define LINKTYPE_ZWAVE_R1_R2 261 +#define LINKTYPE_ZWAVE_R3 262 + +#define LINKTYPE_MATCHING_MAX 262 /* highest value in the "matching" range */ static struct linktype_map { int dlt; @@ -1161,8 +1167,6 @@ swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf, { pcap_usb_header_mmapped *uhdr = (pcap_usb_header_mmapped *)buf; bpf_u_int32 offset = 0; - usb_isodesc *pisodesc; - int32_t numdesc, i; /* * "offset" is the offset *past* the field we're swapping; @@ -1171,7 +1175,7 @@ swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf, */ /* - * The URB id is a totally opaque value; do we really need to + * The URB id is a totally opaque value; do we really need to * convert it to the reading host's byte order??? */ offset += 8; /* skip past id */ @@ -1226,6 +1230,17 @@ swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf, } else offset += 8; /* skip USB setup header */ + /* + * With the old header, there are no isochronous descriptors + * after the header. + * + * With the new header, the actual number of descriptors in + * the header is not s.iso.numdesc, it's ndesc - only the + * first N descriptors, for some value of N, are put into + * the header, and ndesc is set to the actual number copied. + * In addition, if s.iso.numdesc is negative, no descriptors + * are captured, and ndesc is set to 0. + */ if (header_len_64_bytes) { /* * This is either the "version 1" header, with @@ -1254,31 +1269,33 @@ swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf, if (hdr->caplen < offset) return; uhdr->ndesc = SWAPLONG(uhdr->ndesc); - } - if (uhdr->transfer_type == URB_ISOCHRONOUS) { - /* swap the values in struct linux_usb_isodesc */ - pisodesc = (usb_isodesc *)(void *)(buf+offset); - numdesc = uhdr->s.iso.numdesc; - for (i = 0; i < numdesc; i++) { - offset += 4; /* skip past status */ - if (hdr->caplen < offset) - return; - pisodesc->status = SWAPLONG(pisodesc->status); + if (uhdr->transfer_type == URB_ISOCHRONOUS) { + /* swap the values in struct linux_usb_isodesc */ + usb_isodesc *pisodesc; + u_int32_t i; - offset += 4; /* skip past offset */ - if (hdr->caplen < offset) - return; - pisodesc->offset = SWAPLONG(pisodesc->offset); + pisodesc = (usb_isodesc *)(void *)(buf+offset); + for (i = 0; i < uhdr->ndesc; i++) { + offset += 4; /* skip past status */ + if (hdr->caplen < offset) + return; + pisodesc->status = SWAPLONG(pisodesc->status); - offset += 4; /* skip past len */ - if (hdr->caplen < offset) - return; - pisodesc->len = SWAPLONG(pisodesc->len); + offset += 4; /* skip past offset */ + if (hdr->caplen < offset) + return; + pisodesc->offset = SWAPLONG(pisodesc->offset); - offset += 4; /* skip past padding */ + offset += 4; /* skip past len */ + if (hdr->caplen < offset) + return; + pisodesc->len = SWAPLONG(pisodesc->len); - pisodesc++; + offset += 4; /* skip past padding */ + + pisodesc++; + } } } } diff --git a/external/bsd/libpcap/dist/pcap-dag.c b/external/bsd/libpcap/dist/pcap-dag.c index 13bee1fb0bb2..e8e266292429 100644 --- a/external/bsd/libpcap/dist/pcap-dag.c +++ b/external/bsd/libpcap/dist/pcap-dag.c @@ -1,7 +1,7 @@ -/* $NetBSD: pcap-dag.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-dag.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* - * pcap-dag.c: Packet capture interface for Endace DAG card. + * pcap-dag.c: Packet capture interface for Emulex EndaceDAG cards. * * The functionality of this code attempts to mimic that of pcap-linux as much * as possible. This code is compiled in several different ways depending on @@ -12,13 +12,13 @@ * called as required from their pcap-linux/bpf equivalents. * * Authors: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com) - * Modifications: Jesper Peterson - * Koryn Grant - * Stephen Donnelly + * Modifications: Jesper Peterson + * Koryn Grant + * Stephen Donnelly */ #include -__RCSID("$NetBSD: pcap-dag.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-dag.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -45,6 +45,7 @@ struct rtentry; /* declarations in */ #include "dagnew.h" #include "dagapi.h" +#include "dagpci.h" #include "pcap-dag.h" @@ -155,7 +156,7 @@ dag_platform_cleanup(pcap_t *p) #ifdef HAVE_DAG_STREAMS_API if(dag_stop_stream(p->fd, pd->dag_stream) < 0) fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno)); - + if(dag_detach_stream(p->fd, pd->dag_stream) < 0) fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno)); #else @@ -226,7 +227,7 @@ dag_erf_ext_header_count(uint8_t * erf, size_t len) /* loop over the extension headers */ do { - + /* sanity check we have enough bytes */ if ( len < (24 + (hdr_num * 8)) ) return hdr_num; @@ -253,10 +254,11 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) int flags = pd->dag_offset_flags; unsigned int nonblocking = flags & DAGF_NONBLOCK; unsigned int num_ext_hdr = 0; + unsigned int ticks_per_second; /* Get the next bufferful of packets (if necessary). */ while (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size) { - + /* * Has "pcap_breakloop()" been called? */ @@ -295,7 +297,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) /* Pcap is configured to process only available packets, and there aren't any, return immediately. */ return 0; } - + if(!nonblocking && pd->dag_timeout && (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size)) @@ -305,14 +307,14 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) } } - + /* Process the packets. */ while (pd->dag_mem_top - pd->dag_mem_bottom >= dag_record_size) { - + unsigned short packet_len = 0; int caplen = 0; struct pcap_pkthdr pcap_header; - + #ifdef HAVE_DAG_STREAMS_API dag_record_t *header = (dag_record_t *)(pd->dag_mem_bottom); #else @@ -321,7 +323,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) u_char *dp = ((u_char *)header); /* + dag_record_size; */ unsigned short rlen; - + /* * Has "pcap_breakloop()" been called? */ @@ -334,7 +336,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) p->break_loop = 0; return -2; } - + rlen = ntohs(header->rlen); if (rlen < dag_record_size) { @@ -364,7 +366,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) } } } - + if ((header->type & 0x7f) == TYPE_PAD) { continue; } @@ -372,13 +374,13 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) num_ext_hdr = dag_erf_ext_header_count(dp, rlen); /* ERF encapsulation */ - /* The Extensible Record Format is not dropped for this kind of encapsulation, + /* The Extensible Record Format is not dropped for this kind of encapsulation, * and will be handled as a pseudo header by the decoding application. * The information carried in the ERF header and in the optional subheader (if present) * could be merged with the libpcap information, to offer a better decoding. * The packet length is * o the length of the packet on the link (header->wlen), - * o plus the length of the ERF header (dag_record_size), as the length of the + * o plus the length of the ERF header (dag_record_size), as the length of the * pseudo header will be adjusted during the decoding, * o plus the length of the optional subheader (if present). * @@ -420,7 +422,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) dp += dag_record_size; /* Skip over extension headers */ dp += 8 * num_ext_hdr; - + switch((header->type & 0x7f)) { case TYPE_ATM: case TYPE_AAL5: @@ -439,19 +441,22 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) caplen = rlen - dag_record_size - 4; dp+=4; } + /* Skip over extension headers */ + caplen -= (8 * num_ext_hdr); + if (header->type == TYPE_ATM) { caplen = packet_len = ATM_CELL_SIZE; } if (p->linktype == DLT_SUNATM) { struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp; unsigned long rawatm; - + rawatm = ntohl(*((unsigned long *)dp)); sunatm->vci = htons((rawatm >> 4) & 0xffff); sunatm->vpi = (rawatm >> 20) & 0x00ff; - sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) | + sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) | ((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 : - ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 : + ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 : ((dp[ATM_HDR_SIZE] == 0xaa && dp[ATM_HDR_SIZE+1] == 0xaa && dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1))); @@ -470,6 +475,8 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) packet_len = ntohs(header->wlen); packet_len -= (pd->dag_fcs_bits >> 3); caplen = rlen - dag_record_size - 2; + /* Skip over extension headers */ + caplen -= (8 * num_ext_hdr); if (caplen > packet_len) { caplen = packet_len; } @@ -483,6 +490,8 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) packet_len = ntohs(header->wlen); packet_len -= (pd->dag_fcs_bits >> 3); caplen = rlen - dag_record_size; + /* Skip over extension headers */ + caplen -= (8 * num_ext_hdr); if (caplen > packet_len) { caplen = packet_len; } @@ -493,6 +502,8 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) packet_len = ntohs(header->wlen); packet_len -= (pd->dag_fcs_bits >> 3); caplen = rlen - dag_record_size - 4; + /* Skip over extension headers */ + caplen -= (8 * num_ext_hdr); if (caplen > packet_len) { caplen = packet_len; } @@ -503,7 +514,7 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) /* Add the MTP2 Pseudo Header */ caplen += MTP2_HDR_LEN; packet_len += MTP2_HDR_LEN; - + TempPkt[MTP2_SENT_OFFSET] = 0; TempPkt[MTP2_ANNEX_A_USED_OFFSET] = MTP2_ANNEX_A_USED_UNKNOWN; *(TempPkt+MTP2_LINK_NUMBER_OFFSET) = ((header->rec.mc_hdlc.mc_header>>16)&0x01); @@ -518,6 +529,8 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) case TYPE_IPV6: packet_len = ntohs(header->wlen); caplen = rlen - dag_record_size; + /* Skip over extension headers */ + caplen -= (8 * num_ext_hdr); if (caplen > packet_len) { caplen = packet_len; } @@ -538,45 +551,52 @@ dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) continue; } /* switch type */ - /* Skip over extension headers */ - caplen -= (8 * num_ext_hdr); - } /* ERF encapsulation */ - + if (caplen > p->snapshot) caplen = p->snapshot; /* Run the packet filter if there is one. */ if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) { - + /* convert between timestamp formats */ register unsigned long long ts; - + if (IS_BIGENDIAN()) { ts = SWAPLL(header->ts); } else { ts = header->ts; } + switch (p->opt.tstamp_precision) { + case PCAP_TSTAMP_PRECISION_NANO: + ticks_per_second = 1000000000; + break; + case PCAP_TSTAMP_PRECISION_MICRO: + default: + ticks_per_second = 1000000; + break; + + } pcap_header.ts.tv_sec = ts >> 32; - ts = (ts & 0xffffffffULL) * 1000000; + ts = (ts & 0xffffffffULL) * ticks_per_second; ts += 0x80000000; /* rounding */ - pcap_header.ts.tv_usec = ts >> 32; - if (pcap_header.ts.tv_usec >= 1000000) { - pcap_header.ts.tv_usec -= 1000000; + pcap_header.ts.tv_usec = ts >> 32; + if (pcap_header.ts.tv_usec >= ticks_per_second) { + pcap_header.ts.tv_usec -= ticks_per_second; pcap_header.ts.tv_sec++; } /* Fill in our own header data */ pcap_header.caplen = caplen; pcap_header.len = packet_len; - + /* Count the packet. */ pd->stat.ps_recv++; - + /* Call the user supplied callback function */ callback(user, &pcap_header, dp); - + /* Only count packets that pass the filter, for consistency with standard Linux behaviour. */ processed++; if (processed == cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) @@ -603,7 +623,7 @@ dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_) * device will result in a failure. The promisc flag is ignored because DAG * cards are always promiscuous. The to_ms parameter is used in setting the * API polling parameters. - * + * * snaplen is now also ignored, until we get per-stream slen support. Set * slen with approprite DAG tool BEFORE pcap_activate(). * @@ -639,7 +659,7 @@ static int dag_activate(pcap_t* handle) snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't allocate string for device name: %s\n", pcap_strerror(errno)); goto fail; } - + /* Parse input name to get dag device and stream number if provided */ if (dag_parse_name(device, newDev, strlen(device) + 16, &handlep->dag_stream) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: %s\n", pcap_strerror(errno)); @@ -685,7 +705,7 @@ static int dag_activate(pcap_t* handle) snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno)); goto faildetach; } - + if (handle->opt.immediate) { /* Call callback immediately. * XXX - is this the right way to handle this? @@ -710,7 +730,7 @@ static int dag_activate(pcap_t* handle) snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno)); goto faildetach; } - + #else if((handlep->dag_mem_base = dag_mmap(handle->fd)) == MAP_FAILED) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_mmap %s: %s\n", device, pcap_strerror(errno)); @@ -733,14 +753,14 @@ static int dag_activate(pcap_t* handle) handle->snapshot = MIN_DAG_SNAPLEN; } /* snap len has to be a multiple of 4 */ - snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3); + snprintf(conf, 30, "varlen slen=%d", (snaplen + 3) & ~3); if(dag_configure(handle->fd, conf) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,"dag_configure %s: %s\n", device, pcap_strerror(errno)); goto faildetach; } -#endif - +#endif + #ifdef HAVE_DAG_STREAMS_API if(dag_start_stream(handle->fd, handlep->dag_stream) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dag_start_stream %s: %s\n", device, pcap_strerror(errno)); @@ -807,7 +827,7 @@ static int dag_activate(pcap_t* handle) handle->linktype = -1; if (dag_get_datalink(handle) < 0) goto failstop; - + handle->bufsize = 0; if (new_pcap_dag(handle) < 0) { @@ -838,12 +858,12 @@ static int dag_activate(pcap_t* handle) handlep->stat.ps_ifdrop = 0; return 0; -#ifdef HAVE_DAG_STREAMS_API +#ifdef HAVE_DAG_STREAMS_API failstop: if (dag_stop_stream(handle->fd, handlep->dag_stream) < 0) { fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno)); } - + faildetach: if (dag_detach_stream(handle->fd, handlep->dag_stream) < 0) fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno)); @@ -852,7 +872,7 @@ failstop: if (dag_stop(handle->fd) < 0) fprintf(stderr,"dag_stop: %s\n", strerror(errno)); #endif /* HAVE_DAG_STREAMS_API */ - + failclose: if (dag_close(handle->fd) < 0) fprintf(stderr,"dag_close: %s\n", strerror(errno)); @@ -922,6 +942,26 @@ pcap_t *dag_create(const char *device, char *ebuf, int *is_ours) return NULL; p->activate_op = dag_activate; + + /* + * We claim that we support microsecond and nanosecond time + * stamps. + * + * XXX Our native precision is 2^-32s, but libpcap doesn't support + * power of two precisions yet. We can convert to either MICRO or NANO. + */ + p->tstamp_precision_count = 2; + p->tstamp_precision_list = malloc(2 * sizeof(u_int)); + if (p->tstamp_precision_list == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", + pcap_strerror(errno)); + if (p->tstamp_type_list != NULL) + free(p->tstamp_type_list); + free(p); + return NULL; + } + p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO; + p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO; return p; } @@ -934,9 +974,9 @@ dag_stats(pcap_t *p, struct pcap_stat *ps) { */ /*pd->stat.ps_recv = 0;*/ /*pd->stat.ps_drop = 0;*/ - + *ps = pd->stat; - + return 0; } @@ -958,6 +998,8 @@ dag_findalldevs(pcap_if_t **devlistp, char *errbuf) char dagname[DAGNAME_BUFSIZE]; int dagstream; int dagfd; + dag_card_inf_t *inf; + char *description; /* Try all the DAGs 0-DAG_MAX_BOARDS */ for (c = 0; c < DAG_MAX_BOARDS; c++) { @@ -966,8 +1008,11 @@ dag_findalldevs(pcap_if_t **devlistp, char *errbuf) { return -1; } + description = NULL; if ( (dagfd = dag_open(dagname)) >= 0 ) { - if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) { + if ((inf = dag_pciinfo(dagfd))) + description = dag_device_name(inf->device_code, 1); + if (pcap_add_if(devlistp, name, 0, description, errbuf) == -1) { /* * Failure. */ @@ -982,19 +1027,19 @@ dag_findalldevs(pcap_if_t **devlistp, char *errbuf) dag_detach_stream(dagfd, stream); snprintf(name, 10, "dag%d:%d", c, stream); - if (pcap_add_if(devlistp, name, 0, NULL, errbuf) == -1) { + if (pcap_add_if(devlistp, name, 0, description, errbuf) == -1) { /* * Failure. */ ret = -1; } - + rxstreams--; if(rxstreams <= 0) { break; } } - } + } } #endif /* HAVE_DAG_STREAMS_API */ dag_close(dagfd); @@ -1054,13 +1099,13 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) uint32_t mindata; struct timeval maxwait; struct timeval poll; - + if (dag_get_stream_poll(p->fd, pd->dag_stream, &mindata, &maxwait, &poll) < 0) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_get_stream_poll: %s\n", pcap_strerror(errno)); return -1; } - + /* Amount of data to collect in Bytes before calling callbacks. * Important for efficiency, but can introduce latency * at low packet rates if to_ms not set! @@ -1069,7 +1114,7 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) mindata = 0; else mindata = 65536; - + if (dag_set_stream_poll(p->fd, pd->dag_stream, mindata, &maxwait, &poll) < 0) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "dag_set_stream_poll: %s\n", pcap_strerror(errno)); @@ -1084,7 +1129,7 @@ dag_setnonblock(pcap_t *p, int nonblock, char *errbuf) } return (0); } - + static int dag_get_datalink(pcap_t *p) { @@ -1105,18 +1150,18 @@ dag_get_datalink(pcap_t *p) /* Get list of possible ERF types for this card */ if (dag_get_stream_erf_types(p->fd, pd->dag_stream, types, 255) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_stream_erf_types: %s", pcap_strerror(errno)); - return (-1); + return (-1); } - + while (types[index]) { #elif defined HAVE_DAG_GET_ERF_TYPES /* Get list of possible ERF types for this card */ if (dag_get_erf_types(p->fd, types, 255) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "dag_get_erf_types: %s", pcap_strerror(errno)); - return (-1); + return (-1); } - + while (types[index]) { #else /* Check the type through a dagapi call. */ @@ -1162,7 +1207,7 @@ dag_get_datalink(pcap_t *p) p->linktype = DLT_EN10MB; break; - case TYPE_ATM: + case TYPE_ATM: case TYPE_AAL5: case TYPE_MC_ATM: case TYPE_MC_AAL5: diff --git a/external/bsd/libpcap/dist/pcap-dbus.c b/external/bsd/libpcap/dist/pcap-dbus.c index c757e06eab87..a2464c3ee762 100644 --- a/external/bsd/libpcap/dist/pcap-dbus.c +++ b/external/bsd/libpcap/dist/pcap-dbus.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-dbus.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-dbus.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 2012 Jakub Zawadzki @@ -13,8 +13,8 @@ * 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. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @@ -31,7 +31,7 @@ */ #include -__RCSID("$NetBSD: pcap-dbus.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-dbus.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -127,7 +127,7 @@ dbus_write(pcap_t *handle, const void *buf, size_t size) dbus_message_unref(msg); return 0; -} +} static int dbus_stats(pcap_t *handle, struct pcap_stat *stats) @@ -255,8 +255,8 @@ dbus_create(const char *device, char *ebuf, int *is_ours) { pcap_t *p; - if (strcmp(device, "dbus-system") && - strcmp(device, "dbus-session") && + if (strcmp(device, "dbus-system") && + strcmp(device, "dbus-session") && strncmp(device, "dbus://", 7)) { *is_ours = 0; @@ -272,7 +272,7 @@ dbus_create(const char *device, char *ebuf, int *is_ours) return (p); } -int +int dbus_findalldevs(pcap_if_t **alldevsp, char *err_str) { if (pcap_add_if(alldevsp, "dbus-system", 0, "D-Bus system bus", err_str) < 0) diff --git a/external/bsd/libpcap/dist/pcap-dlpi.c b/external/bsd/libpcap/dist/pcap-dlpi.c index 9897aa739fd9..1fead0c79bca 100644 --- a/external/bsd/libpcap/dist/pcap-dlpi.c +++ b/external/bsd/libpcap/dist/pcap-dlpi.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-dlpi.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-dlpi.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 @@ -71,7 +71,7 @@ */ #include -__RCSID("$NetBSD: pcap-dlpi.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-dlpi.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -303,7 +303,7 @@ pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size) ret = -1; #endif /* raw mode */ return (ret); -} +} #ifndef DL_IPATM #define DL_IPATM 0x12 /* ATM Classical IP interface */ diff --git a/external/bsd/libpcap/dist/pcap-dos.c b/external/bsd/libpcap/dist/pcap-dos.c index 5e5c9e69c075..4b3512b5f57f 100644 --- a/external/bsd/libpcap/dist/pcap-dos.c +++ b/external/bsd/libpcap/dist/pcap-dos.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-dos.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-dos.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * This file is part of DOS-libpcap @@ -168,7 +168,7 @@ pcap_t *pcap_create_interface (const char *device, char *ebuf) * network packets. */ static int pcap_activate_dos (pcap_t *pcap) -{ +{ struct pcap_dos *pcapd = pcap->priv; if (pcap->opt.rfmon) { @@ -199,7 +199,7 @@ static int pcap_activate_dos (pcap_t *pcap) !first_init(pcap->opt.source, pcap->errbuf, pcap->opt.promisc)) { return (PCAP_ERROR); - } + } atexit (close_driver); } else if (stricmp(active_dev->name,pcap->opt.source)) @@ -403,7 +403,7 @@ int pcap_stats_ex (pcap_t *p, struct pcap_stat_ex *se) strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics", PCAP_ERRBUF_SIZE); return (-1); - } + } memcpy (se, (*dev->get_stats)(dev), sizeof(*se)); return (0); } @@ -522,7 +522,7 @@ int pcap_lookupnet (const char *device, bpf_u_int32 *localnet, } ARGSUSED (device); return (0); -} +} /* * Get a list of all interfaces that are present and that we probe okay. @@ -962,7 +962,7 @@ static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf) * have default values. Should be taken from another * ini-file/environment in any case (ref. tcpdump.ini) */ - _watt_is_init = 1; + _watt_is_init = 1; if (!using_pktdrv || !has_ip_addr) /* for now .... */ { @@ -1094,7 +1094,7 @@ static int pkt_open (struct device *dev) if (!PktInitDriver(mode)) return (0); - + PktResetStatistics (pktInfo.handle); PktQueueBusy (FALSE); return (1); @@ -1292,7 +1292,7 @@ struct device rtl8139_dev LOCKED_VAR = { 0,0,0,0,0,0, &cs89_dev, rtl8139_probe /* dev->probe routine */ - }; + }; /* * Dequeue routine is called by polling. diff --git a/external/bsd/libpcap/dist/pcap-dos.h b/external/bsd/libpcap/dist/pcap-dos.h index b14798252923..96ccec899531 100644 --- a/external/bsd/libpcap/dist/pcap-dos.h +++ b/external/bsd/libpcap/dist/pcap-dos.h @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-dos.h,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-dos.h,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Internal details for libpcap on DOS. @@ -216,7 +216,7 @@ extern void _w32_os_yield (void); /* Watt-32's misc.c */ #define PCAP_ASSERT(x) ((void)0) #else - void pcap_assert (const char *what, const char *file, unsigned line); + void pcap_assert (const char *what, const char *file, unsigned line); #define PCAP_ASSERT(x) do { \ if (!(x)) \ diff --git a/external/bsd/libpcap/dist/pcap-int.h b/external/bsd/libpcap/dist/pcap-int.h index 4278394cb9fe..4f79e6f78779 100644 --- a/external/bsd/libpcap/dist/pcap-int.h +++ b/external/bsd/libpcap/dist/pcap-int.h @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-int.h,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-int.h,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 1994, 1995, 1996 @@ -204,6 +204,11 @@ struct pcap { /* We're accepting only packets in this direction/these directions. */ pcap_direction_t direction; + /* + * Flags to affect BPF code generation. + */ + int bpf_codegen_flags; + /* * Placeholder for filter code if bpf not in kernel. */ @@ -250,6 +255,11 @@ struct pcap { cleanup_op_t cleanup_op; }; +/* + * BPF code generation flags. + */ +#define BPF_SPECIAL_VLAN_HANDLING 0x00000001 /* special VLAN handling for Linux */ + /* * This is a timeval as stored in a savefile. * It has to use the same types everywhere, independent of the actual diff --git a/external/bsd/libpcap/dist/pcap-linux.c b/external/bsd/libpcap/dist/pcap-linux.c index ac95384140b0..82b7be5c396a 100644 --- a/external/bsd/libpcap/dist/pcap-linux.c +++ b/external/bsd/libpcap/dist/pcap-linux.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-linux.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * pcap-linux.c: Packet capture interface to the Linux kernel @@ -27,10 +27,10 @@ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Modifications: Added PACKET_MMAP support - * Paolo Abeni + * Paolo Abeni * Added TPACKET_V3 support * Gabor Tatarka - * + * * based on previous works of: * Simon Patarin * Phil Wood @@ -49,7 +49,7 @@ * 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. + * 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. @@ -58,12 +58,12 @@ * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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. + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR 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, + * 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. @@ -115,7 +115,7 @@ #define _GNU_SOURCE #include -__RCSID("$NetBSD: pcap-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-linux.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -193,9 +193,10 @@ __RCSID("$NetBSD: pcap-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); # endif /* PACKET_HOST */ - /* check for memory mapped access avaibility. We assume every needed + /* check for memory mapped access avaibility. We assume every needed * struct is defined if the macro TPACKET_HDRLEN is defined, because it * uses many ring related structs and macros */ +# ifdef PCAP_SUPPORT_PACKET_RING # ifdef TPACKET_HDRLEN # define HAVE_PACKET_RING # ifdef TPACKET3_HDRLEN @@ -207,6 +208,7 @@ __RCSID("$NetBSD: pcap-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); # define TPACKET_V1 0 /* Old kernel with only V1, so no TPACKET_Vn defined */ # endif /* TPACKET2_HDRLEN */ # endif /* TPACKET_HDRLEN */ +# endif /* PCAP_SUPPORT_PACKET_RING */ #endif /* PF_PACKET */ #ifdef SO_ATTACH_FILTER @@ -321,7 +323,7 @@ struct pcap_linux { /* * Prototypes for internal functions and methods. */ -static void map_arphrd_to_dlt(pcap_t *, int, const char *, int); +static void map_arphrd_to_dlt(pcap_t *, int, int, const char *, int); #ifdef HAVE_PF_PACKET_SOCKETS static short int map_packet_type_to_sll_type(short int); #endif @@ -339,8 +341,30 @@ static int pcap_setdirection_linux(pcap_t *, pcap_direction_t); static int pcap_set_datalink_linux(pcap_t *, int); static void pcap_cleanup_linux(pcap_t *); +/* + * This is what the header structure looks like in a 64-bit kernel; + * we use this, rather than struct tpacket_hdr, if we're using + * TPACKET_V1 in 32-bit code running on a 64-bit kernel. + */ +struct tpacket_hdr_64 { + uint64_t tp_status; + unsigned int tp_len; + unsigned int tp_snaplen; + unsigned short tp_mac; + unsigned short tp_net; + unsigned int tp_sec; + unsigned int tp_usec; +}; + +/* + * We use this internally as the tpacket version for TPACKET_V1 in + * 32-bit code on a 64-bit kernel. + */ +#define TPACKET_V1_64 99 + union thdr { struct tpacket_hdr *h1; + struct tpacket_hdr_64 *h1_64; #ifdef HAVE_TPACKET2 struct tpacket2_hdr *h2; #endif @@ -358,6 +382,7 @@ static int create_ring(pcap_t *handle, int *status); static int prepare_tpacket_socket(pcap_t *handle); static void pcap_cleanup_linux_mmap(pcap_t *); static int pcap_read_linux_mmap_v1(pcap_t *, int, pcap_handler , u_char *); +static int pcap_read_linux_mmap_v1_64(pcap_t *, int, pcap_handler , u_char *); #ifdef HAVE_TPACKET2 static int pcap_read_linux_mmap_v2(pcap_t *, int, pcap_handler , u_char *); #endif @@ -371,6 +396,12 @@ static void pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes); #endif +#ifdef TP_STATUS_VLAN_TPID_VALID +# define VLAN_TPID(hdr, hv) (((hv)->tp_vlan_tpid || ((hdr)->tp_status & TP_STATUS_VLAN_TPID_VALID)) ? (hv)->tp_vlan_tpid : ETH_P_8021Q) +#else +# define VLAN_TPID(hdr, hv) ETH_P_8021Q +#endif + /* * Wrap some ioctl calls */ @@ -387,7 +418,12 @@ static int has_wext(int sock_fd, const char *device, char *ebuf); static int enter_rfmon_mode(pcap_t *handle, int sock_fd, const char *device); #endif /* HAVE_PF_PACKET_SOCKETS */ +#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP) +static int iface_ethtool_get_ts_info(pcap_t *handle, char *ebuf); +#endif +#ifdef HAVE_PACKET_RING static int iface_get_offload(pcap_t *handle); +#endif static int iface_bind_old(int fd, const char *device, char *ebuf); #ifdef SO_ATTACH_FILTER @@ -414,28 +450,15 @@ pcap_create_interface(const char *device, char *ebuf) handle->activate_op = pcap_activate_linux; handle->can_set_rfmon_op = pcap_can_set_rfmon_linux; + #if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP) /* - * We claim that we support: - * - * software time stamps, with no details about their precision; - * hardware time stamps, synced to the host time; - * hardware time stamps, not synced to the host time. - * - * XXX - we can't ask a device whether it supports - * hardware time stamps, so we just claim all devices do. + * See what time stamp types we support. */ - handle->tstamp_type_count = 3; - handle->tstamp_type_list = malloc(3 * sizeof(u_int)); - if (handle->tstamp_type_list == NULL) { - snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", - pcap_strerror(errno)); + if (iface_ethtool_get_ts_info(handle, ebuf) == -1) { free(handle); return NULL; } - handle->tstamp_type_list[0] = PCAP_TSTAMP_HOST; - handle->tstamp_type_list[1] = PCAP_TSTAMP_ADAPTER; - handle->tstamp_type_list[2] = PCAP_TSTAMP_ADAPTER_UNSYNCED; #endif #if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS) @@ -1014,7 +1037,7 @@ linux_if_drops(const char * if_name) FILE * file; int field_to_convert = 3, if_name_sz = strlen(if_name); long int dropped_pkts = 0; - + file = fopen("/proc/net/dev", "r"); if (!file) return 0; @@ -1029,7 +1052,7 @@ linux_if_drops(const char * if_name) field_to_convert = 4; continue; } - + /* find iface and make sure it actually matches -- space before the name and : after it */ if ((bufptr = strstr(buffer, if_name)) && (bufptr == buffer || *(bufptr-1) == ' ') && @@ -1043,20 +1066,20 @@ linux_if_drops(const char * if_name) while (*bufptr != '\0' && *(bufptr++) == ' '); while (*bufptr != '\0' && *(bufptr++) != ' '); } - + /* get rid of any final spaces */ while (*bufptr != '\0' && *bufptr == ' ') bufptr++; - + if (*bufptr != '\0') dropped_pkts = strtol(bufptr, NULL, 10); break; } } - + fclose(file); return dropped_pkts; -} +} /* @@ -1291,12 +1314,12 @@ pcap_activate_linux(pcap_t *handle) pcap_strerror(errno) ); return PCAP_ERROR; } - + /* copy timeout value */ handlep->timeout = handle->opt.timeout; /* - * If we're in promiscuous mode, then we probably want + * If we're in promiscuous mode, then we probably want * to see when the interface drops packets too, so get an * initial count from /proc/net/dev */ @@ -1499,6 +1522,7 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) int packet_len, caplen; struct pcap_pkthdr pcap_header; + struct bpf_aux_data aux_data; #ifdef HAVE_PF_PACKET_SOCKETS /* * If this is a cooked device, leave extra room for a @@ -1679,9 +1703,14 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset); tag = (struct vlan_tag *)(bp + handlep->vlan_offset); - tag->vlan_tpid = htons(ETH_P_8021Q); + tag->vlan_tpid = htons(VLAN_TPID(aux, aux)); tag->vlan_tci = htons(aux->tp_vlan_tci); + /* store vlan tci to bpf_aux_data struct for userland bpf filter */ +#if defined(TP_STATUS_VLAN_VALID) + aux_data.vlan_tag = htons(aux->tp_vlan_tci) & 0x0fff; + aux_data.vlan_tag_present = (aux->tp_status & TP_STATUS_VLAN_VALID); +#endif packet_len += VLAN_TAG_LEN; } } @@ -1726,9 +1755,8 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) /* Run the packet filter if not using kernel filter */ if (handlep->filter_in_userland && handle->fcode.bf_insns) { - if (bpf_filter(handle->fcode.bf_insns, bp, - packet_len, caplen) == 0) - { + if (bpf_filter_with_aux_data(handle->fcode.bf_insns, bp, + packet_len, caplen, &aux_data) == 0) { /* rejected by filter */ return 0; } @@ -1851,7 +1879,7 @@ pcap_inject_linux(pcap_t *handle, const void *buf, size_t size) return (-1); } return (ret); -} +} /* * Get the statistics for the given packet capture handle. @@ -1889,8 +1917,8 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats) #endif /* HAVE_TPACKET_STATS */ long if_dropped = 0; - - /* + + /* * To fill in ps_ifdrop, we parse /proc/net/dev for the number */ if (handle->opt.promisc) @@ -1920,7 +1948,7 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats) * dropped by the interface driver. It counts only * packets that passed the filter. * - * See above for ps_ifdrop. + * See above for ps_ifdrop. * * Both statistics include packets not yet read from * the kernel by libpcap, and thus not yet seen by @@ -1949,7 +1977,7 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats) * "tp_packets" as the count of packets and "tp_drops" * as the count of drops. * - * Keep a running total because each call to + * Keep a running total because each call to * getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS, .... * resets the counters to zero. */ @@ -1995,10 +2023,10 @@ pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats) * We maintain the count of packets processed by libpcap in * "handlep->packets_read", for reasons described in the comment * at the end of pcap_read_packet(). We have no idea how many - * packets were dropped by the kernel buffers -- but we know + * packets were dropped by the kernel buffers -- but we know * how many the interface dropped, so we can return that. */ - + stats->ps_recv = handlep->packets_read; stats->ps_drop = 0; stats->ps_ifdrop = handlep->stat.ps_ifdrop; @@ -2483,8 +2511,14 @@ pcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter, * calling "pcap_setfilter()". Otherwise, the kernel filter may * filter out packets that would pass the new userland filter. */ - if (handlep->filter_in_userland) - reset_kernel_filter(handle); + if (handlep->filter_in_userland) { + if (reset_kernel_filter(handle) == -1) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "can't remove kernel filter: %s", + pcap_strerror(errno)); + err = -2; /* fatal error */ + } + } /* * Free up the copy of the filter that was made by "fix_program()". @@ -2566,6 +2600,51 @@ map_packet_type_to_sll_type(short int sll_pkttype) } #endif +static int +is_wifi(int sock_fd +#ifndef IW_MODE_MONITOR +_U_ +#endif +, const char *device) +{ + char *pathstr; + struct stat statb; +#ifdef IW_MODE_MONITOR + char errbuf[PCAP_ERRBUF_SIZE]; +#endif + + /* + * See if there's a sysfs wireless directory for it. + * If so, it's a wireless interface. + */ + if (asprintf(&pathstr, "/sys/class/net/%s/wireless", device) == -1) { + /* + * Just give up here. + */ + return 0; + } + if (stat(pathstr, &statb) == 0) { + free(pathstr); + return 1; + } + free(pathstr); + +#ifdef IW_MODE_MONITOR + /* + * OK, maybe it's not wireless, or maybe this kernel doesn't + * support sysfs. Try the wireless extensions. + */ + if (has_wext(sock_fd, device, errbuf) == 1) { + /* + * It supports the wireless extensions, so it's a Wi-Fi + * device. + */ + return 1; + } +#endif + return 0; +} + /* * Linux uses the ARP hardware type to identify the type of an * interface. pcap uses the DLT_xxx constants for this. This @@ -2584,8 +2663,8 @@ map_packet_type_to_sll_type(short int sll_pkttype) * * Sets the link type to -1 if unable to map the type. */ -static void map_arphrd_to_dlt(pcap_t *handle, int arptype, const char *device, - int cooked_ok) +static void map_arphrd_to_dlt(pcap_t *handle, int sock_fd, int arptype, + const char *device, int cooked_ok) { static const char cdma_rmnet[] = "cdma_rmnet"; @@ -2596,7 +2675,7 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, const char *device, * For various annoying reasons having to do with DHCP * software, some versions of Android give the mobile- * phone-network interface an ARPHRD_ value of - * ARPHRD_ETHER, even though the packet supplied by + * ARPHRD_ETHER, even though the packets supplied by * that interface have no link-layer header, and begin * with an IP header, so that the ARPHRD_ value should * be ARPHRD_NONE. @@ -2608,9 +2687,9 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, const char *device, handle->linktype = DLT_RAW; return; } - + /* - * This is (presumably) a real Ethernet capture; give it a + * Is this a real Ethernet device? If so, give it a * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so * that an application can let you choose it, in case you're * capturing DOCSIS traffic that a Cisco Cable Modem @@ -2619,21 +2698,27 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, const char *device, * DOCSIS frames out on the wire inside the low-level * Ethernet framing). * - * XXX - are there any sorts of "fake Ethernet" that have - * ARPHRD_ETHER but that *shouldn't offer DLT_DOCSIS as + * XXX - are there any other sorts of "fake Ethernet" that + * have ARPHRD_ETHER but that shouldn't offer DLT_DOCSIS as * a Cisco CMTS won't put traffic onto it or get traffic * bridged onto it? ISDN is handled in "activate_new()", - * as we fall back on cooked mode there; are there any + * as we fall back on cooked mode there, and we use + * is_wifi() to check for 802.11 devices; are there any * others? */ - handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); - /* - * If that fails, just leave the list empty. - */ - if (handle->dlt_list != NULL) { - handle->dlt_list[0] = DLT_EN10MB; - handle->dlt_list[1] = DLT_DOCSIS; - handle->dlt_count = 2; + if (!is_wifi(sock_fd, device)) { + /* + * It's not a Wi-Fi device; offer DOCSIS. + */ + handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); + /* + * If that fails, just leave the list empty. + */ + if (handle->dlt_list != NULL) { + handle->dlt_list[0] = DLT_EN10MB; + handle->dlt_list[1] = DLT_DOCSIS; + handle->dlt_count = 2; + } } /* FALLTHROUGH */ @@ -3019,6 +3104,10 @@ activate_new(pcap_t *handle) #endif int err = 0; struct packet_mreq mr; +#ifdef SO_BPF_EXTENSIONS + int bpf_extensions; + socklen_t len = sizeof(bpf_extensions); +#endif /* * Open a socket with protocol family packet. If the @@ -3122,7 +3211,7 @@ activate_new(pcap_t *handle) close(sock_fd); return arptype; } - map_arphrd_to_dlt(handle, arptype, device, 1); + map_arphrd_to_dlt(handle, sock_fd, arptype, device, 1); if (handle->linktype == -1 || handle->linktype == DLT_LINUX_SLL || handle->linktype == DLT_LINUX_IRDA || @@ -3349,6 +3438,23 @@ activate_new(pcap_t *handle) */ handle->fd = sock_fd; +#ifdef SO_BPF_EXTENSIONS + /* + * Can we generate special code for VLAN checks? + * (XXX - what if we need the special code but it's not supported + * by the OS? Is that possible?) + */ + if (getsockopt(sock_fd, SOL_SOCKET, SO_BPF_EXTENSIONS, + &bpf_extensions, &len) == 0) { + if (bpf_extensions >= SKF_AD_VLAN_TAG_PRESENT) { + /* + * Yes, we can. Request that we do so. + */ + handle->bpf_codegen_flags |= BPF_SPECIAL_VLAN_HANDLING; + } + } +#endif /* SO_BPF_EXTENSIONS */ + return 1; #else /* HAVE_PF_PACKET_SOCKETS */ strlcpy(ebuf, @@ -3371,7 +3477,7 @@ activate_new(pcap_t *handle) * On error, returns -1, and sets *status to the appropriate error code; * if that is PCAP_ERROR, sets handle->errbuf to the appropriate message. */ -static int +static int activate_mmap(pcap_t *handle, int *status) { struct pcap_linux *handlep = handle->priv; @@ -3432,6 +3538,9 @@ activate_mmap(pcap_t *handle, int *status) case TPACKET_V1: handle->read_op = pcap_read_linux_mmap_v1; break; + case TPACKET_V1_64: + handle->read_op = pcap_read_linux_mmap_v1_64; + break; #ifdef HAVE_TPACKET2 case TPACKET_V2: handle->read_op = pcap_read_linux_mmap_v2; @@ -3452,7 +3561,7 @@ activate_mmap(pcap_t *handle, int *status) return 1; } #else /* HAVE_PACKET_RING */ -static int +static int activate_mmap(pcap_t *handle _U_, int *status _U_) { return 0; @@ -3476,7 +3585,10 @@ init_tpacket(pcap_t *handle, int version, const char *version_str) int val = version; socklen_t len = sizeof(val); - /* Probe whether kernel supports the specified TPACKET version */ + /* + * Probe whether kernel supports the specified TPACKET version; + * this also gets the length of the header for that version. + */ if (getsockopt(handle->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) { if (errno == ENOPROTOOPT || errno == EINVAL) return 1; /* no */ @@ -3515,6 +3627,36 @@ init_tpacket(pcap_t *handle, int version, const char *version_str) } #endif /* defined HAVE_TPACKET2 || defined HAVE_TPACKET3 */ +/* + * If the instruction set for which we're compiling has both 32-bit + * and 64-bit versions, and Linux support for the 64-bit version + * predates TPACKET_V2, define ISA_64_BIT as the .machine value + * you get from uname() for the 64-bit version. Otherwise, leave + * it undefined. (This includes ARM, which has a 64-bit version, + * but Linux support for it appeared well after TPACKET_V2 support + * did, so there should never be a case where 32-bit ARM code is + * running o a 64-bit kernel that only supports TPACKET_V1.) + * + * If we've omitted your favorite such architecture, please contribute + * a patch. (No patch is needed for architectures that are 32-bit-only + * or for which Linux has no support for 32-bit userland - or for which, + * as noted, 64-bit support appeared in Linux after TPACKET_V2 support + * did.) + */ +#if defined(__i386__) +#define ISA_64_BIT "x86_64" +#elif defined(__ppc__) +#define ISA_64_BIT "ppc64" +#elif defined(__sparc__) +#define ISA_64_BIT "sparc64" +#elif defined(__s390__) +#define ISA_64_BIT "s390x" +#elif defined(__mips__) +#define ISA_64_BIT "mips64" +#elif defined(__hppa__) +#define ISA_64_BIT "parisc64" +#endif + /* * Attempt to set the socket to version 3 of the memory-mapped header and, * if that fails because version 3 isn't supported, attempt to fall @@ -3532,11 +3674,10 @@ prepare_tpacket_socket(pcap_t *handle) int ret; #endif - handlep->tp_version = TPACKET_V1; - handlep->tp_hdrlen = sizeof(struct tpacket_hdr); - #ifdef HAVE_TPACKET3 /* + * Try setting the version to TPACKET_V3. + * * The only mode in which buffering is done on PF_PACKET * sockets, so that packets might not be delivered * immediately, is TPACKET_V3 mode. @@ -3545,28 +3686,87 @@ prepare_tpacket_socket(pcap_t *handle) * if the user has requested immediate mode, we don't * use TPACKET_V3. */ - if (handle->opt.immediate) - ret = 1; /* pretend TPACKET_V3 couldn't be set */ - else + if (!handle->opt.immediate) { ret = init_tpacket(handle, TPACKET_V3, "TPACKET_V3"); - if (-1 == ret) { - /* Error during setting up TPACKET_V3. */ - return -1; - } else if (1 == ret) { - /* TPACKET_V3 not supported - fall back to TPACKET_V2. */ + if (ret == 0) { + /* + * Success. + */ + return 1; + } + if (ret == -1) { + /* + * We failed for some reason other than "the + * kernel doesn't support TPACKET_V3". + */ + return -1; + } + } #endif /* HAVE_TPACKET3 */ #ifdef HAVE_TPACKET2 - ret = init_tpacket(handle, TPACKET_V2, "TPACKET_V2"); - if (-1 == ret) { - /* Error during setting up TPACKET_V2. */ - return -1; - } + /* + * Try setting the version to TPACKET_V2. + */ + ret = init_tpacket(handle, TPACKET_V2, "TPACKET_V2"); + if (ret == 0) { + /* + * Success. + */ + return 1; + } + if (ret == -1) { + /* + * We failed for some reason other than "the + * kernel doesn't support TPACKET_V2". + */ + return -1; + } #endif /* HAVE_TPACKET2 */ -#ifdef HAVE_TPACKET3 + /* + * OK, we're using TPACKET_V1, as that's all the kernel supports. + */ + handlep->tp_version = TPACKET_V1; + handlep->tp_hdrlen = sizeof(struct tpacket_hdr); + +#ifdef ISA_64_BIT + /* + * 32-bit userspace + 64-bit kernel + TPACKET_V1 are not compatible with + * each other due to platform-dependent data type size differences. + * + * If we have a 32-bit userland and a 64-bit kernel, use an + * internally-defined TPACKET_V1_64, with which we use a 64-bit + * version of the data structures. + */ + if (sizeof(long) == 4) { + /* + * This is 32-bit code. + */ + struct utsname utsname; + + if (uname(&utsname) == -1) { + /* + * Failed. + */ + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "uname failed: %s", pcap_strerror(errno)); + return -1; + } + if (strcmp(utsname.machine, ISA_64_BIT) == 0) { + /* + * uname() tells us the machine is 64-bit, + * so we presumably have a 64-bit kernel. + * + * XXX - this presumes that uname() won't lie + * in 32-bit code and claim that the machine + * has the 32-bit version of the ISA. + */ + handlep->tp_version = TPACKET_V1_64; + handlep->tp_hdrlen = sizeof(struct tpacket_hdr_64); + } } -#endif /* HAVE_TPACKET3 */ +#endif return 1; } @@ -3610,6 +3810,7 @@ create_ring(pcap_t *handle, int *status) switch (handlep->tp_version) { case TPACKET_V1: + case TPACKET_V1_64: #ifdef HAVE_TPACKET2 case TPACKET_V2: #endif @@ -3741,14 +3942,20 @@ create_ring(pcap_t *handle, int *status) req.tp_frame_nr = handle->opt.buffer_size/req.tp_frame_size; break; #endif + default: + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "Internal error: unknown TPACKET_ value %u", + handlep->tp_version); + *status = PCAP_ERROR; + return -1; } - /* compute the minumum block size that will handle this frame. - * The block has to be page size aligned. - * The max block size allowed by the kernel is arch-dependent and + /* compute the minumum block size that will handle this frame. + * The block has to be page size aligned. + * The max block size allowed by the kernel is arch-dependent and * it's not explicitly checked here. */ req.tp_block_size = getpagesize(); - while (req.tp_block_size < req.tp_frame_size) + while (req.tp_block_size < req.tp_frame_size) req.tp_block_size <<= 1; frames_per_block = req.tp_block_size/req.tp_frame_size; @@ -3846,8 +4053,8 @@ create_ring(pcap_t *handle, int *status) } if (setsockopt(handle->fd, SOL_PACKET, PACKET_TIMESTAMP, (void *)×ource, sizeof(timesource))) { - snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, - "can't set PACKET_TIMESTAMP: %s", + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "can't set PACKET_TIMESTAMP: %s", pcap_strerror(errno)); *status = PCAP_ERROR; return -1; @@ -3862,7 +4069,7 @@ retry: /* req.tp_frame_nr is requested to match frames_per_block*req.tp_block_nr */ req.tp_frame_nr = req.tp_block_nr * frames_per_block; - + #ifdef HAVE_TPACKET3 /* timeout value to retire block - use the configured buffering timeout, or default if <0. */ req.tp_retire_blk_tov = (handlep->timeout>=0)?handlep->timeout:0; @@ -3954,13 +4161,14 @@ destroy_ring(pcap_t *handle) /* tell the kernel to destroy the ring*/ struct tpacket_req req; memset(&req, 0, sizeof(req)); - setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING, + /* do not test for setsockopt failure, as we can't recover from any error */ + (void)setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING, (void *) &req, sizeof(req)); /* if ring is mapped, unmap it*/ if (handlep->mmapbuf) { /* do not test for mmap failure, as we can't recover from any error */ - munmap(handlep->mmapbuf, handlep->mmapbuflen); + (void)munmap(handlep->mmapbuf, handlep->mmapbuflen); handlep->mmapbuf = NULL; } } @@ -3994,7 +4202,7 @@ pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h, memcpy(handlep->oneshot_buffer, bytes, h->caplen); *sp->pkt = handlep->oneshot_buffer; } - + static void pcap_cleanup_linux_mmap( pcap_t *handle ) { @@ -4063,6 +4271,11 @@ pcap_get_ring_frame(pcap_t *handle, int status) TP_STATUS_KERNEL)) return NULL; break; + case TPACKET_V1_64: + if (status != (h.h1_64->tp_status ? TP_STATUS_USER : + TP_STATUS_KERNEL)) + return NULL; + break; #ifdef HAVE_TPACKET2 case TPACKET_V2: if (status != (h.h2->tp_status ? TP_STATUS_USER : @@ -4207,7 +4420,8 @@ static int pcap_handle_packet_mmap( unsigned int tp_sec, unsigned int tp_usec, int tp_vlan_tci_valid, - __u16 tp_vlan_tci) + __u16 tp_vlan_tci, + __u16 tp_vlan_tpid) { struct pcap_linux *handlep = handle->priv; unsigned char *bp; @@ -4218,7 +4432,7 @@ static int pcap_handle_packet_mmap( if (tp_mac + tp_snaplen > handle->bufsize) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "corrupted frame on kernel ring mac " - "offset %d + caplen %d > frame len %d", + "offset %u + caplen %u > frame len %d", tp_mac, tp_snaplen, handle->bufsize); return -1; } @@ -4233,22 +4447,9 @@ static int pcap_handle_packet_mmap( * the filter when the ring became empty, but it can possibly * happen a lot later... */ bp = frame + tp_mac; - if (handlep->filter_in_userland && handle->fcode.bf_insns && - (bpf_filter(handle->fcode.bf_insns, bp, - tp_len, tp_snaplen) == 0)) - return 0; - - sll = (void *)frame + TPACKET_ALIGN(handlep->tp_hdrlen); - if (!linux_check_direction(handle, sll)) - return 0; - - /* get required packet info from ring header */ - pcaphdr.ts.tv_sec = tp_sec; - pcaphdr.ts.tv_usec = tp_usec; - pcaphdr.caplen = tp_snaplen; - pcaphdr.len = tp_len; /* if required build in place the sll header*/ + sll = (void *)frame + TPACKET_ALIGN(handlep->tp_hdrlen); if (handlep->cooked) { struct sll_header *hdrp; @@ -4261,7 +4462,7 @@ static int pcap_handle_packet_mmap( */ bp -= SLL_HDR_LEN; - /*/* + /* * Let's make sure that's past the end of * the tpacket header, i.e. >= * ((u_char *)thdr + TPACKET_HDRLEN), so we @@ -4286,7 +4487,30 @@ static int pcap_handle_packet_mmap( hdrp->sll_halen = htons(sll->sll_halen); memcpy(hdrp->sll_addr, sll->sll_addr, SLL_ADDRLEN); hdrp->sll_protocol = sll->sll_protocol; + } + if (handlep->filter_in_userland && handle->fcode.bf_insns) { + struct bpf_aux_data aux_data; + + aux_data.vlan_tag = tp_vlan_tci & 0x0fff; + aux_data.vlan_tag_present = tp_vlan_tci_valid; + + if (bpf_filter_with_aux_data(handle->fcode.bf_insns, bp, + tp_len, tp_snaplen, &aux_data) == 0) + return 0; + } + + if (!linux_check_direction(handle, sll)) + return 0; + + /* get required packet info from ring header */ + pcaphdr.ts.tv_sec = tp_sec; + pcaphdr.ts.tv_usec = tp_usec; + pcaphdr.caplen = tp_snaplen; + pcaphdr.len = tp_len; + + /* if required build in place the sll header*/ + if (handlep->cooked) { /* update packet len */ pcaphdr.caplen += SLL_HDR_LEN; pcaphdr.len += SLL_HDR_LEN; @@ -4303,7 +4527,7 @@ static int pcap_handle_packet_mmap( memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset); tag = (struct vlan_tag *)(bp + handlep->vlan_offset); - tag->vlan_tpid = htons(ETH_P_8021Q); + tag->vlan_tpid = htons(tp_vlan_tpid); tag->vlan_tci = htons(tp_vlan_tci); pcaphdr.caplen += VLAN_TAG_LEN; @@ -4363,6 +4587,7 @@ pcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback, h.h1->tp_sec, h.h1->tp_usec, 0, + 0, 0); if (ret == 1) { pkts++; @@ -4402,6 +4627,80 @@ pcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback, return pkts; } +static int +pcap_read_linux_mmap_v1_64(pcap_t *handle, int max_packets, pcap_handler callback, + u_char *user) +{ + struct pcap_linux *handlep = handle->priv; + int pkts = 0; + int ret; + + /* wait for frames availability.*/ + ret = pcap_wait_for_frames_mmap(handle); + if (ret) { + return ret; + } + + /* non-positive values of max_packets are used to require all + * packets currently available in the ring */ + while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) { + union thdr h; + + h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER); + if (!h.raw) + break; + + ret = pcap_handle_packet_mmap( + handle, + callback, + user, + h.raw, + h.h1_64->tp_len, + h.h1_64->tp_mac, + h.h1_64->tp_snaplen, + h.h1_64->tp_sec, + h.h1_64->tp_usec, + 0, + 0, + 0); + if (ret == 1) { + pkts++; + handlep->packets_read++; + } else if (ret < 0) { + return ret; + } + + /* + * Hand this block back to the kernel, and, if we're + * counting blocks that need to be filtered in userland + * after having been filtered by the kernel, count + * the one we've just processed. + */ + h.h1_64->tp_status = TP_STATUS_KERNEL; + if (handlep->blocks_to_filter_in_userland > 0) { + handlep->blocks_to_filter_in_userland--; + if (handlep->blocks_to_filter_in_userland == 0) { + /* + * No more blocks need to be filtered + * in userland. + */ + handlep->filter_in_userland = 0; + } + } + + /* next block */ + if (++handle->offset >= handle->cc) + handle->offset = 0; + + /* check for break loop condition*/ + if (handle->break_loop) { + handle->break_loop = 0; + return PCAP_ERROR_BREAK; + } + } + return pkts; +} + #ifdef HAVE_TPACKET2 static int pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback, @@ -4441,7 +4740,8 @@ pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback, #else h.h2->tp_vlan_tci != 0, #endif - h.h2->tp_vlan_tci); + h.h2->tp_vlan_tci, + VLAN_TPID(h.h2, h.h2)); if (ret == 1) { pkts++; handlep->packets_read++; @@ -4542,7 +4842,8 @@ again: #else tp3_hdr->hv1.tp_vlan_tci != 0, #endif - tp3_hdr->hv1.tp_vlan_tci); + tp3_hdr->hv1.tp_vlan_tci, + VLAN_TPID(tp3_hdr, &tp3_hdr->hv1)); if (ret == 1) { pkts++; handlep->packets_read++; @@ -4595,7 +4896,7 @@ again: } #endif /* HAVE_TPACKET3 */ -static int +static int pcap_setfilter_linux_mmap(pcap_t *handle, struct bpf_program *filter) { struct pcap_linux *handlep = handle->priv; @@ -5457,6 +5758,121 @@ enter_rfmon_mode(pcap_t *handle, int sock_fd, const char *device) return 0; } +#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP) +/* + * Map SOF_TIMESTAMPING_ values to PCAP_TSTAMP_ values. + */ +static const struct { + int soft_timestamping_val; + int pcap_tstamp_val; +} sof_ts_type_map[3] = { + { SOF_TIMESTAMPING_SOFTWARE, PCAP_TSTAMP_HOST }, + { SOF_TIMESTAMPING_SYS_HARDWARE, PCAP_TSTAMP_ADAPTER }, + { SOF_TIMESTAMPING_RAW_HARDWARE, PCAP_TSTAMP_ADAPTER_UNSYNCED } +}; +#define NUM_SOF_TIMESTAMPING_TYPES (sizeof sof_ts_type_map / sizeof sof_ts_type_map[0]) + +static void +iface_set_default_ts_types(pcap_t *handle) +{ + int i; + + handle->tstamp_type_count = NUM_SOF_TIMESTAMPING_TYPES; + handle->tstamp_type_list = malloc(NUM_SOF_TIMESTAMPING_TYPES * sizeof(u_int)); + for (i = 0; i < NUM_SOF_TIMESTAMPING_TYPES; i++) + handle->tstamp_type_list[i] = sof_ts_type_map[i].pcap_tstamp_val; +} + +#ifdef ETHTOOL_GET_TS_INFO +/* + * Get a list of time stamping capabilities. + */ +static int +iface_ethtool_get_ts_info(pcap_t *handle, char *ebuf) +{ + int fd; + struct ifreq ifr; + struct ethtool_ts_info info; + int num_ts_types; + int i, j; + + /* + * This doesn't apply to the "any" device; you have to ask + * specific devices for their capabilities, so just default + * to saying we support all of them. + */ + if (strcmp(handle->opt.source, "any") == 0) { + iface_set_default_ts_types(handle); + return 0; + } + + /* + * Create a socket from which to fetch time stamping capabilities. + */ + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, + "socket for SIOCETHTOOL(ETHTOOL_GET_TS_INFO): %s", pcap_strerror(errno)); + return -1; + } + + memset(&ifr, 0, sizeof(ifr)); + strlcpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name)); + memset(&info, 0, sizeof(info)); + info.cmd = ETHTOOL_GET_TS_INFO; + ifr.ifr_data = (caddr_t)&info; + if (ioctl(fd, SIOCETHTOOL, &ifr) == -1) { + close(fd); + if (errno == EOPNOTSUPP || errno == EINVAL) { + /* + * OK, let's just return all the possible time + * stamping types. + */ + iface_set_default_ts_types(handle); + return 0; + } + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "%s: SIOCETHTOOL(ETHTOOL_GET_TS_INFO) ioctl failed: %s", handle->opt.source, + strerror(errno)); + return -1; + } + close(fd); + + num_ts_types = 0; + for (i = 0; i < NUM_SOF_TIMESTAMPING_TYPES; i++) { + if (info.so_timestamping & sof_ts_type_map[i].soft_timestamping_val) + num_ts_types++; + } + handle->tstamp_type_count = num_ts_types; + if (num_ts_types != 0) { + handle->tstamp_type_list = malloc(num_ts_types * sizeof(u_int)); + for (i = 0, j = 0; i < NUM_SOF_TIMESTAMPING_TYPES; i++) { + if (info.so_timestamping & sof_ts_type_map[i].soft_timestamping_val) { + handle->tstamp_type_list[j] = sof_ts_type_map[i].pcap_tstamp_val; + j++; + } + } + } else + handle->tstamp_type_list = NULL; + + return 0; +} +#else /* ETHTOOL_GET_TS_INFO */ +static int +iface_ethtool_get_ts_info(pcap_t *handle, char *ebuf _U_) +{ + /* + * We don't have an ioctl to use to ask what's supported, + * so say we support everything. + */ + iface_set_default_ts_types(handle); + return 0; +} +#endif /* ETHTOOL_GET_TS_INFO */ + +#endif /* defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP) */ + +#ifdef HAVE_PACKET_RING /* * Find out if we have any form of fragmentation/reassembly offloading. * @@ -5467,7 +5883,7 @@ enter_rfmon_mode(pcap_t *handle, int sock_fd, const char *device) */ #if defined(SIOCETHTOOL) && (defined(ETHTOOL_GTSO) || defined(ETHTOOL_GUFO) || defined(ETHTOOL_GGSO) || defined(ETHTOOL_GFLAGS) || defined(ETHTOOL_GGRO)) static int -iface_ethtool_ioctl(pcap_t *handle, int cmd, const char *cmdname) +iface_ethtool_flag_ioctl(pcap_t *handle, int cmd, const char *cmdname) { struct ifreq ifr; struct ethtool_value eval; @@ -5488,11 +5904,11 @@ iface_ethtool_ioctl(pcap_t *handle, int cmd, const char *cmdname) return 0; } snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, - "%s: SIOETHTOOL(%s) ioctl failed: %s", handle->opt.source, + "%s: SIOCETHTOOL(%s) ioctl failed: %s", handle->opt.source, cmdname, strerror(errno)); return -1; } - return eval.data; + return eval.data; } static int @@ -5501,7 +5917,7 @@ iface_get_offload(pcap_t *handle) int ret; #ifdef ETHTOOL_GTSO - ret = iface_ethtool_ioctl(handle, ETHTOOL_GTSO, "ETHTOOL_GTSO"); + ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GTSO, "ETHTOOL_GTSO"); if (ret == -1) return -1; if (ret) @@ -5509,7 +5925,7 @@ iface_get_offload(pcap_t *handle) #endif #ifdef ETHTOOL_GUFO - ret = iface_ethtool_ioctl(handle, ETHTOOL_GUFO, "ETHTOOL_GUFO"); + ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GUFO, "ETHTOOL_GUFO"); if (ret == -1) return -1; if (ret) @@ -5522,7 +5938,7 @@ iface_get_offload(pcap_t *handle) * handed to PF_PACKET sockets on transmission? If not, * this need not be checked. */ - ret = iface_ethtool_ioctl(handle, ETHTOOL_GGSO, "ETHTOOL_GGSO"); + ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GGSO, "ETHTOOL_GGSO"); if (ret == -1) return -1; if (ret) @@ -5530,7 +5946,7 @@ iface_get_offload(pcap_t *handle) #endif #ifdef ETHTOOL_GFLAGS - ret = iface_ethtool_ioctl(handle, ETHTOOL_GFLAGS, "ETHTOOL_GFLAGS"); + ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GFLAGS, "ETHTOOL_GFLAGS"); if (ret == -1) return -1; if (ret & ETH_FLAG_LRO) @@ -5543,7 +5959,7 @@ iface_get_offload(pcap_t *handle) * handed to PF_PACKET sockets on receipt? If not, * this need not be checked. */ - ret = iface_ethtool_ioctl(handle, ETHTOOL_GGRO, "ETHTOOL_GGRO"); + ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GGRO, "ETHTOOL_GGRO"); if (ret == -1) return -1; if (ret) @@ -5564,6 +5980,8 @@ iface_get_offload(pcap_t *handle _U_) } #endif /* SIOCETHTOOL */ +#endif /* HAVE_PACKET_RING */ + #endif /* HAVE_PF_PACKET_SOCKETS */ /* ===== Functions to interface to the older kernels ================== */ @@ -5629,7 +6047,7 @@ activate_old(pcap_t *handle) * Try to find the DLT_ type corresponding to that * link-layer type. */ - map_arphrd_to_dlt(handle, arptype, device, 0); + map_arphrd_to_dlt(handle, handle->fd, arptype, device, 0); if (handle->linktype == -1) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "unknown arptype %d", arptype); @@ -6049,20 +6467,40 @@ set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode) * "nothing more to be read" error). */ save_mode = fcntl(handle->fd, F_GETFL, 0); - if (save_mode != -1 && - fcntl(handle->fd, F_SETFL, save_mode | O_NONBLOCK) >= 0) { - while (recv(handle->fd, &drain, sizeof drain, - MSG_TRUNC) >= 0) - ; - save_errno = errno; - fcntl(handle->fd, F_SETFL, save_mode); - if (save_errno != EAGAIN) { - /* Fatal error */ - reset_kernel_filter(handle); - snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, - "recv: %s", pcap_strerror(save_errno)); - return -2; - } + if (save_mode == -1) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "can't get FD flags when changing filter: %s", + pcap_strerror(errno)); + return -2; + } + if (fcntl(handle->fd, F_SETFL, save_mode | O_NONBLOCK) < 0) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "can't set nonblocking mode when changing filter: %s", + pcap_strerror(errno)); + return -2; + } + while (recv(handle->fd, &drain, sizeof drain, MSG_TRUNC) >= 0) + ; + save_errno = errno; + if (save_errno != EAGAIN) { + /* + * Fatal error. + * + * If we can't restore the mode or reset the + * kernel filter, there's nothing we can do. + */ + (void)fcntl(handle->fd, F_SETFL, save_mode); + (void)reset_kernel_filter(handle); + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "recv failed when changing filter: %s", + pcap_strerror(save_errno)); + return -2; + } + if (fcntl(handle->fd, F_SETFL, save_mode) == -1) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "can't restore FD flags when changing filter: %s", + pcap_strerror(save_errno)); + return -2; } } @@ -6085,11 +6523,16 @@ set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode) save_errno = errno; /* - * XXX - if this fails, we're really screwed; - * we have the total filter on the socket, - * and it won't come off. What do we do then? + * If this fails, we're really screwed; we have the + * total filter on the socket, and it won't come off. + * Report it as a fatal error. */ - reset_kernel_filter(handle); + if (reset_kernel_filter(handle) == -1) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "can't remove kernel total filter: %s", + pcap_strerror(errno)); + return -2; /* fatal error */ + } errno = save_errno; } diff --git a/external/bsd/libpcap/dist/pcap-netfilter-linux.c b/external/bsd/libpcap/dist/pcap-netfilter-linux.c index c4a86183b724..2cbe158abf1f 100644 --- a/external/bsd/libpcap/dist/pcap-netfilter-linux.c +++ b/external/bsd/libpcap/dist/pcap-netfilter-linux.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-netfilter-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-netfilter-linux.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 2011 Jakub Zawadzki @@ -13,8 +13,8 @@ * 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. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @@ -31,7 +31,7 @@ */ #include -__RCSID("$NetBSD: pcap-netfilter-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-netfilter-linux.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -62,14 +62,14 @@ __RCSID("$NetBSD: pcap-netfilter-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp #include /* NOTE: if your program drops privilages after pcap_activate() it WON'T work with nfqueue. - * It took me quite some time to debug ;/ + * It took me quite some time to debug ;/ * * Sending any data to nfnetlink socket requires CAP_NET_ADMIN privilages, * and in nfqueue we need to send verdict reply after recving packet. * * In tcpdump you can disable dropping privilages with -Z root */ - + #include "pcap-netfilter-linux.h" #define HDR_LENGTH (NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct nfgenmsg)))) @@ -121,10 +121,10 @@ netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_c return -1; } - if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_ULOG && - NFNL_MSG_TYPE(nlh->nlmsg_type) == NFULNL_MSG_PACKET) + if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_ULOG && + NFNL_MSG_TYPE(nlh->nlmsg_type) == NFULNL_MSG_PACKET) type = NFLOG; - else if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_QUEUE && + else if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_QUEUE && NFNL_MSG_TYPE(nlh->nlmsg_type) == NFQNL_MSG_PACKET) type = NFQUEUE; @@ -132,7 +132,7 @@ netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_c const unsigned char *payload = NULL; struct pcap_pkthdr pkth; - const struct nfgenmsg *nfg; + const struct nfgenmsg *nfg = NULL; int id = 0; if (handle->linktype != DLT_NFLOG) { @@ -189,7 +189,7 @@ netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_c gettimeofday(&pkth.ts, NULL); if (handle->fcode.bf_insns == NULL || - bpf_filter(handle->fcode.bf_insns, payload, pkth.len, pkth.caplen)) + bpf_filter(handle->fcode.bf_insns, payload, pkth.len, pkth.caplen)) { handlep->packets_read++; callback(user, &pkth, payload); @@ -199,7 +199,10 @@ netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_c if (type == NFQUEUE) { /* XXX, possible responses: NF_DROP, NF_ACCEPT, NF_STOLEN, NF_QUEUE, NF_REPEAT, NF_STOP */ - nfqueue_send_verdict(handle, ntohs(nfg->res_id), id, NF_ACCEPT); + /* if type == NFQUEUE, handle->linktype is always != DLT_NFLOG, + so nfg is always initialized to NLMSG_DATA(nlh). */ + if (nfg != NULL) + nfqueue_send_verdict(handle, ntohs(nfg->res_id), id, NF_ACCEPT); } } @@ -236,7 +239,7 @@ netfilter_inject_linux(pcap_t *handle, const void *buf, size_t size) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "inject not supported on netfilter devices"); return (-1); -} +} struct my_nfattr { u_int16_t nfa_len; @@ -254,7 +257,7 @@ netfilter_send_config_msg(const pcap_t *handle, u_int16_t msg_type, int ack, u_i struct sockaddr_nl snl; static unsigned int seq_id; - + if (!seq_id) seq_id = time(NULL); ++seq_id; @@ -346,7 +349,7 @@ nflog_send_config_cmd(const pcap_t *handle, u_int16_t group_id, u_int8_t cmd, u_ return nflog_send_config_msg(handle, family, group_id, &nfa); } -static int +static int nflog_send_config_mode(const pcap_t *handle, u_int16_t group_id, u_int8_t copy_mode, u_int32_t copy_range) { struct nfulnl_msg_config_mode msg; @@ -400,7 +403,7 @@ nfqueue_send_config_cmd(const pcap_t *handle, u_int16_t group_id, u_int8_t cmd, return nfqueue_send_config_msg(handle, AF_UNSPEC, group_id, &nfa); } -static int +static int nfqueue_send_config_mode(const pcap_t *handle, u_int16_t group_id, u_int8_t copy_mode, u_int32_t copy_range) { struct nfqnl_msg_config_params msg; @@ -433,7 +436,7 @@ netfilter_activate(pcap_t* handle) dev += strlen(NFQUEUE_IFACE); type = NFQUEUE; } - + if (type != OTHER && *dev == ':') { dev++; while (*dev) { @@ -442,7 +445,7 @@ netfilter_activate(pcap_t* handle) if (group_count == 32) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, - "Maximum 32 netfilter groups! dev: %s", + "Maximum 32 netfilter groups! dev: %s", handle->opt.source); return PCAP_ERROR; } @@ -467,7 +470,7 @@ netfilter_activate(pcap_t* handle) if (type == OTHER || *dev) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, - "Can't get netfilter group(s) index from %s", + "Can't get netfilter group(s) index from %s", handle->opt.source); return PCAP_ERROR; } @@ -604,7 +607,7 @@ netfilter_create(const char *device, char *ebuf, int *is_ours) /* Does it begin with NFLOG_IFACE or NFQUEUE_IFACE? */ if (strncmp(cp, NFLOG_IFACE, sizeof NFLOG_IFACE - 1) == 0) cp += sizeof NFLOG_IFACE - 1; - else if (strncmp(cp, NFQUEUE_IFACE, sizeof NFQUEUE_IFACE - 1) == 0) + else if (strncmp(cp, NFQUEUE_IFACE, sizeof NFQUEUE_IFACE - 1) == 0) cp += sizeof NFQUEUE_IFACE - 1; else { /* Nope, doesn't begin with NFLOG_IFACE nor NFQUEUE_IFACE */ @@ -633,11 +636,11 @@ netfilter_create(const char *device, char *ebuf, int *is_ours) return (p); } -int +int netfilter_findalldevs(pcap_if_t **alldevsp, char *err_str) { int sock; - + sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER); if (sock < 0) { /* if netlink is not supported this is not fatal */ diff --git a/external/bsd/libpcap/dist/pcap-netfilter-linux.h b/external/bsd/libpcap/dist/pcap-netfilter-linux.h index 7eeea30cfecd..fd514393aa92 100644 --- a/external/bsd/libpcap/dist/pcap-netfilter-linux.h +++ b/external/bsd/libpcap/dist/pcap-netfilter-linux.h @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-netfilter-linux.h,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-netfilter-linux.h,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 2011 Jakub Zawadzki @@ -13,8 +13,8 @@ * 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. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS diff --git a/external/bsd/libpcap/dist/pcap-nit.c b/external/bsd/libpcap/dist/pcap-nit.c index e4a5e69a524c..f2d9252b7962 100644 --- a/external/bsd/libpcap/dist/pcap-nit.c +++ b/external/bsd/libpcap/dist/pcap-nit.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-nit.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-nit.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 @@ -22,7 +22,7 @@ */ #include -__RCSID("$NetBSD: pcap-nit.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-nit.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -216,7 +216,7 @@ pcap_inject_nit(pcap_t *p, const void *buf, size_t size) return (-1); } return (ret); -} +} static int nit_setflags(pcap_t *p) diff --git a/external/bsd/libpcap/dist/pcap-pf.c b/external/bsd/libpcap/dist/pcap-pf.c index 27bbfd8bb810..880633a185a1 100644 --- a/external/bsd/libpcap/dist/pcap-pf.c +++ b/external/bsd/libpcap/dist/pcap-pf.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-pf.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-pf.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 @@ -25,7 +25,7 @@ */ #include -__RCSID("$NetBSD: pcap-pf.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-pf.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -242,7 +242,7 @@ pcap_inject_pf(pcap_t *p, const void *buf, size_t size) return (-1); } return (ret); -} +} static int pcap_stats_pf(pcap_t *p, struct pcap_stat *ps) diff --git a/external/bsd/libpcap/dist/pcap-septel.c b/external/bsd/libpcap/dist/pcap-septel.c index 24124eee453a..9c547c7c941d 100644 --- a/external/bsd/libpcap/dist/pcap-septel.c +++ b/external/bsd/libpcap/dist/pcap-septel.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-septel.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-septel.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * pcap-septel.c: Packet capture interface for Intel/Septel card. @@ -17,7 +17,7 @@ */ #include -__RCSID("$NetBSD: pcap-septel.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-septel.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -199,9 +199,9 @@ septel_inject(pcap_t *handle, const void *buf _U_, size_t size _U_) * See also pcap(3). */ static pcap_t *septel_activate(pcap_t* handle) { - /* Initialize some components of the pcap structure. */ + /* Initialize some components of the pcap structure. */ handle->linktype = DLT_MTP2; - + handle->bufsize = 0; /* @@ -249,9 +249,9 @@ static int septel_stats(pcap_t *p, struct pcap_stat *ps) { struct pcap_septel *handlep = p->priv; /*handlep->stat.ps_recv = 0;*/ /*handlep->stat.ps_drop = 0;*/ - + *ps = handlep->stat; - + return 0; } diff --git a/external/bsd/libpcap/dist/pcap-sita.c b/external/bsd/libpcap/dist/pcap-sita.c index 03947f4d4e3e..22312c404a05 100644 --- a/external/bsd/libpcap/dist/pcap-sita.c +++ b/external/bsd/libpcap/dist/pcap-sita.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-sita.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-sita.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * pcap-sita.c: Packet capture interface additions for SITA ACN devices @@ -27,7 +27,7 @@ */ #include -__RCSID("$NetBSD: pcap-sita.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-sita.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -188,7 +188,7 @@ static int read_client_nbytes(int fd, int count, unsigned char *buf) { find_unit_by_fd(fd, &chassis, &geoslot, &u); while (count) { if ((len = recv(fd, buf, count, 0)) <= 0) return -1; /* read in whatever data was sent to us */ - count -= len; + count -= len; buf += len; } /* till we have everything we are looking for */ return 0; @@ -216,7 +216,7 @@ static void empty_unit(int chassis, int geoslot) { u->imsg = (char *)realloc(u->imsg, 1); /* and re-allocate the old large buffer into a new small one */ if (u->imsg == NULL) { /* oops, realloc call failed */ fprintf(stderr, "Warning...call to realloc() failed, value of errno is %d\n", errno); - + } } @@ -558,10 +558,10 @@ static void sort_if_table(void) { } if (has_swapped == 0) return; - } + } return; } - + static int process_client_data (char *errbuf) { /* returns: -1 = error, 0 = OK */ int chassis, geoslot; unit_t *u; diff --git a/external/bsd/libpcap/dist/pcap-snf.c b/external/bsd/libpcap/dist/pcap-snf.c index b72c3aec44ab..5dff943e8758 100644 --- a/external/bsd/libpcap/dist/pcap-snf.c +++ b/external/bsd/libpcap/dist/pcap-snf.c @@ -1,7 +1,7 @@ #include -__RCSID("$NetBSD: pcap-snf.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-snf.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); -/* $NetBSD: pcap-snf.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-snf.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -21,6 +21,9 @@ __RCSID("$NetBSD: pcap-snf.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); #include #include +#if SNF_VERSION_API >= 0x0003 +#define SNF_HAVE_INJECT_API +#endif #include "pcap-int.h" #include "pcap-snf.h" @@ -31,6 +34,9 @@ __RCSID("$NetBSD: pcap-snf.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); struct pcap_snf { snf_handle_t snf_handle; /* opaque device handle */ snf_ring_t snf_ring; /* opaque device ring handle */ +#ifdef SNF_HAVE_INJECT_API + snf_inject_t snf_inj; /* inject handle, if inject is used */ +#endif int snf_timeout; int snf_boardnum; }; @@ -46,9 +52,10 @@ static int snf_pcap_stats(pcap_t *p, struct pcap_stat *ps) { struct snf_ring_stats stats; + struct pcap_snf *snfps = p->priv; int rc; - if ((rc = snf_ring_getstats(ps->snf_ring, &stats))) { + if ((rc = snf_ring_getstats(snfps->snf_ring, &stats))) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_get_stats: %s", pcap_strerror(rc)); return -1; @@ -67,6 +74,10 @@ snf_platform_cleanup(pcap_t *p) if (p == NULL) return; +#ifdef SNF_HAVE_INJECT_API + if (ps->snf_inj) + snf_inject_close(ps->snf_inj); +#endif snf_ring_close(ps->snf_ring); snf_close(ps->snf_handle); pcap_cleanup_live_common(p); @@ -100,14 +111,23 @@ snf_setnonblock(pcap_t *p, int nonblock, char *errbuf) static inline struct timeval -snf_timestamp_to_timeval(const int64_t ts_nanosec) +snf_timestamp_to_timeval(const int64_t ts_nanosec, const int tstamp_precision) { struct timeval tv; - int32_t rem; + long tv_nsec; + if (ts_nanosec == 0) return (struct timeval) { 0, 0 }; + tv.tv_sec = ts_nanosec / _NSEC_PER_SEC; - tv.tv_usec = (ts_nanosec % _NSEC_PER_SEC) / 1000; + tv_nsec = (ts_nanosec % _NSEC_PER_SEC); + + /* libpcap expects tv_usec to be nanos if using nanosecond precision. */ + if (tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) + tv.tv_usec = tv_nsec; + else + tv.tv_usec = tv_nsec / 1000; + return tv; } @@ -118,11 +138,13 @@ snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) struct pcap_pkthdr hdr; int i, flags, err, caplen, n; struct snf_recv_req req; + int nonblock, timeout; - if (!p || cnt == 0) + if (!p) return -1; n = 0; + timeout = ps->snf_timeout; while (n < cnt || PACKET_COUNT_IS_UNLIMITED(cnt)) { /* * Has "pcap_breakloop()" been called? @@ -136,14 +158,17 @@ snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) } } - err = snf_ring_recv(ps->snf_ring, ps->snf_timeout, &req); + err = snf_ring_recv(ps->snf_ring, timeout, &req); if (err) { - if (err == EBUSY || err == EAGAIN) - return (0); - if (err == EINTR) + if (err == EBUSY || err == EAGAIN) { + return (n); + } + else if (err == EINTR) { + timeout = 0; continue; - if (err != 0) { + } + else { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_read: %s", pcap_strerror(err)); return -1; @@ -156,12 +181,17 @@ snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, req.pkt_addr, req.length, caplen)) { - hdr.ts = snf_timestamp_to_timeval(req.timestamp); + hdr.ts = snf_timestamp_to_timeval(req.timestamp, p->opt.tstamp_precision); hdr.caplen = caplen; hdr.len = req.length; callback(user, &hdr, req.pkt_addr); } n++; + + /* After one successful packet is received, we won't block + * again for that timeout. */ + if (timeout != 0) + timeout = 0; } return (n); } @@ -188,9 +218,32 @@ snf_setfilter(pcap_t *p, struct bpf_program *fp) static int snf_inject(pcap_t *p, const void *buf _U_, size_t size _U_) { - strlcpy(p->errbuf, "Sending packets isn't supported with snf", +#ifdef SNF_HAVE_INJECT_API + struct pcap_snf *ps = p->priv; + int rc; + if (ps->snf_inj == NULL) { + rc = snf_inject_open(ps->snf_boardnum, 0, &ps->snf_inj); + if (rc) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "snf_inject_open: %s", pcap_strerror(rc)); + return (-1); + } + } + + rc = snf_inject_send(ps->snf_inj, -1, 0, buf, size); + if (!rc) { + return (size); + } + else { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "snf_inject_send: %s", + pcap_strerror(rc)); + return (-1); + } +#else + strlcpy(p->errbuf, "Sending packets isn't supported with this snf version", PCAP_ERRBUF_SIZE); return (-1); +#endif } static int @@ -200,7 +253,7 @@ snf_activate(pcap_t* p) char *device = p->opt.source; const char *nr = NULL; int err; - int flags = 0; + int flags = -1, ring_id = -1; if (device == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, @@ -210,8 +263,10 @@ snf_activate(pcap_t* p) /* In Libpcap, we set pshared by default if NUM_RINGS is set to > 1. * Since libpcap isn't thread-safe */ - if ((nr = getenv("SNF_NUM_RINGS")) && *nr && atoi(nr) > 1) - flags |= SNF_F_PSHARED; + if ((nr = getenv("SNF_FLAGS")) && *nr) + flags = strtol(nr, NULL, 0); + else if ((nr = getenv("SNF_NUM_RINGS")) && *nr && atoi(nr) > 1) + flags = SNF_F_PSHARED; else nr = NULL; @@ -227,10 +282,14 @@ snf_activate(pcap_t* p) return -1; } - err = snf_ring_open(ps->snf_handle, &ps->snf_ring); + if ((nr = getenv("SNF_PCAP_RING_ID")) && *nr) { + ring_id = (int) strtol(nr, NULL, 0); + } + err = snf_ring_open_id(ps->snf_handle, ring_id, &ps->snf_ring); if (err != 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, - "snf_ring_open failed: %s", pcap_strerror(err)); + "snf_ring_open_id(ring=%d) failed: %s", + ring_id, pcap_strerror(err)); return -1; } @@ -260,12 +319,104 @@ snf_activate(pcap_t* p) p->setnonblock_op = snf_setnonblock; p->stats_op = snf_pcap_stats; p->cleanup_op = snf_platform_cleanup; +#ifdef SNF_HAVE_INJECT_API + ps->snf_inj = NULL; +#endif return 0; } +#define MAX_DESC_LENGTH 128 int snf_findalldevs(pcap_if_t **devlistp, char *errbuf) { + pcap_if_t *devlist = NULL,*curdev,*prevdev; + pcap_addr_t *curaddr; + struct snf_ifaddrs *ifaddrs, *ifa; + char desc[MAX_DESC_LENGTH]; + int ret; + + if (snf_init(SNF_VERSION_API)) + return (-1); + + if (snf_getifaddrs(&ifaddrs) || ifaddrs == NULL) + { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "snf_getifaddrs: %s", pcap_strerror(errno)); + return (-1); + } + ifa = ifaddrs; + while (ifa) + { + /* + * Allocate a new entry + */ + curdev = (pcap_if_t *)malloc(sizeof(pcap_if_t)); + if (curdev == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "snf_findalldevs malloc: %s", pcap_strerror(errno)); + return (-1); + } + if (devlist == NULL) /* save first entry */ + devlist = curdev; + else + prevdev->next = curdev; + /* + * Fill in the entry. + */ + curdev->next = NULL; + curdev->name = strdup(ifa->snf_ifa_name); + if (curdev->name == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "snf_findalldevs strdup: %s", pcap_strerror(errno)); + free(curdev); + return (-1); + } + (void)snprintf(desc,MAX_DESC_LENGTH,"Myricom snf%d", + ifa->snf_ifa_portnum); + curdev->description = strdup(desc); + if (curdev->description == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "snf_findalldevs strdup1: %s", pcap_strerror(errno)); + free(curdev->name); + free(curdev); + return (-1); + } + curdev->addresses = NULL; + curdev->flags = 0; + + curaddr = (pcap_addr_t *)malloc(sizeof(pcap_addr_t)); + if (curaddr == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "snf_findalldevs malloc1: %s", pcap_strerror(errno)); + free(curdev->description); + free(curdev->name); + free(curdev); + return (-1); + } + curdev->addresses = curaddr; + curaddr->next = NULL; + curaddr->addr = (struct sockaddr*)malloc(sizeof(struct sockaddr_storage)); + if (curaddr->addr == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc2: %s", pcap_strerror(errno)); + free(curdev->description); + free(curdev->name); + free(curaddr); + free(curdev); + return (-1); + } + curaddr->addr->sa_family = AF_INET; + curaddr->netmask = NULL; + curaddr->broadaddr = NULL; + curaddr->dstaddr = NULL; + curaddr->next = NULL; + + prevdev = curdev; + ifa = ifa->snf_ifa_next; + } + snf_freeifaddrs(ifaddrs); + *devlistp = devlist; + /* * There are no platform-specific devices since each device * exists as a regular Ethernet device. @@ -329,6 +480,22 @@ snf_create(const char *device, char *ebuf, int *is_ours) return NULL; ps = p->priv; + /* + * We support microsecond and nanosecond time stamps. + */ + p->tstamp_precision_count = 2; + p->tstamp_precision_list = malloc(2 * sizeof(u_int)); + if (p->tstamp_precision_list == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", + pcap_strerror(errno)); + if (p->tstamp_type_list != NULL) + free(p->tstamp_type_list); + free(p); + return NULL; + } + p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO; + p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO; + p->activate_op = snf_activate; ps->snf_boardnum = boardnum; return p; diff --git a/external/bsd/libpcap/dist/pcap-snit.c b/external/bsd/libpcap/dist/pcap-snit.c index b7d63246c071..9e6f53197825 100644 --- a/external/bsd/libpcap/dist/pcap-snit.c +++ b/external/bsd/libpcap/dist/pcap-snit.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-snit.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-snit.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 @@ -26,7 +26,7 @@ */ #include -__RCSID("$NetBSD: pcap-snit.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-snit.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -216,7 +216,7 @@ static int pcap_inject_snit(pcap_t *p, const void *buf, size_t size) { struct strbuf ctl, data; - + /* * XXX - can we just do * diff --git a/external/bsd/libpcap/dist/pcap-snoop.c b/external/bsd/libpcap/dist/pcap-snoop.c index f3ca86faf4cb..0c87bc145113 100644 --- a/external/bsd/libpcap/dist/pcap-snoop.c +++ b/external/bsd/libpcap/dist/pcap-snoop.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-snoop.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-snoop.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 @@ -22,7 +22,7 @@ */ #include -__RCSID("$NetBSD: pcap-snoop.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-snoop.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -119,7 +119,7 @@ again: caplen = (datalen < p->snapshot) ? datalen : p->snapshot; cp = (u_char *)(sh + 1) + p->offset; /* XXX */ - /* + /* * XXX unfortunately snoop loopback isn't exactly like * BSD's. The address family is encoded in the first 2 * bytes rather than the first 4 bytes! Luckily the last @@ -160,7 +160,7 @@ pcap_inject_snoop(pcap_t *p, const void *buf, size_t size) return (-1); } return (ret); -} +} static int pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps) diff --git a/external/bsd/libpcap/dist/pcap-usb-linux.c b/external/bsd/libpcap/dist/pcap-usb-linux.c index e5defe268bfa..203587bf4017 100644 --- a/external/bsd/libpcap/dist/pcap-usb-linux.c +++ b/external/bsd/libpcap/dist/pcap-usb-linux.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-usb-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-usb-linux.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 2006 Paolo Abeni (Italy) @@ -13,8 +13,8 @@ * 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. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @@ -36,7 +36,7 @@ */ #include -__RCSID("$NetBSD: pcap-usb-linux.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap-usb-linux.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -144,21 +144,21 @@ static int usb_setdirection_linux(pcap_t *, pcap_direction_t); static void usb_cleanup_linux_mmap(pcap_t *); /* facility to add an USB device to the device list*/ -static int +static int usb_dev_add(pcap_if_t** alldevsp, int n, char *err_str) { char dev_name[10]; - char dev_descr[30]; + char dev_descr[30]; snprintf(dev_name, 10, USB_IFACE"%d", n); snprintf(dev_descr, 30, "USB bus number %d", n); - if (pcap_add_if(alldevsp, dev_name, 0, + if (pcap_add_if(alldevsp, dev_name, 0, dev_descr, err_str) < 0) return -1; - return 0; + return 0; } -int +int usb_findalldevs(pcap_if_t **alldevsp, char *err_str) { struct dirent* data; @@ -177,7 +177,7 @@ usb_findalldevs(pcap_if_t **alldevsp, char *err_str) if (strncmp(name, "usb", 3) != 0) continue; - if (sscanf(&name[3], "%d", &n) == 0) + if (sscanf(&name[3], "%d", &n) == 0) continue; ret = usb_dev_add(alldevsp, n, err_str); @@ -198,7 +198,7 @@ usb_findalldevs(pcap_if_t **alldevsp, char *err_str) if ((len < 1) || !isdigit(name[--len])) continue; while (isdigit(name[--len])); - if (sscanf(&name[len+1], "%d", &n) != 1) + if (sscanf(&name[len+1], "%d", &n) != 1) continue; ret = usb_dev_add(alldevsp, n, err_str); @@ -212,12 +212,12 @@ usb_findalldevs(pcap_if_t **alldevsp, char *err_str) return 0; } -static +static int usb_mmap(pcap_t* handle) { struct pcap_usb_linux *handlep = handle->priv; int len = ioctl(handle->fd, MON_IOCQ_RING_SIZE); - if (len < 0) + if (len < 0) return 0; handlep->mmapbuflen = len; @@ -265,7 +265,7 @@ probe_devices(int bus) continue; snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d/%s", bus, data->d_name); - + fd = open(buf, O_RDWR); if (fd == -1) continue; @@ -368,7 +368,7 @@ usb_activate(pcap_t* handle) } /*now select the read method: try to open binary interface */ - snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handlep->bus_index); + snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handlep->bus_index); handle->fd = open(full_path, O_RDONLY, 0); if (handle->fd >= 0) { @@ -407,7 +407,7 @@ usb_activate(pcap_t* handle) } else { /*Binary interface not available, try open text interface */ - snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handlep->bus_index); + snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handlep->bus_index); handle->fd = open(full_path, O_RDONLY, 0); if (handle->fd < 0) { @@ -417,7 +417,7 @@ usb_activate(pcap_t* handle) * Not found at the new location; try * the old location. */ - snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handlep->bus_index); + snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handlep->bus_index); handle->fd = open(full_path, O_RDONLY, 0); } if (handle->fd < 0) { @@ -458,22 +458,22 @@ usb_activate(pcap_t* handle) return 0; } -static inline int +static inline int ascii_to_int(char c) { return c < 'A' ? c- '0': ((c<'a') ? c - 'A' + 10: c-'a'+10); } /* - * see /Documentation/usb/usbmon.txt and - * /drivers/usb/mon/mon_text.c for urb string + * see /Documentation/usb/usbmon.txt and + * /drivers/usb/mon/mon_text.c for urb string * format description */ static int usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) { /* see: - * /usr/src/linux/Documentation/usb/usbmon.txt + * /usr/src/linux/Documentation/usb/usbmon.txt * for message format */ struct pcap_usb_linux *handlep = handle->priv; @@ -506,11 +506,11 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u return -1; } - /* read urb header; %n argument may increment return value, but it's + /* read urb header; %n argument may increment return value, but it's * not mandatory, so does not count on it*/ string[ret] = 0; - ret = sscanf(string, "%x %d %c %c%c:%d:%d %s%n", &tag, ×tamp, &etype, - &pipeid1, &pipeid2, &dev_addr, &ep_num, status, + ret = sscanf(string, "%x %d %c %c%c:%d:%d %s%n", &tag, ×tamp, &etype, + &pipeid1, &pipeid2, &dev_addr, &ep_num, status, &cnt); if (ret < 8) { @@ -526,10 +526,10 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u string += cnt; /* don't use usbmon provided timestamp, since it have low precision*/ - if (gettimeofday(&pkth.ts, NULL) < 0) + if (gettimeofday(&pkth.ts, NULL) < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, - "Can't get timestamp for message '%s' %d:%s", + "Can't get timestamp for message '%s' %d:%s", string, errno, strerror(errno)); return -1; } @@ -572,11 +572,11 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u if (ret != 1) { /* this a setup packet, setup data can be filled with underscore if - * usbmon has not been able to read them, so we must parse this fields as + * usbmon has not been able to read them, so we must parse this fields as * strings */ pcap_usb_setup* shdr; char str1[3], str2[3], str3[5], str4[5], str5[5]; - ret = sscanf(string, "%s %s %s %s %s%n", str1, str2, str3, str4, + ret = sscanf(string, "%s %s %s %s %s%n", str1, str2, str3, str4, str5, &cnt); if (ret < 5) { @@ -597,7 +597,7 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u uhdr->setup_flag = 0; } - else + else uhdr->setup_flag = 1; /* read urb data */ @@ -610,7 +610,7 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u } string += cnt; - /* urb tag is not present if urb length is 0, so we can stop here + /* urb tag is not present if urb length is 0, so we can stop here * text parsing */ pkth.len = urb_len+pkth.caplen; uhdr->urb_len = urb_len; @@ -627,7 +627,7 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u return -1; } - if (urb_tag != '=') + if (urb_tag != '=') goto got; /* skip urb tag and following space */ @@ -636,7 +636,7 @@ usb_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *u /* if we reach this point we got some urb data*/ uhdr->data_flag = 0; - /* read all urb data; if urb length is greater then the usbmon internal + /* read all urb data; if urb length is greater then the usbmon internal * buffer length used by the kernel to spool the URB, we get only * a partial information. * At least until linux 2.6.17 there is no way to set usbmon intenal buffer @@ -675,7 +675,7 @@ usb_inject_linux(pcap_t *handle, const void *buf, size_t size) return (-1); } -static int +static int usb_stats_linux(pcap_t *handle, struct pcap_stat *stats) { struct pcap_usb_linux *handlep = handle->priv; @@ -700,7 +700,7 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats) } if (fd < 0) { snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, - "Can't open USB stats file %s: %s", + "Can't open USB stats file %s: %s", string, strerror(errno)); return -1; } @@ -722,11 +722,11 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats) /* extract info on dropped urbs */ for (consumed=0; consumed < ret; ) { - /* from the sscanf man page: - * The C standard says: "Execution of a %n directive does + /* from the sscanf man page: + * The C standard says: "Execution of a %n directive does * not increment the assignment count returned at the completion * of execution" but the Corrigendum seems to contradict this. - * Do not make any assumptions on the effect of %n conversions + * Do not make any assumptions on the effect of %n conversions * on the return value and explicitly check for cnt assignmet*/ int ntok; @@ -738,7 +738,7 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats) ptr += cnt; if (strcmp(token, "nreaders") == 0) ret = sscanf(ptr, "%d", &stats->ps_drop); - else + else ret = sscanf(ptr, "%d", &dummy); if (ntok != 1) break; @@ -751,7 +751,7 @@ usb_stats_linux(pcap_t *handle, struct pcap_stat *stats) return 0; } -static int +static int usb_setdirection_linux(pcap_t *p, pcap_direction_t d) { p->direction = d; @@ -759,7 +759,7 @@ usb_setdirection_linux(pcap_t *p, pcap_direction_t d) } -static int +static int usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats) { struct pcap_usb_linux *handlep = handle->priv; @@ -780,7 +780,7 @@ usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats) } /* - * see /Documentation/usb/usbmon.txt and + * see /Documentation/usb/usbmon.txt and * /drivers/usb/mon/mon_bin.c binary ABI */ static int @@ -838,7 +838,7 @@ usb_read_linux_bin(pcap_t *handle, int max_packets, pcap_handler callback, u_cha } /* - * see /Documentation/usb/usbmon.txt and + * see /Documentation/usb/usbmon.txt and * /drivers/usb/mon/mon_bin.c binary ABI */ #define VEC_SIZE 32 @@ -892,7 +892,7 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch for (i=0; immapbuf[vec[i]]; - if (hdr->event_type == '@') + if (hdr->event_type == '@') continue; /* we can get less that than really captured from kernel, depending on @@ -922,7 +922,11 @@ usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_ch } /* flush pending events*/ - ioctl(handle->fd, MON_IOCH_MFLUSH, nflush); + if (ioctl(handle->fd, MON_IOCH_MFLUSH, nflush) == -1) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "Can't mflush fd %d: %s", handle->fd, strerror(errno)); + return -1; + } return packets; } diff --git a/external/bsd/libpcap/dist/pcap-usb-linux.h b/external/bsd/libpcap/dist/pcap-usb-linux.h index f443cb41679d..fef1c35f438a 100644 --- a/external/bsd/libpcap/dist/pcap-usb-linux.h +++ b/external/bsd/libpcap/dist/pcap-usb-linux.h @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-usb-linux.h,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-usb-linux.h,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 2006 Paolo Abeni (Italy) @@ -13,8 +13,8 @@ * 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. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS diff --git a/external/bsd/libpcap/dist/pcap-win32.c b/external/bsd/libpcap/dist/pcap-win32.c index b7e7bcce8abd..097f95385f19 100644 --- a/external/bsd/libpcap/dist/pcap-win32.c +++ b/external/bsd/libpcap/dist/pcap-win32.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap-win32.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap-win32.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy) @@ -14,9 +14,9 @@ * 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. Neither the name of the Politecnico di Torino, CACE Technologies - * nor the names of its contributors may be used to endorse or promote - * products derived from this software without specific prior written + * 3. Neither the name of the Politecnico di Torino, CACE Technologies + * nor the names of its contributors may be used to endorse or promote + * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @@ -110,7 +110,7 @@ BOOL WINAPI DllMain( } /* Start winsock */ -int +int wsockinit() { WORD wVersionRequested; @@ -120,13 +120,13 @@ wsockinit() if (done) return err; - - wVersionRequested = MAKEWORD( 1, 1); + + wVersionRequested = MAKEWORD( 1, 1); err = WSAStartup( wVersionRequested, &wsaData ); atexit ((void(*)(void))WSACleanup); InitializeCriticalSection(&g_PcapCompileCriticalSection); done = 1; - + if ( err != 0 ) err = -1; return err; @@ -222,11 +222,11 @@ pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user) snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed"); return (PCAP_ERROR); } - + cc = p->Packet->ulBytesReceived; bp = p->Packet->Buffer; - } + } else bp = p->bp; @@ -330,14 +330,14 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) /* The timeout has expired but we no packets arrived */ return 0; header = (dag_record_t*)p->adapter->DagBuffer; - } + } else header = (dag_record_t*)p->bp; - + endofbuf = (char*)header + cc; - - /* - * Cycle through the packets + + /* + * Cycle through the packets */ do { @@ -347,12 +347,12 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) /* Increase the number of captured packets */ pw->stat.ps_recv++; - + /* Find the beginning of the packet */ dp = ((u_char *)header) + dag_record_size; /* Determine actual packet len */ - switch(header->type) + switch(header->type) { case TYPE_ATM: packet_len = ATM_SNAPLEN; @@ -370,9 +370,9 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) caplen = packet_len; } dp += 2; - + break; - + case TYPE_HDLC_POS: swt = SWAPS(header->wlen); packet_len = swt - (pw->dag_fcs_bits); @@ -381,10 +381,10 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) { caplen = packet_len; } - + break; } - + if(caplen > p->snapshot) caplen = p->snapshot; @@ -397,14 +397,14 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) * 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 (p->break_loop) { - if (n == 0) + if (n == 0) { p->break_loop = 0; return (-2); - } - else + } + else { p->bp = (char*)header; p->cc = endofbuf - (char*)header; @@ -425,30 +425,30 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) pcap_header.ts.tv_sec++; } } - + /* No underlaying filtering system. We need to filter on our own */ - if (p->fcode.bf_insns) + if (p->fcode.bf_insns) { - if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0) + if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0) { /* Move to next packet */ header = (dag_record_t*)((char*)header + erf_record_len); continue; } } - + /* Fill the header for the user suppplied callback function */ pcap_header.caplen = caplen; pcap_header.len = packet_len; - + /* Call the callback function */ (*callback)(user, &pcap_header, dp); - + /* Move to next packet */ header = (dag_record_t*)((char*)header + erf_record_len); /* Stop if the number of packets requested by user has been reached*/ - if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) + if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) { p->bp = (char*)header; p->cc = endofbuf - (char*)header; @@ -456,24 +456,24 @@ pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user) } } while((u_char*)header < endofbuf); - + return 1; } #endif /* HAVE_DAG_API */ /* Send a packet to the network */ -static int +static int pcap_inject_win32(pcap_t *p, const void *buf, size_t size){ LPPACKET PacketToSend; PacketToSend=PacketAllocatePacket(); - + if (PacketToSend == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketAllocatePacket failed"); return -1; } - + PacketInitPacket(PacketToSend,(PVOID)buf,size); if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed"); @@ -524,28 +524,28 @@ pcap_activate_win32(pcap_t *p) wsockinit(); p->adapter = PacketOpenAdapter(p->opt.source); - + if (p->adapter == NULL) { /* Adapter detected but we are not able to open it. Return failure. */ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror()); return PCAP_ERROR; } - + /*get network type*/ if(PacketGetNetType (p->adapter,&type) == FALSE) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror()); goto bad; } - + /*Set the linktype*/ - switch (type.LinkType) + switch (type.LinkType) { case NdisMediumWan: p->linktype = DLT_EN10MB; break; - + case NdisMedium802_3: p->linktype = DLT_EN10MB; /* @@ -568,27 +568,27 @@ pcap_activate_win32(pcap_t *p) p->dlt_count = 2; } break; - + case NdisMediumFddi: p->linktype = DLT_FDDI; break; - - case NdisMedium802_5: - p->linktype = DLT_IEEE802; + + case NdisMedium802_5: + p->linktype = DLT_IEEE802; break; - + case NdisMediumArcnetRaw: p->linktype = DLT_ARCNET; break; - + case NdisMediumArcnet878_2: p->linktype = DLT_ARCNET; break; - + case NdisMediumAtm: p->linktype = DLT_ATM_RFC1483; break; - + case NdisMediumCHDLC: p->linktype = DLT_CHDLC; break; @@ -619,7 +619,7 @@ pcap_activate_win32(pcap_t *p) } /* Set promiscuous mode */ - if (p->opt.promisc) + if (p->opt.promisc) { if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE) @@ -628,7 +628,7 @@ pcap_activate_win32(pcap_t *p) goto bad; } } - else + else { if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE) { @@ -649,8 +649,8 @@ pcap_activate_win32(pcap_t *p) if(!(p->adapter->Flags & INFO_FLAG_DAG_CARD)) { - /* - * Traditional Adapter + /* + * Traditional Adapter */ /* * If the buffer size wasn't explicitly set, default to @@ -664,16 +664,16 @@ pcap_activate_win32(pcap_t *p) snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer"); goto bad; } - + p->buffer = (u_char *)malloc(p->bufsize); - if (p->buffer == NULL) + if (p->buffer == NULL) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); goto bad; } - + PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize); - + if (p->opt.immediate) { /* tell the driver to copy the buffer as soon as data arrives */ @@ -696,8 +696,8 @@ pcap_activate_win32(pcap_t *p) else #ifdef HAVE_DAG_API { - /* - * Dag Card + /* + * Dag Card */ LONG status; HKEY dagkey; @@ -705,8 +705,8 @@ pcap_activate_win32(pcap_t *p) DWORD lpcbdata; int postype = 0; char keyname[512]; - - snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s", + + snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s", "SYSTEM\\CurrentControlSet\\Services\\DAG", strstr(_strlwr(p->opt.source), "dag")); do @@ -714,36 +714,36 @@ pcap_activate_win32(pcap_t *p) status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey); if(status != ERROR_SUCCESS) break; - + status = RegQueryValueEx(dagkey, "PosType", NULL, &lptype, (char*)&postype, &lpcbdata); - + if(status != ERROR_SUCCESS) { postype = 0; } - + RegCloseKey(dagkey); } while(FALSE); - - + + p->snapshot = PacketSetSnapLen(p->adapter, snaplen); - - /* Set the length of the FCS associated to any packet. This value + + /* Set the length of the FCS associated to any packet. This value * will be subtracted to the packet length */ pw->dag_fcs_bits = p->adapter->DagFcsLen; } #else goto bad; #endif /* HAVE_DAG_API */ - + PacketSetReadTimeout(p->adapter, p->opt.timeout); - + #ifdef HAVE_DAG_API if(p->adapter->Flags & INFO_FLAG_DAG_CARD) { @@ -884,23 +884,23 @@ pcap_setfilter_win32_npf(pcap_t *p, struct bpf_program *fp) /* * We filter at user level, since the kernel driver does't process the packets */ -static int +static int pcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) { - - if(!fp) + + if(!fp) { strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf)); return -1; } - + /* Install a user level filter */ - if (install_bpf_program(p, fp) < 0) + if (install_bpf_program(p, fp) < 0) { snprintf(p->errbuf, sizeof(p->errbuf), "setfilter, unable to install the filter: %s", pcap_strerror(errno)); return -1; } - + return (0); } diff --git a/external/bsd/libpcap/dist/pcap.3pcap.in b/external/bsd/libpcap/dist/pcap.3pcap.in index bce2cca93e92..1fb066a69098 100644 --- a/external/bsd/libpcap/dist/pcap.3pcap.in +++ b/external/bsd/libpcap/dist/pcap.3pcap.in @@ -354,12 +354,25 @@ open a .B pcap_t for a ``savefile'', given a pathname .TP +.BR pcap_open_offline_with_tstamp_precision (3PCAP) +open a +.B pcap_t +for a ``savefile'', given a pathname, and specify the precision to +provide for packet time stamps +.TP .BR pcap_fopen_offline (3PCAP) open a .B pcap_t for a ``savefile'', given a .B "FILE\ *" .TP +.BR pcap_fopen_offline_with_tstamp_precision (3PCAP) +open a +.B pcap_t +for a ``savefile'', given a +.BR "FILE\ *" , +and specify the precision to provide for packet time stamps +.TP .BR pcap_open_dead (3PCAP) create a ``fake'' .B pcap_t @@ -424,6 +437,16 @@ get description for a time stamp type .BR pcap_tstamp_type_name_to_val (3PCAP) get time stamp type corresponding to a name .TP +.BR pcap_set_tstamp_precision (3PCAP) +set time stamp precision for a not-yet-activated +.B pcap_t +for live capture +.TP +.BR pcap_get_tstamp_precision (3PCAP) +get the time stamp precision of a +.B pcap_t +for live capture +.TP .BR pcap_datalink (3PCAP) get link-layer header type for a .B pcap_t @@ -552,7 +575,7 @@ bytes of the packet on success, and NULL on error. .BR pcap_next_ex () is passed two pointer arguments, one of which points to a .IR struct pcap_pkthdr * -and one of which points to a +and one of which points to a .IR "const u_char" *. It sets the first pointer to point to a .I struct pcap_pkthdr @@ -580,7 +603,9 @@ for packets to become available. On some, but all, platforms, if a read timeout was specified, the wait will terminate after the read timeout expires; applications should be prepared for this, as it happens on some platforms, but should not rely on it, as it -does not happen on other platforms. +does not happen on other platforms. Note that the wait might, or might +not, terminate even if no packets are available; applications should be +prepared for this to happen, but must not rely on it happening. .PP A handle can be put into ``non-blocking mode'', so that those routines will, rather than blocking, return an indication that no packets are @@ -596,8 +621,8 @@ Non-blocking mode is often combined with routines such as .BR select (2) or .BR poll (2) -or other routines a platform offers to wait for the availability of data -on any of a set of descriptors. To obtain, for a handle, a descriptor +or other routines a platform offers to wait for any of a set of +descriptors to be ready to read. To obtain, for a handle, a descriptor that can be used in those routines, call .BR pcap_get_selectable_fd (). Not all handles have such a descriptor available; @@ -606,7 +631,14 @@ will return \-1 if no such descriptor exists. In addition, for various reasons, one or more of those routines will not work properly with the descriptor; the documentation for .BR pcap_get_selectable_fd () -gives details. +gives details. Note that, just as an attempt to read packets from a +.B pcap_t +may not return any packets if the read timeout expires, a +.BR select (), +.BR poll (), +or other such call may, if the read timeout expires, indicate that a +descriptor is ready to read even if there are no packets available to +read. .TP .B Routines .RS diff --git a/external/bsd/libpcap/dist/pcap.c b/external/bsd/libpcap/dist/pcap.c index 5ef92a9887af..35c2e26bdbeb 100644 --- a/external/bsd/libpcap/dist/pcap.c +++ b/external/bsd/libpcap/dist/pcap.c @@ -1,4 +1,4 @@ -/* $NetBSD: pcap.c,v 1.5 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: pcap.c,v 1.6 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998 @@ -34,7 +34,7 @@ */ #include -__RCSID("$NetBSD: pcap.c,v 1.5 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: pcap.c,v 1.6 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -285,7 +285,8 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) pcap_t * pcap_create(const char *source, char *errbuf) { - return (dag_create(source, errbuf)); + int is_ours; + return (dag_create(source, errbuf, &is_ours)); } #elif defined(SEPTEL_ONLY) int @@ -297,7 +298,8 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) pcap_t * pcap_create(const char *source, char *errbuf) { - return (septel_create(source, errbuf)); + int is_ours; + return (septel_create(source, errbuf, &is_ours)); } #elif defined(SNF_ONLY) int @@ -309,7 +311,8 @@ pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) pcap_t * pcap_create(const char *source, char *errbuf) { - return (snf_create(source, errbuf)); + int is_ours; + return (snf_create(source, errbuf, &is_ours)); } #else /* regular pcap */ struct capture_source_type { @@ -566,6 +569,12 @@ pcap_create_common(const char *source, char *ebuf, size_t size) 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); } @@ -1836,6 +1845,12 @@ pcap_open_dead_with_tstamp_precision(int linktype, int snaplen, u_int precision) p->setmintocopy_op = pcap_setmintocopy_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); } diff --git a/external/bsd/libpcap/dist/pcap/bluetooth.h b/external/bsd/libpcap/dist/pcap/bluetooth.h index 00a01a9f2d73..1b1ffccfae48 100644 --- a/external/bsd/libpcap/dist/pcap/bluetooth.h +++ b/external/bsd/libpcap/dist/pcap/bluetooth.h @@ -1,4 +1,4 @@ -/* $NetBSD: bluetooth.h,v 1.2 2014/11/19 19:33:31 christos Exp $ */ +/* $NetBSD: bluetooth.h,v 1.3 2015/03/31 21:39:43 christos Exp $ */ /* * Copyright (c) 2006 Paolo Abeni (Italy) @@ -13,8 +13,8 @@ * 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. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @@ -32,7 +32,7 @@ * bluetooth data struct * By Paolo Abeni */ - + #ifndef _PCAP_BLUETOOTH_STRUCTS_H__ #define _PCAP_BLUETOOTH_STRUCTS_H__ diff --git a/external/bsd/libpcap/dist/pcap/bpf.h b/external/bsd/libpcap/dist/pcap/bpf.h index 66ef55a1b36f..2dc9865bfd71 100644 --- a/external/bsd/libpcap/dist/pcap/bpf.h +++ b/external/bsd/libpcap/dist/pcap/bpf.h @@ -1,4 +1,4 @@ -/* $NetBSD: bpf.h,v 1.6 2014/11/19 19:33:31 christos Exp $ */ +/* $NetBSD: bpf.h,v 1.7 2015/03/31 21:39:43 christos Exp $ */ /*- * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 @@ -6,7 +6,7 @@ * * This code is derived from the Stanford/CMU enet packet filter, * (net/enet.c) distributed as part of 4.3BSD, and code contributed - * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence * Berkeley Laboratory. * * Redistribution and use in source and binary forms, with or without @@ -61,7 +61,8 @@ * or Tru64 UNIX-style multiple-include protection (or, at least, * Tru64 UNIX 5.x-style; I don't have earlier versions available to check), * or AIX-style multiple-include protection (or, at least, AIX 5.x-style; - * I don't have earlier versions available to check). + * I don't have earlier versions available to check), or QNX-style + * multiple-include protection (as per GitHub pull request #394). * * We do not check for BPF_MAJOR_VERSION, as that's defined by * , which is directly or indirectly included in some @@ -70,7 +71,7 @@ * * This also provides our own multiple-include protection. */ -#if !defined(_NET_BPF_H_) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h) +#if !defined(_NET_BPF_H_) && !defined(_NET_BPF_H_INCLUDED) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h) #define lib_pcap_bpf_h #ifdef __cplusplus @@ -89,7 +90,7 @@ typedef u_int bpf_u_int32; #endif /* - * Alignment macros. BPF_WORDALIGN rounds up to the next + * Alignment macros. BPF_WORDALIGN rounds up to the next * even multiple of BPF_ALIGNMENT. * * Tcpdump's print-pflog.c uses this, so we define it here. @@ -108,7 +109,7 @@ struct bpf_program { u_int bf_len; struct bpf_insn *bf_insns; }; - + /* * Link-layer header type codes. * @@ -433,7 +434,7 @@ struct bpf_program { */ #define DLT_SUNATM 123 /* Solaris+SunATM */ -/* +/* * Reserved as per request from Kent Dahlgren * for private use. */ @@ -676,7 +677,7 @@ struct bpf_program { /* * Juniper-private data link type, as per request from - * Hannes Gredler . + * Hannes Gredler . * The DLT_ are used for prepending meta-information * like interface index, interface name * before standard Ethernet, PPP, Frelay & C-HDLC Frames @@ -693,7 +694,7 @@ struct bpf_program { /* * Juniper-private data link type, as per request from - * Hannes Gredler . + * Hannes Gredler . * The DLT_ is used for internal communication with a * voice Adapter Card (PIC) */ @@ -768,7 +769,7 @@ struct bpf_program { /* * Juniper-private data link type, as per request from - * Hannes Gredler . + * Hannes Gredler . * The DLT_ is used for internal communication with a * integrated service module (ISM). */ @@ -811,7 +812,7 @@ struct bpf_program { /* * Juniper-private data link type, as per request from - * Hannes Gredler . + * Hannes Gredler . * The DLT_ is used for capturing data on a secure tunnel interface. */ #define DLT_JUNIPER_ST 200 @@ -903,11 +904,11 @@ struct bpf_program { */ #define DLT_IEEE802_15_4_NONASK_PHY 215 -/* +/* * David Gibson requested this for * captures from the Linux kernel /dev/input/eventN devices. This * is used to communicate keystrokes and mouse movements from the - * Linux kernel to display systems, such as Xorg. + * Linux kernel to display systems, such as Xorg. */ #define DLT_LINUX_EVDEV 216 @@ -1107,7 +1108,7 @@ struct bpf_program { #define DLT_JUNIPER_ATM_CEMIC 238 /* - * NetFilter LOG messages + * NetFilter LOG messages * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets) * * Requested by Jakub Zawadzki @@ -1216,7 +1217,7 @@ struct bpf_program { /* * DLT type for upper-protocol layer PDU saves from wireshark. - * + * * the actual contents are determined by two TAGs stored with each * packet: * EXP_PDU_TAG_LINKTYPE the link type (LINKTYPE_ value) of the @@ -1316,7 +1317,19 @@ struct bpf_program { */ #define DLT_IPMI_HPM_2 260 -#define DLT_MATCHING_MAX 260 /* highest value in the "matching" range */ +/* + * per Joshua Wright , formats for Zwave captures. + */ +#define DLT_ZWAVE_R1_R2 261 +#define DLT_ZWAVE_R3 262 + +/* + * per Steve Karg , formats for Wattstopper + * Digital Lighting Management room bus serial protocol captures. + */ +#define DLT_WATTSTOPPER_DLM 263 + +#define DLT_MATCHING_MAX 263 /* highest value in the "matching" range */ /* * DLT and savefile link type values are split into a class and @@ -1468,6 +1481,16 @@ struct bpf_insn { bpf_u_int32 k; }; +/* + * Auxiliary data, for use when interpreting a filter intended for the + * Linux kernel when the kernel rejects the filter (requiring us to + * run it in userland). It contains VLAN tag information. + */ +struct bpf_aux_data { + u_short vlan_tag_present; + u_short vlan_tag; +}; + /* * Macros for insn array initializers. */ @@ -1477,9 +1500,11 @@ struct bpf_insn { #if __STDC__ || defined(__cplusplus) extern int bpf_validate(const struct bpf_insn *, int); extern u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int); +extern u_int bpf_filter_with_aux_data(const struct bpf_insn *, const u_char *, u_int, u_int, const struct bpf_aux_data *); #else extern int bpf_validate(); extern u_int bpf_filter(); +extern u_int bpf_filter(); #endif /* diff --git a/external/bsd/libpcap/dist/pcap/pcap.h b/external/bsd/libpcap/dist/pcap/pcap.h index ae6df907299f..bbaed1956a65 100644 --- a/external/bsd/libpcap/dist/pcap/pcap.h +++ b/external/bsd/libpcap/dist/pcap/pcap.h @@ -1,4 +1,4 @@ -/* $NetBSD: pcap.h,v 1.5 2014/11/19 19:33:31 christos Exp $ */ +/* $NetBSD: pcap.h,v 1.6 2015/03/31 21:39:43 christos Exp $ */ /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* @@ -416,6 +416,7 @@ int pcap_fileno(pcap_t *); pcap_dumper_t *pcap_dump_open(pcap_t *, const char *); pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp); +pcap_dumper_t *pcap_dump_open_append(pcap_t *, const char *); FILE *pcap_dump_file(pcap_dumper_t *); long pcap_dump_ftell(pcap_dumper_t *); int pcap_dump_flush(pcap_dumper_t *); @@ -428,13 +429,13 @@ void pcap_freealldevs(pcap_if_t *); const char *pcap_lib_version(void); /* - * On at least some versions of NetBSD, we don't want to declare + * On at least some versions of NetBSD and QNX, we don't want to declare * bpf_filter() here, as it's also be declared in , with a * different signature, but, on other BSD-flavored UN*Xes, it's not * declared in , so we *do* want to declare it here, so it's * declared when we build pcap-bpf.c. */ -#ifndef __NetBSD__ +#if !defined(__NetBSD__) && !defined(__QNX__) u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int); #endif int bpf_validate(const struct bpf_insn *f, int len); diff --git a/external/bsd/libpcap/dist/pcap/usb.h b/external/bsd/libpcap/dist/pcap/usb.h index b07483141733..0243eff45686 100644 --- a/external/bsd/libpcap/dist/pcap/usb.h +++ b/external/bsd/libpcap/dist/pcap/usb.h @@ -1,4 +1,4 @@ -/* $NetBSD: usb.h,v 1.2 2014/11/19 19:33:31 christos Exp $ */ +/* $NetBSD: usb.h,v 1.3 2015/03/31 21:39:43 christos Exp $ */ /* * Copyright (c) 2006 Paolo Abeni (Italy) @@ -13,8 +13,8 @@ * 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. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior written + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @@ -32,11 +32,11 @@ * Basic USB data struct * By Paolo Abeni */ - + #ifndef _PCAP_USB_STRUCTS_H__ #define _PCAP_USB_STRUCTS_H__ -/* +/* * possible transfer mode */ #define URB_TRANSFER_IN 0x80 diff --git a/external/bsd/libpcap/dist/pcap_breakloop.3pcap b/external/bsd/libpcap/dist/pcap_breakloop.3pcap index 95841ac6fb6a..4076d91e69ba 100644 --- a/external/bsd/libpcap/dist/pcap_breakloop.3pcap +++ b/external/bsd/libpcap/dist/pcap_breakloop.3pcap @@ -1,4 +1,4 @@ -.\" $NetBSD: pcap_breakloop.3pcap,v 1.2 2014/11/19 19:33:30 christos Exp $ +.\" $NetBSD: pcap_breakloop.3pcap,v 1.3 2015/03/31 21:39:42 christos Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. @@ -93,7 +93,7 @@ If \-2 is returned from .B pcap_dispatch() or .BR pcap_loop() , -the flag is cleared, so a subsequent call will resume reading packets. +the flag is cleared, so a subsequent call will resume reading packets. If a positive number is returned, the flag is not cleared, so a subsequent call will return \-2 and clear the flag. .SH SEE ALSO diff --git a/external/bsd/libpcap/dist/pcap_datalink_name_to_val.3pcap b/external/bsd/libpcap/dist/pcap_datalink_name_to_val.3pcap index cf7d5154076e..fc39134fd29a 100644 --- a/external/bsd/libpcap/dist/pcap_datalink_name_to_val.3pcap +++ b/external/bsd/libpcap/dist/pcap_datalink_name_to_val.3pcap @@ -1,4 +1,4 @@ -.\" $NetBSD: pcap_datalink_name_to_val.3pcap,v 1.2 2014/11/19 19:33:30 christos Exp $ +.\" $NetBSD: pcap_datalink_name_to_val.3pcap,v 1.3 2015/03/31 21:39:42 christos Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. @@ -43,6 +43,6 @@ removed, to the corresponding link-layer header type value. The translation is case-insensitive. .SH RETURN VALUE .B pcap_datalink_name_to_val() -returns 0 on success and \-1 on failure. +returns type value on success and \-1 on failure. .SH SEE ALSO pcap(3PCAP) diff --git a/external/bsd/libpcap/dist/pcap_dump.3pcap b/external/bsd/libpcap/dist/pcap_dump.3pcap index 51297f9a8086..7aecc56dfa2e 100644 --- a/external/bsd/libpcap/dist/pcap_dump.3pcap +++ b/external/bsd/libpcap/dist/pcap_dump.3pcap @@ -1,4 +1,4 @@ -.\" $NetBSD: pcap_dump.3pcap,v 1.2 2014/11/19 19:33:30 christos Exp $ +.\" $NetBSD: pcap_dump.3pcap,v 1.3 2015/03/31 21:39:42 christos Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. @@ -42,9 +42,9 @@ Note that its calling arguments are suitable for use with .B pcap_dispatch() or .BR pcap_loop() . -If called directly, the +If called directly, the .I user -parameter is of type +parameter is of type .B pcap_dumper_t as returned by .BR pcap_dump_open() . diff --git a/external/bsd/libpcap/dist/pcap_dump_open.3pcap.in b/external/bsd/libpcap/dist/pcap_dump_open.3pcap.in index 4fc1ddaacc4f..f55a71cdd791 100644 --- a/external/bsd/libpcap/dist/pcap_dump_open.3pcap.in +++ b/external/bsd/libpcap/dist/pcap_dump_open.3pcap.in @@ -29,6 +29,7 @@ pcap_dump_open, pcap_dump_fopen \- open a file to which to write packets .LP .ft B pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname); +pcap_dumper_t *pcap_dump_open_append(pcap_t *p, const char *fname); pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *fp); .ft .fi @@ -60,9 +61,19 @@ or returned by an earlier call to .BR pcap_open_live() , or .BR pcap_open_dead() . -The link-layer type and snapshot length from +The time stamp precision, link-layer type, and snapshot length from .I p are used as the link-layer type and snapshot length of the output file. +.PP +.B pcap_dump_open_append() +is like +.B pcap_dump_open +but does not create the file if it does not exist and, if it does +already exist, and is a pcap file with the same byte order as the host +opening the file, and has the same time stamp precision, link-layer +header type, and snapshot length as +.IR p , +it will write new packets at the end of the file. .SH RETURN VALUES A pointer to a .B pcap_dumper_t diff --git a/external/bsd/libpcap/dist/pcap_get_selectable_fd.3pcap b/external/bsd/libpcap/dist/pcap_get_selectable_fd.3pcap index f74b751efe5f..91cdb573429d 100644 --- a/external/bsd/libpcap/dist/pcap_get_selectable_fd.3pcap +++ b/external/bsd/libpcap/dist/pcap_get_selectable_fd.3pcap @@ -1,4 +1,4 @@ -.\" $NetBSD: pcap_get_selectable_fd.3pcap,v 1.2 2014/11/19 19:33:30 christos Exp $ +.\" $NetBSD: pcap_get_selectable_fd.3pcap,v 1.3 2015/03/31 21:39:42 christos Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. @@ -38,9 +38,9 @@ int pcap_get_selectable_fd(pcap_t *p); returns, on UNIX, a file descriptor number for a file descriptor on which one can do a -.B select() -or -.B poll() +.BR select() , +.BR poll() , +or other such call to wait for it to be possible to read packets without blocking, if such a descriptor exists, or \-1, if no such descriptor exists. Some network devices opened with @@ -56,6 +56,12 @@ or (for example, regular network devices on FreeBSD 4.3 and 4.4, and Endace DAG devices), so \-1 is returned for those devices. .PP +Note that a descriptor on which a read can be done without blocking may, +on some platforms, not have any packets to read if the read timeout has +expired. A call to +.B pcap_dispatch() +will return 0 in this case, but will not block. +.PP Note that in: .IP FreeBSD prior to FreeBSD 4.6; diff --git a/external/bsd/libpcap/dist/pcap_loop.3pcap b/external/bsd/libpcap/dist/pcap_loop.3pcap index 30c0a3f2f1c0..612e2c3a6d8c 100644 --- a/external/bsd/libpcap/dist/pcap_loop.3pcap +++ b/external/bsd/libpcap/dist/pcap_loop.3pcap @@ -1,4 +1,4 @@ -.\" $NetBSD: pcap_loop.3pcap,v 1.2 2014/11/19 19:33:30 christos Exp $ +.\" $NetBSD: pcap_loop.3pcap,v 1.3 2015/03/31 21:39:42 christos Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. @@ -79,6 +79,13 @@ causes all the packets received in one buffer to be processed when reading a live capture, and causes all the packets in the file to be processed when reading a ``savefile''. .PP +Note that, when doing a live capture on some platforms, if the read +timeout expires when there are no packets available, +.B pcap_dispatch() +will return 0, even when not in non-blocking mode, as there are no +packets to process. Applications should be prepared for this to happen, +but must not rely on it happening. +.PP .ft B (In older versions of libpcap, the behavior when \fIcnt\fP diff --git a/external/bsd/libpcap/dist/pcap_setdirection.3pcap b/external/bsd/libpcap/dist/pcap_setdirection.3pcap index da4d08dc51db..801e5ab0f252 100644 --- a/external/bsd/libpcap/dist/pcap_setdirection.3pcap +++ b/external/bsd/libpcap/dist/pcap_setdirection.3pcap @@ -1,4 +1,4 @@ -.\" $NetBSD: pcap_setdirection.3pcap,v 1.2 2014/11/19 19:33:30 christos Exp $ +.\" $NetBSD: pcap_setdirection.3pcap,v 1.3 2015/03/31 21:39:42 christos Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. @@ -39,7 +39,7 @@ is used to specify a direction that packets will be captured. is one of the constants .BR PCAP_D_IN , .B PCAP_D_OUT -or +or .BR PCAP_D_INOUT . .B PCAP_D_IN will only capture packets received by the device, diff --git a/external/bsd/libpcap/dist/pcap_setnonblock.3pcap b/external/bsd/libpcap/dist/pcap_setnonblock.3pcap index e0ecbec25c21..a0ffa4b98219 100644 --- a/external/bsd/libpcap/dist/pcap_setnonblock.3pcap +++ b/external/bsd/libpcap/dist/pcap_setnonblock.3pcap @@ -1,4 +1,4 @@ -.\" $NetBSD: pcap_setnonblock.3pcap,v 1.2 2014/11/19 19:33:30 christos Exp $ +.\" $NetBSD: pcap_setnonblock.3pcap,v 1.3 2015/03/31 21:39:42 christos Exp $ .\" .\" Copyright (c) 1994, 1996, 1997 .\" The Regents of the University of California. All rights reserved. @@ -59,6 +59,14 @@ immediately rather than blocking waiting for packets to arrive. and .B pcap_next() will not work in ``non-blocking'' mode. +.PP +When first activated with +.B pcap_activate() +or opened with +.B pcap_open_live() , +a capture handle is not in ``non-blocking mode''; a call to +.B pcap_setnonblock() +is required in order to put it into ``non-blocking'' mode. .SH RETURN VALUE .B pcap_getnonblock() returns the current ``non-blocking'' state of the capture descriptor; it diff --git a/external/bsd/libpcap/dist/pcap_tstamp_type_name_to_val.3pcap b/external/bsd/libpcap/dist/pcap_tstamp_type_name_to_val.3pcap index 0558a26393fb..d908aa5cdefb 100644 --- a/external/bsd/libpcap/dist/pcap_tstamp_type_name_to_val.3pcap +++ b/external/bsd/libpcap/dist/pcap_tstamp_type_name_to_val.3pcap @@ -1,4 +1,4 @@ -.\" $NetBSD: pcap_tstamp_type_name_to_val.3pcap,v 1.2 2014/11/19 19:33:30 christos Exp $ +.\" $NetBSD: pcap_tstamp_type_name_to_val.3pcap,v 1.3 2015/03/31 21:39:42 christos Exp $ .\" .\" .\" Copyright (c) 1994, 1996, 1997 @@ -40,7 +40,7 @@ translates a time stamp type name to the corresponding time stamp type value. The translation is case-insensitive. .SH RETURN VALUE .B pcap_tstamp_type_name_to_val() -returns 0 on success and +returns time stamp type value on success and .B PCAP_ERROR on failure. .SH SEE ALSO diff --git a/external/bsd/libpcap/dist/savefile.c b/external/bsd/libpcap/dist/savefile.c index e777d2a29253..1ac908bacf32 100644 --- a/external/bsd/libpcap/dist/savefile.c +++ b/external/bsd/libpcap/dist/savefile.c @@ -1,4 +1,4 @@ -/* $NetBSD: savefile.c,v 1.2 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: savefile.c,v 1.3 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 @@ -31,7 +31,7 @@ */ #include -__RCSID("$NetBSD: savefile.c,v 1.2 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: savefile.c,v 1.3 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -223,14 +223,14 @@ pcap_t* pcap_hopen_offline_with_tstamp_precision(intptr_t osfd, u_int precision, FILE *file; fd = _open_osfhandle(osfd, _O_RDONLY); - if ( fd < 0 ) + if ( fd < 0 ) { snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno)); return NULL; } file = _fdopen(fd, "rb"); - if ( file == NULL ) + if ( file == NULL ) { snprintf(errbuf, PCAP_ERRBUF_SIZE, pcap_strerror(errno)); return NULL; @@ -349,6 +349,11 @@ found: */ p->oneshot_callback = pcap_oneshot; + /* + * Savefiles never require special BPF code generation. + */ + p->bpf_codegen_flags = 0; + p->activated = 1; return (p); diff --git a/external/bsd/libpcap/dist/scanner.l b/external/bsd/libpcap/dist/scanner.l index d999ae1e1319..63ec27e35dec 100644 --- a/external/bsd/libpcap/dist/scanner.l +++ b/external/bsd/libpcap/dist/scanner.l @@ -1,4 +1,4 @@ -/* $NetBSD: scanner.l,v 1.6 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: scanner.l,v 1.7 2015/03/31 21:39:42 christos Exp $ */ %{ /* @@ -22,11 +22,7 @@ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include -__RCSID("$NetBSD: scanner.l,v 1.6 2014/11/19 19:33:30 christos Exp $"); - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif +__RCSID("$NetBSD: scanner.l,v 1.7 2015/03/31 21:39:42 christos Exp $"); #ifdef WIN32 #include @@ -285,6 +281,7 @@ vlan return VLAN; mpls return MPLS; pppoed return PPPOED; pppoes return PPPOES; +geneve return GENEVE; lane return LANE; llc return LLC; diff --git a/external/bsd/libpcap/dist/sf-pcap-ng.c b/external/bsd/libpcap/dist/sf-pcap-ng.c index 37b18069801b..a32f03773505 100644 --- a/external/bsd/libpcap/dist/sf-pcap-ng.c +++ b/external/bsd/libpcap/dist/sf-pcap-ng.c @@ -1,4 +1,4 @@ -/* $NetBSD: sf-pcap-ng.c,v 1.5 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: sf-pcap-ng.c,v 1.6 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 @@ -29,7 +29,7 @@ static const char rcsid[] _U_ = #endif #include -__RCSID("$NetBSD: sf-pcap-ng.c,v 1.5 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: sf-pcap-ng.c,v 1.6 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -669,7 +669,7 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf, /* * Check whether the first 4 bytes of the file are the block - * type for a pcap-ng savefile. + * type for a pcap-ng savefile. */ if (magic != BT_SHB) { /* @@ -1005,7 +1005,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) epbp->timestamp_low; } goto found; - + case BT_SPB: /* * Get a pointer to the fixed-length portion of the @@ -1197,7 +1197,7 @@ pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data) * Not a packet block, IDB, or SHB; ignore it. */ break; - } + } } found: @@ -1215,10 +1215,16 @@ found: } /* - * Convert the time stamp to a struct timeval. + * Convert the time stamp to seconds and fractions of a second, + * with the fractions being in units of the file-supplied resolution. */ sec = t / ps->ifaces[interface_id].tsresol + ps->ifaces[interface_id].tsoffset; frac = t % ps->ifaces[interface_id].tsresol; + + /* + * Convert the fractions from units of the file-supplied resolution + * to units of the user-requested resolution. + */ switch (ps->ifaces[interface_id].scale_type) { case PASS_THROUGH: @@ -1232,21 +1238,28 @@ found: case SCALE_DOWN: /* * The interface resolution is different from what the - * user wants; scale up or down to that resolution. + * user wants; convert the fractions to units of the + * resolution the user requested by multiplying by the + * quotient of the user-requested resolution and the + * file-supplied resolution. We do that by multiplying + * by the user-requested resolution and dividing by the + * file-supplied resolution, as the quotient might not + * fit in an integer. * * XXX - if ps->ifaces[interface_id].tsresol is a power * of 10, we could just multiply by the quotient of - * ps->ifaces[interface_id].tsresol and ps->user_tsresol - * in the scale-up case, and divide by the quotient of * ps->user_tsresol and ps->ifaces[interface_id].tsresol - * in the scale-down case, as we know those are integers, - * which would involve fewer arithmetic operations. + * in the scale-up case, and divide by the quotient of + * ps->ifaces[interface_id].tsresol and ps->user_tsresol + * in the scale-down case, as we know those will be integers. + * That would involve fewer arithmetic operations, and + * would run less risk of overflow. * * Is there something clever we could do if * ps->ifaces[interface_id].tsresol is a power of 2? */ - frac *= ps->ifaces[interface_id].tsresol; - frac /= ps->user_tsresol; + frac *= ps->user_tsresol; + frac /= ps->ifaces[interface_id].tsresol; break; } hdr->ts.tv_sec = sec; diff --git a/external/bsd/libpcap/dist/sf-pcap.c b/external/bsd/libpcap/dist/sf-pcap.c index d1588ba5a8be..22a922ef1857 100644 --- a/external/bsd/libpcap/dist/sf-pcap.c +++ b/external/bsd/libpcap/dist/sf-pcap.c @@ -1,4 +1,4 @@ -/* $NetBSD: sf-pcap.c,v 1.5 2014/11/19 19:33:30 christos Exp $ */ +/* $NetBSD: sf-pcap.c,v 1.6 2015/03/31 21:39:42 christos Exp $ */ /* * Copyright (c) 1993, 1994, 1995, 1996, 1997 @@ -36,7 +36,7 @@ static const char rcsid[] _U_ = #endif #include -__RCSID("$NetBSD: sf-pcap.c,v 1.5 2014/11/19 19:33:30 christos Exp $"); +__RCSID("$NetBSD: sf-pcap.c,v 1.6 2015/03/31 21:39:42 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -687,7 +687,7 @@ pcap_dump_open(pcap_t *p, const char *fname) */ pcap_dumper_t * pcap_dump_fopen(pcap_t *p, FILE *f) -{ +{ int linktype; linktype = dlt_to_linktype(p->linktype); @@ -702,6 +702,168 @@ pcap_dump_fopen(pcap_t *p, FILE *f) return (pcap_setup_dump(p, linktype, f, "stream")); } +pcap_dumper_t * +pcap_dump_open_append(pcap_t *p, const char *fname) +{ + FILE *f; + int linktype; + int amt_read; + struct pcap_file_header ph; + + linktype = dlt_to_linktype(p->linktype); + if (linktype == -1) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "%s: link-layer type %d isn't supported in savefiles", + fname, linktype); + return (NULL); + } + if (fname[0] == '-' && fname[1] == '\0') + return (pcap_setup_dump(p, linktype, stdout, "standard output")); + +#if !defined(WIN32) && !defined(MSDOS) + f = fopen(fname, "r+"); +#else + f = fopen(fname, "rb+"); +#endif + if (f == NULL) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", + fname, pcap_strerror(errno)); + return (NULL); + } + + /* + * Try to read a pcap header. + */ + amt_read = fread(&ph, 1, sizeof (ph), f); + if (amt_read != sizeof (ph)) { + if (ferror(f)) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", + fname, pcap_strerror(errno)); + fclose(f); + return (NULL); + } else if (feof(f) && amt_read > 0) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "%s: truncated pcap file header", fname); + fclose(f); + return (NULL); + } + } + +#if defined(WIN32) || defined(MSDOS) + /* + * We turn off buffering. + * XXX - why? And why not on the standard output? + */ + setbuf(f, NULL); +#endif + + /* + * If a header is already present and: + * + * it's not for a pcap file of the appropriate resolution + * and the right byte order for this machine; + * + * the link-layer header types don't match; + * + * the snapshot lengths don't match; + * + * return an error. + */ + if (amt_read > 0) { + /* + * A header is already present. + * Do the checks. + */ + switch (ph.magic) { + + case TCPDUMP_MAGIC: + if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_MICRO) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "%s: different time stamp precision, cannot append to file", fname); + fclose(f); + return (NULL); + } + break; + + case NSEC_TCPDUMP_MAGIC: + if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_NANO) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "%s: different time stamp precision, cannot append to file", fname); + fclose(f); + return (NULL); + } + break; + + case SWAPLONG(TCPDUMP_MAGIC): + case SWAPLONG(NSEC_TCPDUMP_MAGIC): + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "%s: different byte order, cannot append to file", fname); + fclose(f); + return (NULL); + + case KUZNETZOV_TCPDUMP_MAGIC: + case SWAPLONG(KUZNETZOV_TCPDUMP_MAGIC): + case NAVTEL_TCPDUMP_MAGIC: + case SWAPLONG(NAVTEL_TCPDUMP_MAGIC): + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "%s: not a pcap file to which we can append", fname); + fclose(f); + return (NULL); + + default: + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "%s: not a pcap file", fname); + fclose(f); + return (NULL); + } + + /* + * Good version? + */ + if (ph.version_major != PCAP_VERSION_MAJOR || + ph.version_minor != PCAP_VERSION_MINOR) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "%s: version is %u.%u, cannot append to file", fname, + ph.version_major, ph.version_minor); + fclose(f); + return (NULL); + } + if (linktype != (int)ph.linktype) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "%s: different linktype, cannot append to file", fname); + fclose(f); + return (NULL); + } + if (p->snapshot != (int)ph.snaplen) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "%s: different snaplen, cannot append to file", fname); + fclose(f); + return (NULL); + } + } else { + /* + * A header isn't present; attempt to write it. + */ + if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s", + fname, pcap_strerror(errno)); + (void)fclose(f); + return (NULL); + } + } + + /* + * Start writing at the end of the file. + */ + if (fseek(f, 0, SEEK_END) == -1) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't seek to end of %s: %s", + fname, pcap_strerror(errno)); + (void)fclose(f); + return (NULL); + } + return ((pcap_dumper_t *)f); +} + FILE * pcap_dump_file(pcap_dumper_t *p) { diff --git a/external/bsd/libpcap/dist/tests/filtertest.c b/external/bsd/libpcap/dist/tests/filtertest.c index b54185551441..a6c81a5d1f84 100644 --- a/external/bsd/libpcap/dist/tests/filtertest.c +++ b/external/bsd/libpcap/dist/tests/filtertest.c @@ -1,4 +1,4 @@ -/* $NetBSD: filtertest.c,v 1.2 2014/11/19 19:33:31 christos Exp $ */ +/* $NetBSD: filtertest.c,v 1.3 2015/03/31 21:39:43 christos Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 @@ -28,7 +28,7 @@ The Regents of the University of California. All rights reserved.\n"; #endif #include -__RCSID("$NetBSD: filtertest.c,v 1.2 2014/11/19 19:33:31 christos Exp $"); +__RCSID("$NetBSD: filtertest.c,v 1.3 2015/03/31 21:39:43 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -62,6 +62,9 @@ static void warn(const char *, ...) extern int optind; extern int opterr; extern char *optarg; +#ifdef BDEBUG +int dflag; +#endif /* * On Windows, we need to open the file in binary mode, so that @@ -183,10 +186,13 @@ main(int argc, char **argv) { char *cp; int op; +#ifndef BDEBUG int dflag; +#endif char *infile; int Oflag; long snaplen; + char *p; int dlt; bpf_u_int32 netmask = PCAP_NETMASK_UNKNOWN; char *cmdbuf; @@ -197,11 +203,19 @@ main(int argc, char **argv) if(wsockinit() != 0) return 1; #endif /* WIN32 */ +#ifndef BDEBUG dflag = 1; +#else + /* if optimizer debugging is enabled, output DOT graph + * `dflag=4' is equivalent to -dddd to follow -d/-dd/-ddd + * convention in tcpdump command line + */ + dflag = 4; +#endif infile = NULL; Oflag = 1; snaplen = 68; - + if ((cp = strrchr(argv[0], '/')) != NULL) program_name = cp + 1; else @@ -257,9 +271,12 @@ main(int argc, char **argv) } dlt = pcap_datalink_name_to_val(argv[optind]); - if (dlt < 0) - error("invalid data link type %s", argv[optind]); - + if (dlt < 0) { + dlt = (int)strtol(argv[optind], &p, 10); + if (p == argv[optind] || *p != '\0') + error("invalid data link type %s", argv[optind]); + } + if (infile) cmdbuf = read_infile(infile); else @@ -271,8 +288,21 @@ main(int argc, char **argv) if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) error("%s", pcap_geterr(pd)); + if (!bpf_validate(fcode.bf_insns, fcode.bf_len)) warn("Filter doesn't pass validation"); + +#ifdef BDEBUG + // replace line feed with space + for (cp = cmdbuf; *cp != '\0'; ++cp) { + if (*cp == '\r' || *cp == '\n') { + *cp = ' '; + } + } + // only show machine code if BDEBUG defined, since dflag > 3 + printf("machine codes for filter: %s\n", cmdbuf); +#endif + bpf_dump(&fcode, dflag); pcap_close(pd); exit(0); diff --git a/external/bsd/libpcap/dist/tests/findalldevstest.c b/external/bsd/libpcap/dist/tests/findalldevstest.c index 714eda04f3e8..b13c10539718 100644 --- a/external/bsd/libpcap/dist/tests/findalldevstest.c +++ b/external/bsd/libpcap/dist/tests/findalldevstest.c @@ -1,7 +1,7 @@ -/* $NetBSD: findalldevstest.c,v 1.2 2014/11/19 19:33:31 christos Exp $ */ +/* $NetBSD: findalldevstest.c,v 1.3 2015/03/31 21:39:43 christos Exp $ */ #include -__RCSID("$NetBSD: findalldevstest.c,v 1.2 2014/11/19 19:33:31 christos Exp $"); +__RCSID("$NetBSD: findalldevstest.c,v 1.3 2015/03/31 21:39:43 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -16,7 +16,7 @@ __RCSID("$NetBSD: findalldevstest.c,v 1.2 2014/11/19 19:33:31 christos Exp $"); #include -static void ifprint(pcap_if_t *d); +static int ifprint(pcap_if_t *d); static char *iptos(bpf_u_int32 in); int main(int argc, char **argv) @@ -25,7 +25,8 @@ int main(int argc, char **argv) pcap_if_t *d; char *s; bpf_u_int32 net, mask; - + int exit_status = 0; + char errbuf[PCAP_ERRBUF_SIZE+1]; if (pcap_findalldevs(&alldevs, errbuf) == -1) { @@ -34,12 +35,14 @@ int main(int argc, char **argv) } for(d=alldevs;d;d=d->next) { - ifprint(d); + if (!ifprint(d)) + exit_status = 2; } if ( (s = pcap_lookupdev(errbuf)) == NULL) { fprintf(stderr,"Error in pcap_lookupdev: %s\n",errbuf); + exit_status = 2; } else { @@ -49,21 +52,23 @@ int main(int argc, char **argv) if (pcap_lookupnet(s, &net, &mask, errbuf) < 0) { fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf); + exit_status = 2; } else { printf("Preferred device is on network: %s/%s\n",iptos(net), iptos(mask)); } - - exit(0); + + exit(exit_status); } -static void ifprint(pcap_if_t *d) +static int ifprint(pcap_if_t *d) { pcap_addr_t *a; #ifdef INET6 char ntop_buf[INET6_ADDRSTRLEN]; #endif + int status = 1; /* success */ printf("%s\n",d->name); if (d->description) @@ -71,8 +76,8 @@ static void ifprint(pcap_if_t *d) printf("\tLoopback: %s\n",(d->flags & PCAP_IF_LOOPBACK)?"yes":"no"); for(a=d->addresses;a;a=a->next) { - switch(a->addr->sa_family) - { + if (a->addr != NULL) + switch(a->addr->sa_family) { case AF_INET: printf("\tAddress Family: AF_INET\n"); if (a->addr) @@ -116,9 +121,15 @@ static void ifprint(pcap_if_t *d) default: printf("\tAddress Family: Unknown (%d)\n", a->addr->sa_family); break; + } + else + { + fprintf(stderr, "\tWarning: a->addr is NULL, skipping this address.\n"); + status = 0; } } printf("\n"); + return status; } /* From tcptraceroute */ diff --git a/external/bsd/libpcap/dist/tests/valgrindtest.c b/external/bsd/libpcap/dist/tests/valgrindtest.c index ddb98244f30a..bb29ff50edfc 100644 --- a/external/bsd/libpcap/dist/tests/valgrindtest.c +++ b/external/bsd/libpcap/dist/tests/valgrindtest.c @@ -1,4 +1,4 @@ -/* $NetBSD: valgrindtest.c,v 1.2 2014/11/19 19:33:31 christos Exp $ */ +/* $NetBSD: valgrindtest.c,v 1.3 2015/03/31 21:39:43 christos Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 @@ -28,7 +28,7 @@ The Regents of the University of California. All rights reserved.\n"; #endif #include -__RCSID("$NetBSD: valgrindtest.c,v 1.2 2014/11/19 19:33:31 christos Exp $"); +__RCSID("$NetBSD: valgrindtest.c,v 1.3 2015/03/31 21:39:43 christos Exp $"); #ifdef HAVE_CONFIG_H #include "config.h" @@ -236,7 +236,7 @@ main(int argc, char **argv) dorfmon = 0; useactivate = 0; infile = NULL; - + if ((cp = strrchr(argv[0], '/')) != NULL) program_name = cp + 1; else diff --git a/external/bsd/libpcap/lib/shlib_version b/external/bsd/libpcap/lib/shlib_version index d7d0dd23dbad..99e740219a43 100644 --- a/external/bsd/libpcap/lib/shlib_version +++ b/external/bsd/libpcap/lib/shlib_version @@ -1,5 +1,5 @@ -# $NetBSD: shlib_version,v 1.2 2013/04/06 17:29:12 christos Exp $ +# $NetBSD: shlib_version,v 1.3 2015/03/31 21:39:43 christos Exp $ # Remember to update distrib/sets/lists/base/shl.* when changing # major=5 -minor=0 +minor=1