You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
214 lines
5.7 KiB
214 lines
5.7 KiB
7 years ago
|
From 06553e55d6ff2b203c4ab1dda2d6fb15c45e2896 Mon Sep 17 00:00:00 2001
|
||
|
From: Guy Harris <guy@alum.mit.edu>
|
||
|
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 <netinet/in.h>
|
||
|
#include <arpa/inet.h>
|
||
|
-#include <errno.h>
|
||
|
|
||
|
#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
|
||
|
|