Module Name: src Committed By: rmind Date: Thu Aug 29 14:25:41 UTC 2013
Modified Files: src/share/man/man4: bpf.4 src/sys/external/bsd/ipf/netinet: fil.c src/sys/net: bpf.c bpf.h bpf_filter.c if_ppp.c src/sys/net/npf: npf_ruleset.c Log Message: 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@ To generate a diff of this commit: cvs rdiff -u -r1.51 -r1.52 src/share/man/man4/bpf.4 cvs rdiff -u -r1.8 -r1.9 src/sys/external/bsd/ipf/netinet/fil.c cvs rdiff -u -r1.173 -r1.174 src/sys/net/bpf.c cvs rdiff -u -r1.59 -r1.60 src/sys/net/bpf.h cvs rdiff -u -r1.55 -r1.56 src/sys/net/bpf_filter.c cvs rdiff -u -r1.138 -r1.139 src/sys/net/if_ppp.c cvs rdiff -u -r1.20 -r1.21 src/sys/net/npf/npf_ruleset.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/share/man/man4/bpf.4 diff -u src/share/man/man4/bpf.4:1.51 src/share/man/man4/bpf.4:1.52 --- src/share/man/man4/bpf.4:1.51 Sun Oct 28 20:19:30 2012 +++ src/share/man/man4/bpf.4 Thu Aug 29 14:25:41 2013 @@ -1,6 +1,6 @@ .\" -*- 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 .\" The Regents of the University of California. All rights reserved. @@ -630,6 +630,16 @@ that copy the index register to the accu .It Sy BPF_MISC+BPF_TAX Ta X \*[Lt]- A .It Sy BPF_MISC+BPF_TXA Ta A \*[Lt]- X .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 .Pp The BPF interface provides the following macros to facilitate Index: src/sys/external/bsd/ipf/netinet/fil.c diff -u src/sys/external/bsd/ipf/netinet/fil.c:1.8 src/sys/external/bsd/ipf/netinet/fil.c:1.9 --- src/sys/external/bsd/ipf/netinet/fil.c:1.8 Wed Jan 9 13:23:20 2013 +++ src/sys/external/bsd/ipf/netinet/fil.c Thu Aug 29 14:25:40 2013 @@ -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. @@ -138,7 +138,7 @@ extern struct timeout ipf_slowtimer_ch; #if !defined(lint) #if defined(__NetBSD__) #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 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 $"; @@ -2405,8 +2405,13 @@ ipf_scanlist(fr_info_t *fin, u_32_t pass continue; mc = (u_char *)fin->fin_m; 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)) continue; +#endif break; } #endif Index: src/sys/net/bpf.c diff -u src/sys/net/bpf.c:1.173 src/sys/net/bpf.c:1.174 --- src/sys/net/bpf.c:1.173 Sat Oct 27 22:36:14 2012 +++ src/sys/net/bpf.c Thu Aug 29 14:25:41 2013 @@ -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 *(*c 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; Index: src/sys/net/bpf.h diff -u src/sys/net/bpf.h:1.59 src/sys/net/bpf.h:1.60 --- src/sys/net/bpf.h:1.59 Thu Mar 15 00:57:56 2012 +++ src/sys/net/bpf.h Thu Aug 29 14:25:41 2013 @@ -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_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); +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 Index: src/sys/net/bpf_filter.c diff -u src/sys/net/bpf_filter.c:1.55 src/sys/net/bpf_filter.c:1.56 --- src/sys/net/bpf_filter.c:1.55 Sat Oct 27 22:36:14 2012 +++ src/sys/net/bpf_filter.c Thu Aug 29 14:25:41 2013 @@ -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 * 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, co 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; } } } Index: src/sys/net/if_ppp.c diff -u src/sys/net/if_ppp.c:1.138 src/sys/net/if_ppp.c:1.139 --- src/sys/net/if_ppp.c:1.138 Sun Nov 25 09:06:43 2012 +++ src/sys/net/if_ppp.c Thu Aug 29 14:25:41 2013 @@ -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 * 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 * 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 * 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 /* Index: src/sys/net/npf/npf_ruleset.c diff -u src/sys/net/npf/npf_ruleset.c:1.20 src/sys/net/npf/npf_ruleset.c:1.21 --- src/sys/net/npf/npf_ruleset.c:1.20 Mon Mar 18 02:24:45 2013 +++ src/sys/net/npf/npf_ruleset.c Thu Aug 29 14:25:41 2013 @@ -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_ 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);