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.
180 lines
4.5 KiB
180 lines
4.5 KiB
From d4306feb76ee9a6d9ecee63b152404bd0db0f97c Mon Sep 17 00:00:00 2001 |
|
From: Michal Sekletar <msekleta@redhat.com> |
|
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 <linux/if_packet.h> |
|
+#include <linux/filter.h> |
|
+#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 <stdint.h> |
|
+ |
|
#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 |
|
|
|
|