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