From 2cd29a22595951ec8c6fc24d34dd3b0cab0ae181 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Nov 19 2015 15:59:09 +0000 Subject: import libpcap-1.5.3-8.el7 --- diff --git a/SOURCES/0001-Add-names-for-DLT_NETLINK.patch b/SOURCES/0001-Add-names-for-DLT_NETLINK.patch new file mode 100644 index 0000000..56d29e4 --- /dev/null +++ b/SOURCES/0001-Add-names-for-DLT_NETLINK.patch @@ -0,0 +1,29 @@ +From 2048727a901ef7d9d3803c9206730d11b2fd6ebf Mon Sep 17 00:00:00 2001 +From: Jakub Zawadzki +Date: Sat, 7 Dec 2013 23:37:23 +0100 +Subject: [PATCH] Add names for DLT_NETLINK + +Before patch: + tcpdump: listening on nlmon0, link-type 253, capture size 65535 bytes + +After patch: + tcpdump: listening on nlmon0, link-type NETLINK (Linux netlink), capture size 65535 bytes +--- + pcap.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/pcap.c b/pcap.c +index 626938c..faa9762 100644 +--- a/pcap.c ++++ b/pcap.c +@@ -1203,6 +1203,7 @@ static struct dlt_choice dlt_choices[] = { + DLT_CHOICE(DLT_NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"), + DLT_CHOICE(DLT_IPOIB, "RFC 4391 IP-over-Infiniband"), + DLT_CHOICE(DLT_DBUS, "D-Bus"), ++ DLT_CHOICE(DLT_NETLINK, "Linux netlink"), + DLT_CHOICE_SENTINEL + }; + +-- +2.4.3 + diff --git a/SOURCES/0001-Fix-link-type-for-nlmon.patch b/SOURCES/0001-Fix-link-type-for-nlmon.patch new file mode 100644 index 0000000..98e1b85 --- /dev/null +++ b/SOURCES/0001-Fix-link-type-for-nlmon.patch @@ -0,0 +1,31 @@ +From 674f2e8bd990be129932c5778d951ffee6eaefbd Mon Sep 17 00:00:00 2001 +From: Jakub Zawadzki +Date: Sat, 7 Dec 2013 23:36:47 +0100 +Subject: [PATCH] Fix link-type for nlmon. + +Before patch: + tcpdump: listening on nlmon0, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes + +After patch: + tcpdump: listening on nlmon0, link-type 253, capture size 65535 bytes +--- + pcap-linux.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/pcap-linux.c b/pcap-linux.c +index 8800c96..7c07793 100644 +--- a/pcap-linux.c ++++ b/pcap-linux.c +@@ -3195,7 +3195,8 @@ activate_new(pcap_t *handle) + * same applies to LAPD capture. + */ + if (handle->linktype != DLT_LINUX_IRDA && +- handle->linktype != DLT_LINUX_LAPD) ++ handle->linktype != DLT_LINUX_LAPD && ++ handle->linktype != DLT_NETLINK) + handle->linktype = DLT_LINUX_SLL; + } + +-- +2.4.3 + diff --git a/SOURCES/0001-Handle-using-cooked-mode-for-DLT_NETLINK-in-activate.patch b/SOURCES/0001-Handle-using-cooked-mode-for-DLT_NETLINK-in-activate.patch new file mode 100644 index 0000000..575e30f --- /dev/null +++ b/SOURCES/0001-Handle-using-cooked-mode-for-DLT_NETLINK-in-activate.patch @@ -0,0 +1,58 @@ +From b5d27a8197012ac2b1b52621be2cfe0b5fc2b47e Mon Sep 17 00:00:00 2001 +From: Guy Harris +Date: Tue, 19 Nov 2013 10:45:42 -0800 +Subject: [PATCH] Handle using cooked mode for DLT_NETLINK in activate_new(). + +That's how we handle it elsewhere; if that can be cleaned up, especially +if we can avoid opening a raw socket in the cooked-mode case, that would +be nice. + +Note this in comments. + +(cherry picked from eeb0348fe8d74800af37759618270fb8bed17443) + +Conflicts: + pcap-linux.c +--- + pcap-linux.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/pcap-linux.c b/pcap-linux.c +index e6343b0..a0e543c 100644 +--- a/pcap-linux.c ++++ b/pcap-linux.c +@@ -2941,7 +2941,9 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok) + /* Don't expect IP packet out of this interfaces... */ + handle->linktype = DLT_LINUX_IRDA; + /* We need to save packet direction for IrDA decoding, +- * so let's use "Linux-cooked" mode. Jean II */ ++ * so let's use "Linux-cooked" mode. Jean II ++ * ++ * XXX - this is handled in activate_new(). */ + //handlep->cooked = 1; + break; + +@@ -2982,8 +2984,11 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok) + * We need to use cooked mode, so that in sll_protocol we + * pick up the netlink protocol type such as NETLINK_ROUTE, + * NETLINK_GENERIC, NETLINK_FIB_LOOKUP, etc. ++ * ++ * XXX - this is now handled in activate_new() + */ +- handle->cooked = 1; ++ ++ /* handlep->cooked = 1; */ + break; + + default: +@@ -3122,6 +3127,7 @@ activate_new(pcap_t *handle) + handle->linktype == DLT_LINUX_SLL || + handle->linktype == DLT_LINUX_IRDA || + handle->linktype == DLT_LINUX_LAPD || ++ handle->linktype == DLT_NETLINK || + (handle->linktype == DLT_EN10MB && + (strncmp("isdn", device, 4) == 0 || + strncmp("isdY", device, 4) == 0))) { +-- +2.4.3 + diff --git a/SOURCES/0001-Introduce-bpf_filter1-function.patch b/SOURCES/0001-Introduce-bpf_filter1-function.patch new file mode 100644 index 0000000..19783df --- /dev/null +++ b/SOURCES/0001-Introduce-bpf_filter1-function.patch @@ -0,0 +1,180 @@ +From d4306feb76ee9a6d9ecee63b152404bd0db0f97c Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Tue, 5 Aug 2014 16:46:19 +0200 +Subject: [PATCH] Introduce bpf_filter1 function + +Function takes additional argument which is a pointer to bpf_aux_data +structure. This newly introduced struct holds auxiliary data provided by caller +to specify additional data needed to implement some BPF extensions while +executing filter in userspace. + +bpf_filter1 currently implements support for two BPF extesions, namely +vlan_tci and vlan_pr. + +(cherry picked from 02e420f820750e970c93068c01ea10d4c16f2b9a) + +Conflicts: + bpf/net/bpf_filter.c +--- + bpf/net/bpf_filter.c | 77 +++++++++++++++++++++++++++++++++++++++++++--------- + pcap/bpf.h | 10 +++++++ + 2 files changed, 74 insertions(+), 13 deletions(-) + +diff --git a/bpf/net/bpf_filter.c b/bpf/net/bpf_filter.c +index 0c4fb00..3409a9b 100644 +--- a/bpf/net/bpf_filter.c ++++ b/bpf/net/bpf_filter.c +@@ -200,6 +200,17 @@ m_xhalf(m, k, err) + } + #endif + ++#ifdef __linux__ ++#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 +@@ -208,11 +219,12 @@ m_xhalf(m, k, err) + * in all other cases, p is a pointer to a buffer and buflen is its size. + */ + u_int +-bpf_filter(pc, p, wirelen, buflen) ++bpf_filter1(pc, p, wirelen, buflen, aux_data) + register const struct bpf_insn *pc; + register const u_char *p; + u_int wirelen; + register u_int buflen; ++ register const struct bpf_aux_data *aux_data; + { + register u_int32 A, X; + register int k; +@@ -288,22 +300,50 @@ bpf_filter(pc, p, wirelen, buflen) + continue; + + case BPF_LD|BPF_B|BPF_ABS: +- k = pc->k; +- if (k >= buflen) { ++ { ++#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 >= buflen) { + #if defined(KERNEL) || defined(_KERNEL) +- if (m == NULL) +- return 0; +- n = m; +- MINDEX(len, n, k); +- A = mtod(n, u_char *)[k]; +- continue; ++ if (m == NULL) ++ return 0; ++ n = m; ++ MINDEX(len, n, k); ++ A = mtod(n, u_char *)[k]; ++ continue; + #else +- return 0; ++ 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; + } +- A = p[k]; +- continue; +- + case BPF_LD|BPF_W|BPF_LEN: + A = wirelen; + continue; +@@ -532,6 +572,17 @@ bpf_filter(pc, p, wirelen, buflen) + } + } + ++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_filter1(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/pcap/bpf.h b/pcap/bpf.h +index 8286ed5..495f326 100644 +--- a/pcap/bpf.h ++++ b/pcap/bpf.h +@@ -70,6 +70,9 @@ + * + * This also provides our own multiple-include protection. + */ ++ ++#include ++ + #if !defined(_NET_BPF_H_) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h) + #define lib_pcap_bpf_h + +@@ -1317,6 +1320,11 @@ struct bpf_insn { + bpf_u_int32 k; + }; + ++struct bpf_aux_data { ++ uint16_t vlan_tag_present; ++ uint16_t vlan_tag; ++}; ++ + /* + * Macros for insn array initializers. + */ +@@ -1326,9 +1334,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_filter1(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 + + /* +-- +2.4.3 + diff --git a/SOURCES/0001-bpf-make-sure-sll-header-size-if-accounted-for.patch b/SOURCES/0001-bpf-make-sure-sll-header-size-if-accounted-for.patch new file mode 100644 index 0000000..25a8562 --- /dev/null +++ b/SOURCES/0001-bpf-make-sure-sll-header-size-if-accounted-for.patch @@ -0,0 +1,46 @@ +From 98e98bf9cc6ee76d7861db966708b1e51cc6e014 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Tue, 15 Sep 2015 13:30:37 +0200 +Subject: [PATCH] bpf: make sure sll header size if accounted for + +This got reverted when backporting bpf_filter_with_auxdata. + +Related: #1176612 +--- + pcap-linux.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/pcap-linux.c b/pcap-linux.c +index a5b8953..f7f2aae 100644 +--- a/pcap-linux.c ++++ b/pcap-linux.c +@@ -4306,7 +4306,7 @@ static int pcap_handle_packet_mmap( + 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) ++ if (bpf_filter_with_aux_data(handle->fcode.bf_insns, bp, tp_len, snaplen, &aux_data) == 0) + return 0; + } + +@@ -4316,7 +4316,7 @@ static int pcap_handle_packet_mmap( + /* get required packet info from ring header */ + pcaphdr.ts.tv_sec = tp_sec; + pcaphdr.ts.tv_usec = tp_usec; +- pcaphdr.caplen = tp_snaplen; ++ pcaphdr.caplen = snaplen; + pcaphdr.len = tp_len; + + /* if required build in place the sll header*/ +@@ -4329,7 +4329,7 @@ static int pcap_handle_packet_mmap( + #if defined(HAVE_TPACKET2) || defined(HAVE_TPACKET3) + if (tp_vlan_tci_valid && + handlep->vlan_offset != -1 && +- tp_snaplen >= (unsigned int) handlep->vlan_offset) ++ snaplen >= (unsigned int) handlep->vlan_offset) + { + struct vlan_tag *tag; + +-- +2.4.3 + diff --git a/SOURCES/0001-linktype-add-netlink-link-dlt-type.patch b/SOURCES/0001-linktype-add-netlink-link-dlt-type.patch new file mode 100644 index 0000000..609cd21 --- /dev/null +++ b/SOURCES/0001-linktype-add-netlink-link-dlt-type.patch @@ -0,0 +1,92 @@ +From 23d2673796e60c7fea6ba218eb084cbd59e7271b Mon Sep 17 00:00:00 2001 +From: Daniel Borkmann +Date: Mon, 18 Nov 2013 15:39:37 -0800 +Subject: [PATCH] linktype: add netlink link/dlt type + +With Linux 3.11, we have the possibility to debug local netlink traffic +[1] i.e. the workflow looks like this: + +Setup: + modprobe nlmon + ip link add type nlmon + ip link set nlmon0 up + +Capture: + tcpdump -i nlmon0 ... + +Teardown: + ip link set nlmon0 down + ip link del dev nlmon0 + rmmod nlmon + +For pcap interoperability, introduce a common link type for netlink +captures. +--- + pcap-common.c | 7 ++++++- + pcap-linux.c | 13 +++++++++++++ + pcap/bpf.h | 7 ++++++- + 3 files changed, 25 insertions(+), 2 deletions(-) + +diff --git a/pcap-common.c b/pcap-common.c +index 6175a5a..f26d22e 100644 +--- a/pcap-common.c ++++ b/pcap-common.c +@@ -932,7 +932,12 @@ + */ + #define LINKTYPE_WIRESHARK_UPPER_PDU 252 + +-#define LINKTYPE_MATCHING_MAX 252 /* highest value in the "matching" range */ ++/* ++ * Link-layer header type for the netlink protocol (nlmon devices). ++ */ ++#define LINKTYPE_NETLINK 253 ++ ++#define LINKTYPE_MATCHING_MAX 253 /* highest value in the "matching" range */ + + static struct linktype_map { + int dlt; +diff --git a/pcap-linux.c b/pcap-linux.c +index e817382..0651522 100644 +--- a/pcap-linux.c ++++ b/pcap-linux.c +@@ -2972,6 +2972,19 @@ static void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok) + handle->linktype = DLT_IEEE802_15_4_NOFCS; + break; + ++#ifndef ARPHRD_NETLINK ++#define ARPHRD_NETLINK 824 ++#endif ++ case ARPHRD_NETLINK: ++ handle->linktype = DLT_NETLINK; ++ /* ++ * We need to use cooked mode, so that in sll_protocol we ++ * pick up the netlink protocol type such as NETLINK_ROUTE, ++ * NETLINK_GENERIC, NETLINK_FIB_LOOKUP, etc. ++ */ ++ handle->cooked = 1; ++ break; ++ + default: + handle->linktype = -1; + break; +diff --git a/pcap/bpf.h b/pcap/bpf.h +index ad36eb6..8286ed5 100644 +--- a/pcap/bpf.h ++++ b/pcap/bpf.h +@@ -1224,7 +1224,12 @@ struct bpf_program { + */ + #define DLT_WIRESHARK_UPPER_PDU 252 + +-#define DLT_MATCHING_MAX 252 /* highest value in the "matching" range */ ++/* ++ * DLT type for the netlink protocol (nlmon devices). ++ */ ++#define DLT_NETLINK 253 ++ ++#define DLT_MATCHING_MAX 253 /* highest value in the "matching" range */ + + /* + * DLT and savefile link type values are split into a class and +-- +2.4.3 + diff --git a/SOURCES/0002-Use-BPF-extensions-in-compiled-filters.patch b/SOURCES/0002-Use-BPF-extensions-in-compiled-filters.patch new file mode 100644 index 0000000..e419caa --- /dev/null +++ b/SOURCES/0002-Use-BPF-extensions-in-compiled-filters.patch @@ -0,0 +1,236 @@ +From e80ed31b6e3ab778a7e0dd53348f488a91456cfc Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 31 Oct 2014 15:19:54 +0100 +Subject: [PATCH 2/2] Use BPF extensions in compiled filters + +libpcap will generate BPF filter code which uses BPF extensions if target +platform supports them. Currently supported BPF extensions are vlan_tci and +vlan_pr. + +Also to properly handle such filters when filtering in userspace libpcap now +employs bpf_filter1. + +(cherry picked from 04660eb1e56102e2369473cae2538e4d3d263607) + +Conflicts: + pcap-linux.c +--- + gencode.c | 110 +++++++++++++++++++++++++++++++++++++++++++++-------------- + pcap-linux.c | 23 +++++++++---- + 2 files changed, 102 insertions(+), 31 deletions(-) + +diff --git a/gencode.c b/gencode.c +index d58ea30..2ff725e 100644 +--- a/gencode.c ++++ b/gencode.c +@@ -58,6 +58,7 @@ static const char rcsid[] _U_ = + + #include + #include ++#include + + #endif /* WIN32 */ + +@@ -135,9 +136,9 @@ static pcap_t *bpf_pcap; + + /* Hack for updating VLAN, MPLS, and PPPoE offsets. */ + #ifdef WIN32 +-static u_int orig_linktype = (u_int)-1, orig_nl = (u_int)-1, label_stack_depth = (u_int)-1; ++static u_int orig_linktype = (u_int)-1, orig_nl = (u_int)-1, 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 orig_linktype = -1U, orig_nl = -1U, label_stack_depth = -1U, vlan_stack_depth = -1U; + #endif + + /* XXX */ +@@ -962,6 +963,7 @@ init_linktype(p) + orig_linktype = -1; + orig_nl = -1; + label_stack_depth = 0; ++ vlan_stack_depth = 0; + + reg_off_ll = -1; + reg_off_macpl = -1; +@@ -7861,6 +7863,76 @@ gen_ahostop(eaddr, dir) + /* NOTREACHED */ + } + ++#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT) ++static int skf_ad_vlan_tag_present_supported(int bpf_extensions) { ++ return bpf_extensions >= SKF_AD_VLAN_TAG_PRESENT; ++} ++ ++static struct block * ++gen_vlan_bpf_extensions(int vlan_num) { ++ struct block *b0, *b1; ++ struct slist *s; ++ int val = 0, len, r; ++ ++ len = sizeof(val); ++ r = getsockopt(bpf_pcap->fd, SOL_SOCKET, SO_BPF_EXTENSIONS, &val, &len); ++ if (r < 0) ++ return NULL; ++ ++ if (!skf_ad_vlan_tag_present_supported(val)) ++ return NULL; ++ ++ /* 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_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; ++ ++ return b0; ++} ++ + /* + * support IEEE 802.1Q VLAN trunk over ethernet + */ +@@ -7912,36 +7984,24 @@ gen_vlan(vlan_num) + 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) ++ if (!vlan_stack_depth) { ++ b0 = gen_vlan_bpf_extensions(vlan_num); ++ if (!b0) ++ b0 = gen_vlan_no_bpf_extensions(vlan_num); ++ } ++ else + #endif +- break; +- ++ b0 = gen_vlan_no_bpf_extensions(vlan_num); ++ break; + default: + bpf_error("no VLAN support for data link type %d", + linktype); + /*NOTREACHED*/ + } + ++ vlan_stack_depth++; ++ + return (b0); + } + +diff --git a/pcap-linux.c b/pcap-linux.c +index a0e543c..68e6d05 100644 +--- a/pcap-linux.c ++++ b/pcap-linux.c +@@ -1475,6 +1475,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 +@@ -1658,6 +1659,11 @@ pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) + tag->vlan_tpid = htons(ETH_P_8021Q); + 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; + } + } +@@ -1702,8 +1708,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_filter1(handle->fcode.bf_insns, bp, ++ packet_len, caplen, &aux_data) == 0) + { + /* rejected by filter */ + return 0; +@@ -4270,10 +4276,15 @@ static int pcap_handle_packet_mmap( + snaplen += sizeof(struct sll_header); + } + +- if (handlep->filter_in_userland && handle->fcode.bf_insns && +- (bpf_filter(handle->fcode.bf_insns, bp, +- tp_len, snaplen) == 0)) +- return 0; ++ 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_filter1(handle->fcode.bf_insns, bp, tp_len, tp_snaplen, &aux_data) == 0) ++ return 0; ++ } + + if (!linux_check_direction(handle, sll)) + return 0; +-- +2.4.3 + diff --git a/SOURCES/0003-More-descriptive-name-for-bpf_filter1.patch b/SOURCES/0003-More-descriptive-name-for-bpf_filter1.patch new file mode 100644 index 0000000..13e264a --- /dev/null +++ b/SOURCES/0003-More-descriptive-name-for-bpf_filter1.patch @@ -0,0 +1,101 @@ +From e58e6b25c82cc2f76f08b291e14f4e81f4ae1364 Mon Sep 17 00:00:00 2001 +From: Guy Harris +Date: Wed, 5 Nov 2014 11:18:51 -0800 +Subject: [PATCH 3/3] More descriptive name for bpf_filter1(). + +Call it bpf_filter_with_aux_data(), to better indicate what it does. + +Also expand some comments and clean up white space a bit. + +(cherry picked from 20119d41be224cf9ea821155ad0b267f7e40f234) + +Conflicts: + pcap-linux.c +--- + bpf/net/bpf_filter.c | 7 +++++-- + pcap-linux.c | 7 +++---- + pcap/bpf.h | 7 ++++++- + 3 files changed, 14 insertions(+), 7 deletions(-) + +diff --git a/bpf/net/bpf_filter.c b/bpf/net/bpf_filter.c +index 3409a9b..307f980 100644 +--- a/bpf/net/bpf_filter.c ++++ b/bpf/net/bpf_filter.c +@@ -215,11 +215,14 @@ enum { + * 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. + */ + u_int +-bpf_filter1(pc, p, wirelen, buflen, aux_data) ++bpf_filter_with_aux_data(pc, p, wirelen, buflen, aux_data) + register const struct bpf_insn *pc; + register const u_char *p; + u_int wirelen; +@@ -579,7 +582,7 @@ bpf_filter(pc, p, wirelen, buflen) + u_int wirelen; + register u_int buflen; + { +- return bpf_filter1(pc, p, wirelen, buflen, NULL); ++ return bpf_filter_with_aux_data(pc, p, wirelen, buflen, NULL); + } + + +diff --git a/pcap-linux.c b/pcap-linux.c +index 68e6d05..a370858 100644 +--- a/pcap-linux.c ++++ b/pcap-linux.c +@@ -1708,9 +1708,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_filter1(handle->fcode.bf_insns, bp, +- packet_len, caplen, &aux_data) == 0) +- { ++ if (bpf_filter_with_aux_data(handle->fcode.bf_insns, bp, ++ packet_len, caplen, &aux_data) == 0) { + /* rejected by filter */ + return 0; + } +@@ -4282,7 +4281,7 @@ static int pcap_handle_packet_mmap( + aux_data.vlan_tag = tp_vlan_tci & 0x0fff; + aux_data.vlan_tag_present = tp_vlan_tci_valid; + +- if (bpf_filter1(handle->fcode.bf_insns, bp, tp_len, tp_snaplen, &aux_data) == 0) ++ if (bpf_filter_with_aux_data(handle->fcode.bf_insns, bp, tp_len, tp_snaplen, &aux_data) == 0) + return 0; + } + +diff --git a/pcap/bpf.h b/pcap/bpf.h +index 495f326..29efd7e 100644 +--- a/pcap/bpf.h ++++ b/pcap/bpf.h +@@ -1320,6 +1320,11 @@ 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 { + uint16_t vlan_tag_present; + uint16_t vlan_tag; +@@ -1334,7 +1339,7 @@ struct bpf_aux_data { + #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_filter1(const struct bpf_insn *, const u_char *, u_int, u_int, const struct bpf_aux_data *); ++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(); +-- +2.4.3 + diff --git a/SOURCES/0004-Get-rid-of-unused-variable.patch b/SOURCES/0004-Get-rid-of-unused-variable.patch new file mode 100644 index 0000000..3112a40 --- /dev/null +++ b/SOURCES/0004-Get-rid-of-unused-variable.patch @@ -0,0 +1,37 @@ +From 98ab67580f4cdcede021f6f5a2d9d50bb86bff55 Mon Sep 17 00:00:00 2001 +From: Guy Harris +Date: Wed, 5 Nov 2014 11:19:39 -0800 +Subject: [PATCH 4/4] Get rid of unused variable. + +Also clean up white space a bit. + +(cherry picked from 86db77ce320dd9e81e5cc7b93ac9adf26643b140) +--- + gencode.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/gencode.c b/gencode.c +index 2ff725e..9c1d17b 100644 +--- a/gencode.c ++++ b/gencode.c +@@ -7940,7 +7940,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) +@@ -8012,7 +8012,7 @@ struct block * + gen_mpls(label_num) + int label_num; + { +- struct block *b0,*b1; ++ struct block *b0, *b1; + + /* + * Change the offsets to point to the type and data fields within +-- +2.4.3 + diff --git a/SOURCES/0005-Move-the-socket-ops-out-of-gencode.c.patch b/SOURCES/0005-Move-the-socket-ops-out-of-gencode.c.patch new file mode 100644 index 0000000..685904e --- /dev/null +++ b/SOURCES/0005-Move-the-socket-ops-out-of-gencode.c.patch @@ -0,0 +1,213 @@ +From 06553e55d6ff2b203c4ab1dda2d6fb15c45e2896 Mon Sep 17 00:00:00 2001 +From: Guy Harris +Date: Wed, 5 Nov 2014 14:33:14 -0800 +Subject: [PATCH 5/5] Move the socket ops out of gencode.c. + +Instead, do it in pcap-linux.c, and have it set a flag in the pcap_t +structure to indicate to the code in gencode.c that it needs to generate +special VLAN-handling code. + +(cherry picked from 612503bb0801a49a1c6ebe9c82591289b1d2e5c9) + +Conflicts: + pcap-linux.c +--- + gencode.c | 37 ++++++++++++++----------------------- + pcap-int.h | 10 ++++++++++ + pcap-linux.c | 24 ++++++++++++++++++++++++ + pcap.c | 12 ++++++++++++ + savefile.c | 5 +++++ + 5 files changed, 65 insertions(+), 23 deletions(-) + +diff --git a/gencode.c b/gencode.c +index 9c1d17b..6b3772f 100644 +--- a/gencode.c ++++ b/gencode.c +@@ -58,7 +58,6 @@ static const char rcsid[] _U_ = + + #include + #include +-#include + + #endif /* WIN32 */ + +@@ -7864,23 +7863,11 @@ gen_ahostop(eaddr, dir) + } + + #if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT) +-static int skf_ad_vlan_tag_present_supported(int bpf_extensions) { +- return bpf_extensions >= SKF_AD_VLAN_TAG_PRESENT; +-} +- + static struct block * +-gen_vlan_bpf_extensions(int vlan_num) { ++gen_vlan_bpf_extensions(int vlan_num) ++{ + struct block *b0, *b1; + struct slist *s; +- int val = 0, len, r; +- +- len = sizeof(val); +- r = getsockopt(bpf_pcap->fd, SOL_SOCKET, SO_BPF_EXTENSIONS, &val, &len); +- if (r < 0) +- return NULL; +- +- if (!skf_ad_vlan_tag_present_supported(val)) +- return NULL; + + /* generate new filter code based on extracting packet + * metadata */ +@@ -7908,7 +7895,8 @@ gen_vlan_bpf_extensions(int vlan_num) { + #endif + + static struct block * +-gen_vlan_no_bpf_extensions(int vlan_num) { ++gen_vlan_no_bpf_extensions(int vlan_num) ++{ + struct block *b0, *b1; + + /* check for VLAN, including QinQ */ +@@ -7985,14 +7973,17 @@ gen_vlan(vlan_num) + case DLT_NETANALYZER: + case DLT_NETANALYZER_TRANSPARENT: + #if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT) +- if (!vlan_stack_depth) { +- b0 = gen_vlan_bpf_extensions(vlan_num); +- if (!b0) +- b0 = gen_vlan_no_bpf_extensions(vlan_num); +- } +- else ++ if (vlan_stack_depth == 0) { ++ /* ++ * 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); ++ b0 = gen_vlan_no_bpf_extensions(vlan_num); + break; + default: + bpf_error("no VLAN support for data link type %d", +diff --git a/pcap-int.h b/pcap-int.h +index 0c27ec7..c9dbb5f 100644 +--- a/pcap-int.h ++++ b/pcap-int.h +@@ -182,6 +182,11 @@ struct pcap { + pcap_direction_t direction; + + /* ++ * Flags to affect BPF code generation. ++ */ ++ int bpf_codegen_flags; ++ ++ /* + * Placeholder for filter code if bpf not in kernel. + */ + struct bpf_program fcode; +@@ -228,6 +233,11 @@ struct pcap { + }; + + /* ++ * 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 + * `struct timeval'; `struct timeval' has 32-bit tv_sec values on some +diff --git a/pcap-linux.c b/pcap-linux.c +index a370858..a82f4eb 100644 +--- a/pcap-linux.c ++++ b/pcap-linux.c +@@ -3024,6 +3024,10 @@ activate_new(pcap_t *handle) + #endif + int err = 0; + struct packet_mreq mr; ++#ifdef SO_BPF_EXTENSIONS ++ int bpf_extensions; ++ socklen_t len; ++#endif + + /* + * Open a socket with protocol family packet. If the +@@ -3342,6 +3346,26 @@ activate_new(pcap_t *handle) + /* Save the socket FD in the pcap structure */ + 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?) ++ */ ++ len = sizeof(bpf_extensions); ++ ++ 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 */ ++ ++ ++ + #if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS) + if (handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) { + int nsec_tstamps = 1; +diff --git a/pcap.c b/pcap.c +index 6b16cea..74dc708 100644 +--- a/pcap.c ++++ b/pcap.c +@@ -558,6 +558,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); + } + +@@ -1810,6 +1816,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/savefile.c b/savefile.c +index 73e3ea9..98f9c82 100644 +--- a/savefile.c ++++ b/savefile.c +@@ -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); +-- +2.4.3 + diff --git a/SPECS/libpcap.spec b/SPECS/libpcap.spec index 8e87dfb..ceab764 100644 --- a/SPECS/libpcap.spec +++ b/SPECS/libpcap.spec @@ -1,7 +1,7 @@ Name: libpcap Epoch: 14 Version: 1.5.3 -Release: 4%{?dist}.2 +Release: 8%{?dist} Summary: A system-independent interface for user-level packet capture Group: Development/Libraries License: BSD with advertising @@ -16,6 +16,17 @@ Patch4: 0001-NFLOG-don-t-crash-trying-to-filter-at-link-layer.patch Patch5: 0001-pcap-linux-don-t-use-TPACKETV3-for-memory-mmapped-ca.patch Patch6: 0001-Make-sure-the-userland-filtering-happens-correctly-o.patch Patch7: 0001-bpf-increase-snaplen-if-doing-cooked-mode-userspace-.patch +Patch8: 0001-linktype-add-netlink-link-dlt-type.patch +Patch9: 0001-Handle-using-cooked-mode-for-DLT_NETLINK-in-activate.patch +Patch10: 0001-Introduce-bpf_filter1-function.patch +Patch11: 0002-Use-BPF-extensions-in-compiled-filters.patch +Patch12: 0003-More-descriptive-name-for-bpf_filter1.patch +Patch13: 0004-Get-rid-of-unused-variable.patch +Patch14: 0005-Move-the-socket-ops-out-of-gencode.c.patch +Patch15: 0001-Add-names-for-DLT_NETLINK.patch +Patch16: 0001-Fix-link-type-for-nlmon.patch +Patch17: 0001-bpf-make-sure-sll-header-size-if-accounted-for.patch + %description Libpcap provides a portable framework for low-level network @@ -84,12 +95,20 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/libpcap.a %{_mandir}/man5/pcap*.5* %changelog -* Mon Apr 20 2015 Michal Sekletar - 14:1.5.3-4.2 -- make sure that userland bpf filter interpreter is given snaplen such that size of - cooked header is accounted for (#1207666) +* Tue Sep 15 2015 Michal Sekletar - 14:1.5.3-8 +- make sure that sll header size is accounted for (#1176612) + +* Wed Jul 08 2015 Michal Sekletar - 14:1.5.3-7 +- make sure that netlink monitor interfaces are also properly recognized by tcpdump (#1031974) -* Tue Mar 31 2015 Michal Sekletar - 14:1.5.3-4.1 -- display also first packet when capturing in cooked mode (#1207666) +* Tue Jun 16 2015 Michal Sekletar - 14:1.5.3-6 +- libpcap now correctly recognizes Netlink datalink type (#1031974) +- fix vlan tagged packet filtering (#1079525) + +* Tue Mar 31 2015 Michal Sekletar - 14:1.5.3-5 +- display also first packet when capturing in cooked mode (#1176612) +- make sure that userland bpf filter interpreter is given snaplen such that size of + cooked header is account for * Tue Dec 2 2014 Michal Sekletar - 14:1.5.3-4 - disable TPACKET_V3 memory mapped packet capture on AF_PACKET socket, use TPACKET_V2 instead (#1085096)