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.
181 lines
4.5 KiB
181 lines
4.5 KiB
7 years ago
|
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
|
||
|
|