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@
This commit is contained in:
parent
8bb6eda9b2
commit
1962fa8781
@ -1,6 +1,6 @@
|
|||||||
.\" -*- nroff -*-
|
.\" -*- nroff -*-
|
||||||
.\"
|
.\"
|
||||||
.\" $NetBSD: bpf.4,v 1.51 2012/10/28 20:19:30 alnsn Exp $
|
.\" $NetBSD: bpf.4,v 1.52 2013/08/29 14:25:41 rmind Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 1990, 1991, 1992, 1993, 1994
|
.\" Copyright (c) 1990, 1991, 1992, 1993, 1994
|
||||||
.\" The Regents of the University of California. All rights reserved.
|
.\" The Regents of the University of California. All rights reserved.
|
||||||
@ -630,6 +630,16 @@ that copy the index register to the accumulator or vice versa.
|
|||||||
.It Sy BPF_MISC+BPF_TAX Ta X \*[Lt]- A
|
.It Sy BPF_MISC+BPF_TAX Ta X \*[Lt]- A
|
||||||
.It Sy BPF_MISC+BPF_TXA Ta A \*[Lt]- X
|
.It Sy BPF_MISC+BPF_TXA Ta A \*[Lt]- X
|
||||||
.El
|
.El
|
||||||
|
.Pp
|
||||||
|
Also, two instructions to call a "coprocessor" if initialized by the kernel
|
||||||
|
component. There is no coprocessor by default.
|
||||||
|
.Bl -column "BPF_MISC+BPF_COP" "A \*[Lt]- funcs[X](...)" -offset indent
|
||||||
|
.It Sy BPF_MISC+BPF_COP Ta A \*[Lt]- funcs[k](..)
|
||||||
|
.It Sy BPF_MISC+BPF_COPX Ta A \*[Lt]- funcs[X](..)
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
If the coprocessor is not set or the function index is out of range, these
|
||||||
|
instructions will abort the program and return zero.
|
||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
The BPF interface provides the following macros to facilitate
|
The BPF interface provides the following macros to facilitate
|
||||||
|
9
sys/external/bsd/ipf/netinet/fil.c
vendored
9
sys/external/bsd/ipf/netinet/fil.c
vendored
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: fil.c,v 1.8 2013/01/09 13:23:20 christos Exp $ */
|
/* $NetBSD: fil.c,v 1.9 2013/08/29 14:25:40 rmind Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2012 by Darren Reed.
|
* Copyright (C) 2012 by Darren Reed.
|
||||||
@ -138,7 +138,7 @@ extern struct timeout ipf_slowtimer_ch;
|
|||||||
#if !defined(lint)
|
#if !defined(lint)
|
||||||
#if defined(__NetBSD__)
|
#if defined(__NetBSD__)
|
||||||
#include <sys/cdefs.h>
|
#include <sys/cdefs.h>
|
||||||
__KERNEL_RCSID(0, "$NetBSD: fil.c,v 1.8 2013/01/09 13:23:20 christos Exp $");
|
__KERNEL_RCSID(0, "$NetBSD: fil.c,v 1.9 2013/08/29 14:25:40 rmind Exp $");
|
||||||
#else
|
#else
|
||||||
static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed";
|
static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed";
|
||||||
static const char rcsid[] = "@(#)Id: fil.c,v 1.1.1.2 2012/07/22 13:45:07 darrenr Exp $";
|
static const char rcsid[] = "@(#)Id: fil.c,v 1.1.1.2 2012/07/22 13:45:07 darrenr Exp $";
|
||||||
@ -2405,8 +2405,13 @@ ipf_scanlist(fr_info_t *fin, u_32_t pass)
|
|||||||
continue;
|
continue;
|
||||||
mc = (u_char *)fin->fin_m;
|
mc = (u_char *)fin->fin_m;
|
||||||
wlen = fin->fin_dlen + fin->fin_hlen;
|
wlen = fin->fin_dlen + fin->fin_hlen;
|
||||||
|
#if defined(__NetBSD__)
|
||||||
|
if (!bpf_filter(bpf_def_ctx, fr->fr_data, mc, wlen, 0))
|
||||||
|
continue;
|
||||||
|
#else
|
||||||
if (!bpf_filter(fr->fr_data, mc, wlen, 0))
|
if (!bpf_filter(fr->fr_data, mc, wlen, 0))
|
||||||
continue;
|
continue;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -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
|
* Copyright (c) 1990, 1991, 1993
|
||||||
@ -39,7 +39,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#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)
|
#if defined(_KERNEL_OPT)
|
||||||
#include "opt_bpf.h"
|
#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)
|
if (d->bd_jitcode != NULL)
|
||||||
slen = d->bd_jitcode(pkt, pktlen, buflen);
|
slen = d->bd_jitcode(pkt, pktlen, buflen);
|
||||||
else
|
else
|
||||||
slen = bpf_filter(d->bd_filter, pkt, pktlen, buflen);
|
slen = bpf_filter(bpf_def_ctx, d->bd_filter,
|
||||||
|
pkt, pktlen, buflen);
|
||||||
|
|
||||||
if (!slen) {
|
if (!slen) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -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
|
* Copyright (c) 1990, 1991, 1993
|
||||||
@ -254,6 +254,8 @@ struct bpf_hdr32 {
|
|||||||
/* misc */
|
/* misc */
|
||||||
#define BPF_MISCOP(code) ((code) & 0xf8)
|
#define BPF_MISCOP(code) ((code) & 0xf8)
|
||||||
#define BPF_TAX 0x00
|
#define BPF_TAX 0x00
|
||||||
|
#define BPF_COP 0x20
|
||||||
|
#define BPF_COPX 0x40
|
||||||
#define BPF_TXA 0x80
|
#define BPF_TXA 0x80
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -378,10 +380,25 @@ void bpf_ops_handover_exit(void);
|
|||||||
|
|
||||||
void bpfilterattach(int);
|
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;
|
||||||
|
|
||||||
int bpf_validate(const struct bpf_insn *, int);
|
bpf_ctx_t *bpf_create(void);
|
||||||
u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
|
void bpf_destroy(bpf_ctx_t *);
|
||||||
|
|
||||||
|
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
|
__END_DECLS
|
||||||
|
|
||||||
|
@ -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
|
* Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
|
||||||
@ -37,7 +37,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#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 0
|
||||||
#if !(defined(lint) || defined(KERNEL))
|
#if !(defined(lint) || defined(KERNEL))
|
||||||
@ -51,6 +51,41 @@ static const char rcsid[] =
|
|||||||
#include <sys/kmem.h>
|
#include <sys/kmem.h>
|
||||||
#include <sys/endian.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_SHORT(p) be16dec(p)
|
||||||
#define EXTRACT_LONG(p) be32dec(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
|
* wirelen is the length of the original packet
|
||||||
* buflen is the amount of data present
|
* 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
|
u_int
|
||||||
bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen,
|
bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen,
|
||||||
u_int buflen)
|
u_int buflen)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
uint32_t A, X, k;
|
uint32_t A, X, k;
|
||||||
uint32_t mem[BPF_MEMWORDS];
|
uint32_t mem[BPF_MEMWORDS];
|
||||||
|
|
||||||
|
#ifdef _KERNEL
|
||||||
|
KASSERT(bc != NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (pc == 0) {
|
if (pc == 0) {
|
||||||
/*
|
/*
|
||||||
* No filter means accept all.
|
* 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:
|
case BPF_MISC|BPF_TXA:
|
||||||
A = X;
|
A = X;
|
||||||
continue;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 */
|
/* Id: if_ppp.c,v 1.6 1997/03/04 03:33:00 paulus Exp */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -102,7 +102,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#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"
|
#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.
|
* but only if it is a data packet.
|
||||||
*/
|
*/
|
||||||
if (sc->sc_pass_filt_out.bf_insns != 0
|
if (sc->sc_pass_filt_out.bf_insns != 0
|
||||||
&& bpf_filter(sc->sc_pass_filt_out.bf_insns, (u_char *) m0,
|
&& bpf_filter(bpf_def_ctx, sc->sc_pass_filt_out.bf_insns,
|
||||||
len, 0) == 0) {
|
(u_char *)m0, len, 0) == 0) {
|
||||||
error = 0; /* drop this packet */
|
error = 0; /* drop this packet */
|
||||||
goto bad;
|
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.
|
* Update the time we sent the most recent packet.
|
||||||
*/
|
*/
|
||||||
if (sc->sc_active_filt_out.bf_insns == 0
|
if (sc->sc_active_filt_out.bf_insns == 0
|
||||||
|| bpf_filter(sc->sc_active_filt_out.bf_insns, (u_char *) m0,
|
|| bpf_filter(bpf_def_ctx, sc->sc_active_filt_out.bf_insns,
|
||||||
len, 0))
|
(u_char *)m0, len, 0))
|
||||||
sc->sc_last_sent = time_second;
|
sc->sc_last_sent = time_second;
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
@ -1584,15 +1584,15 @@ ppp_inproc(struct ppp_softc *sc, struct mbuf *m)
|
|||||||
* if it counts as link activity.
|
* if it counts as link activity.
|
||||||
*/
|
*/
|
||||||
if (sc->sc_pass_filt_in.bf_insns != 0
|
if (sc->sc_pass_filt_in.bf_insns != 0
|
||||||
&& bpf_filter(sc->sc_pass_filt_in.bf_insns, (u_char *) m,
|
&& bpf_filter(bpf_def_ctx, sc->sc_pass_filt_in.bf_insns,
|
||||||
ilen, 0) == 0) {
|
(u_char *)m, ilen, 0) == 0) {
|
||||||
/* drop this packet */
|
/* drop this packet */
|
||||||
m_freem(m);
|
m_freem(m);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (sc->sc_active_filt_in.bf_insns == 0
|
if (sc->sc_active_filt_in.bf_insns == 0
|
||||||
|| bpf_filter(sc->sc_active_filt_in.bf_insns, (u_char *) m,
|
|| bpf_filter(bpf_def_ctx, sc->sc_active_filt_in.bf_insns,
|
||||||
ilen, 0))
|
(u_char *)m, ilen, 0))
|
||||||
sc->sc_last_recv = time_second;
|
sc->sc_last_recv = time_second;
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
|
@ -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.
|
* Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
|
||||||
@ -34,7 +34,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/cdefs.h>
|
#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/param.h>
|
||||||
#include <sys/types.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: {
|
case NPF_CODE_BPF: {
|
||||||
struct mbuf *m = nbuf_head_mbuf(nbuf);
|
struct mbuf *m = nbuf_head_mbuf(nbuf);
|
||||||
size_t pktlen = m_length(m);
|
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:
|
default:
|
||||||
KASSERT(false);
|
KASSERT(false);
|
||||||
|
Loading…
Reference in New Issue
Block a user