summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorrmind <rmind@NetBSD.org>2013-08-29 14:25:40 +0000
committerrmind <rmind@NetBSD.org>2013-08-29 14:25:40 +0000
commit77fa8a9336aedef9f5ba3fce13d8ddc2bf62d995 (patch)
treec1852c551afd17ec956bc5483c0f713fdacaa6f6 /sys/net
parent0e4dc5220ac207e97fbf5dfc0b15b7061c82c04c (diff)
Implement BPF_COP/BPF_COPX instructions in the misc category (BPF_MISC)
which add a capability to call external functions in a predetermined way. It can be thought as a BPF "coprocessor" -- a generic mechanism to offload more complex packet inspection operations. There is no default coprocessor and this functionality is not targeted to the /dev/bpf. This is primarily targeted to the kernel subsystems, therefore there is no way to set a custom coprocessor at the userlevel. Discussed on: tech-net@ OK: core@
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/bpf.c7
-rw-r--r--sys/net/bpf.h25
-rw-r--r--sys/net/bpf_filter.c69
-rw-r--r--sys/net/if_ppp.c20
-rw-r--r--sys/net/npf/npf_ruleset.c7
5 files changed, 106 insertions, 22 deletions
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index 05e2889d35c..41be01c4784 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -1,4 +1,4 @@
-/* $NetBSD: bpf.c,v 1.173 2012/10/27 22:36:14 alnsn Exp $ */
+/* $NetBSD: bpf.c,v 1.174 2013/08/29 14:25:41 rmind Exp $ */
/*
* Copyright (c) 1990, 1991, 1993
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.173 2012/10/27 22:36:14 alnsn Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bpf.c,v 1.174 2013/08/29 14:25:41 rmind Exp $");
#if defined(_KERNEL_OPT)
#include "opt_bpf.h"
@@ -1382,7 +1382,8 @@ bpf_deliver(struct bpf_if *bp, void *(*cpfn)(void *, const void *, size_t),
if (d->bd_jitcode != NULL)
slen = d->bd_jitcode(pkt, pktlen, buflen);
else
- slen = bpf_filter(d->bd_filter, pkt, pktlen, buflen);
+ slen = bpf_filter(bpf_def_ctx, d->bd_filter,
+ pkt, pktlen, buflen);
if (!slen) {
continue;
diff --git a/sys/net/bpf.h b/sys/net/bpf.h
index ff928cb6b4e..866a9181750 100644
--- a/sys/net/bpf.h
+++ b/sys/net/bpf.h
@@ -1,4 +1,4 @@
-/* $NetBSD: bpf.h,v 1.59 2012/03/15 00:57:56 christos Exp $ */
+/* $NetBSD: bpf.h,v 1.60 2013/08/29 14:25:41 rmind Exp $ */
/*
* Copyright (c) 1990, 1991, 1993
@@ -254,6 +254,8 @@ struct bpf_hdr32 {
/* misc */
#define BPF_MISCOP(code) ((code) & 0xf8)
#define BPF_TAX 0x00
+#define BPF_COP 0x20
+#define BPF_COPX 0x40
#define BPF_TXA 0x80
/*
@@ -378,10 +380,25 @@ void bpf_ops_handover_exit(void);
void bpfilterattach(int);
-#endif
+struct bpf_ctx;
+typedef struct bpf_ctx bpf_ctx_t;
+typedef uint32_t (*bpf_copfunc_t)(const struct mbuf *, uint32_t, uint32_t *);
+extern bpf_ctx_t *bpf_def_ctx;
+
+bpf_ctx_t *bpf_create(void);
+void bpf_destroy(bpf_ctx_t *);
-int bpf_validate(const struct bpf_insn *, int);
-u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+int bpf_set_cop(bpf_ctx_t *, const bpf_copfunc_t *, size_t);
+u_int bpf_filter(bpf_ctx_t *, const struct bpf_insn *,
+ const u_char *, u_int, u_int);
+int bpf_validate(const struct bpf_insn *, int);
+
+#else
+
+int bpf_validate(const struct bpf_insn *, int);
+u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+
+#endif
__END_DECLS
diff --git a/sys/net/bpf_filter.c b/sys/net/bpf_filter.c
index e8a6b4499e8..cbf4ea7a527 100644
--- a/sys/net/bpf_filter.c
+++ b/sys/net/bpf_filter.c
@@ -1,4 +1,4 @@
-/* $NetBSD: bpf_filter.c,v 1.55 2012/10/27 22:36:14 alnsn Exp $ */
+/* $NetBSD: bpf_filter.c,v 1.56 2013/08/29 14:25:41 rmind Exp $ */
/*-
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bpf_filter.c,v 1.55 2012/10/27 22:36:14 alnsn Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bpf_filter.c,v 1.56 2013/08/29 14:25:41 rmind Exp $");
#if 0
#if !(defined(lint) || defined(KERNEL))
@@ -51,6 +51,41 @@ static const char rcsid[] =
#include <sys/kmem.h>
#include <sys/endian.h>
+#include <net/bpf.h>
+
+#ifdef _KERNEL
+
+struct bpf_ctx {
+ const bpf_copfunc_t * copfuncs;
+ size_t nfuncs;
+};
+
+/* Default BPF context (zeroed). */
+static bpf_ctx_t bpf_def_ctx1;
+bpf_ctx_t * bpf_def_ctx = &bpf_def_ctx1;
+
+bpf_ctx_t *
+bpf_create(void)
+{
+ return kmem_zalloc(sizeof(bpf_ctx_t), KM_SLEEP);
+}
+
+void
+bpf_destroy(bpf_ctx_t *bc)
+{
+ kmem_free(bc, sizeof(bpf_ctx_t));
+}
+
+int
+bpf_set_cop(bpf_ctx_t *bc, const bpf_copfunc_t *funcs, size_t n)
+{
+ bc->copfuncs = funcs;
+ bc->nfuncs = n;
+ return 0;
+}
+
+#endif
+
#define EXTRACT_SHORT(p) be16dec(p)
#define EXTRACT_LONG(p) be32dec(p)
@@ -143,13 +178,23 @@ m_xbyte(const struct mbuf *m, uint32_t k, int *err)
* wirelen is the length of the original packet
* buflen is the amount of data present
*/
+#ifdef _KERNEL
+u_int
+bpf_filter(bpf_ctx_t *bc, const struct bpf_insn *pc, const u_char *p,
+ u_int wirelen, u_int buflen)
+#else
u_int
bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen,
u_int buflen)
+#endif
{
uint32_t A, X, k;
uint32_t mem[BPF_MEMWORDS];
+#ifdef _KERNEL
+ KASSERT(bc != NULL);
+#endif
+
if (pc == 0) {
/*
* No filter means accept all.
@@ -465,6 +510,26 @@ bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen,
case BPF_MISC|BPF_TXA:
A = X;
continue;
+
+ case BPF_MISC|BPF_COP:
+#ifdef _KERNEL
+ if (pc->k < bc->nfuncs) {
+ const bpf_copfunc_t fn = bc->copfuncs[pc->k];
+ A = fn((const struct mbuf *)p, A, mem);
+ continue;
+ }
+#endif
+ return 0;
+
+ case BPF_MISC|BPF_COPX:
+#ifdef _KERNEL
+ if (X < bc->nfuncs) {
+ const bpf_copfunc_t fn = bc->copfuncs[X];
+ A = fn((const struct mbuf *)p, A, mem);
+ continue;
+ }
+#endif
+ return 0;
}
}
}
diff --git a/sys/net/if_ppp.c b/sys/net/if_ppp.c
index bbdbbf4f4db..5a42db16323 100644
--- a/sys/net/if_ppp.c
+++ b/sys/net/if_ppp.c
@@ -1,4 +1,4 @@
-/* $NetBSD: if_ppp.c,v 1.138 2012/11/25 09:06:43 mbalmer Exp $ */
+/* $NetBSD: if_ppp.c,v 1.139 2013/08/29 14:25:41 rmind Exp $ */
/* Id: if_ppp.c,v 1.6 1997/03/04 03:33:00 paulus Exp */
/*
@@ -102,7 +102,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ppp.c,v 1.138 2012/11/25 09:06:43 mbalmer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ppp.c,v 1.139 2013/08/29 14:25:41 rmind Exp $");
#include "ppp.h"
@@ -946,8 +946,8 @@ pppoutput(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst,
* but only if it is a data packet.
*/
if (sc->sc_pass_filt_out.bf_insns != 0
- && bpf_filter(sc->sc_pass_filt_out.bf_insns, (u_char *) m0,
- len, 0) == 0) {
+ && bpf_filter(bpf_def_ctx, sc->sc_pass_filt_out.bf_insns,
+ (u_char *)m0, len, 0) == 0) {
error = 0; /* drop this packet */
goto bad;
}
@@ -956,8 +956,8 @@ pppoutput(struct ifnet *ifp, struct mbuf *m0, const struct sockaddr *dst,
* Update the time we sent the most recent packet.
*/
if (sc->sc_active_filt_out.bf_insns == 0
- || bpf_filter(sc->sc_active_filt_out.bf_insns, (u_char *) m0,
- len, 0))
+ || bpf_filter(bpf_def_ctx, sc->sc_active_filt_out.bf_insns,
+ (u_char *)m0, len, 0))
sc->sc_last_sent = time_second;
#else
/*
@@ -1584,15 +1584,15 @@ ppp_inproc(struct ppp_softc *sc, struct mbuf *m)
* if it counts as link activity.
*/
if (sc->sc_pass_filt_in.bf_insns != 0
- && bpf_filter(sc->sc_pass_filt_in.bf_insns, (u_char *) m,
- ilen, 0) == 0) {
+ && bpf_filter(bpf_def_ctx, sc->sc_pass_filt_in.bf_insns,
+ (u_char *)m, ilen, 0) == 0) {
/* drop this packet */
m_freem(m);
return;
}
if (sc->sc_active_filt_in.bf_insns == 0
- || bpf_filter(sc->sc_active_filt_in.bf_insns, (u_char *) m,
- ilen, 0))
+ || bpf_filter(bpf_def_ctx, sc->sc_active_filt_in.bf_insns,
+ (u_char *)m, ilen, 0))
sc->sc_last_recv = time_second;
#else
/*
diff --git a/sys/net/npf/npf_ruleset.c b/sys/net/npf/npf_ruleset.c
index 9ba06421c37..0163cb76056 100644
--- a/sys/net/npf/npf_ruleset.c
+++ b/sys/net/npf/npf_ruleset.c
@@ -1,4 +1,4 @@
-/* $NetBSD: npf_ruleset.c,v 1.20 2013/03/18 02:24:45 rmind Exp $ */
+/* $NetBSD: npf_ruleset.c,v 1.21 2013/08/29 14:25:41 rmind Exp $ */
/*-
* Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.20 2013/03/18 02:24:45 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.21 2013/08/29 14:25:41 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@@ -681,7 +681,8 @@ npf_rule_inspect(npf_cache_t *npc, nbuf_t *nbuf, const npf_rule_t *rl,
case NPF_CODE_BPF: {
struct mbuf *m = nbuf_head_mbuf(nbuf);
size_t pktlen = m_length(m);
- return bpf_filter(code, (unsigned char *)m, pktlen, 0) != 0;
+ return bpf_filter(bpf_def_ctx, code, (unsigned char *)m,
+ pktlen, 0) != 0;
}
default:
KASSERT(false);