1*57718be8SEnji Cooper /* $NetBSD: h_bpf.h,v 1.2 2014/07/08 21:44:26 alnsn Exp $ */ 2*57718be8SEnji Cooper 3*57718be8SEnji Cooper /*- 4*57718be8SEnji Cooper * Copyright (c) 2014 Alexander Nasonov. 5*57718be8SEnji Cooper * All rights reserved. 6*57718be8SEnji Cooper * 7*57718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 8*57718be8SEnji Cooper * modification, are permitted provided that the following conditions 9*57718be8SEnji Cooper * are met: 10*57718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 11*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 12*57718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 13*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 14*57718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 15*57718be8SEnji Cooper * 16*57718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 17*57718be8SEnji Cooper * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18*57718be8SEnji Cooper * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19*57718be8SEnji Cooper * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20*57718be8SEnji Cooper * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21*57718be8SEnji Cooper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22*57718be8SEnji Cooper * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23*57718be8SEnji Cooper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24*57718be8SEnji Cooper * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25*57718be8SEnji Cooper * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26*57718be8SEnji Cooper * SUCH DAMAGE. 27*57718be8SEnji Cooper */ 28*57718be8SEnji Cooper 29*57718be8SEnji Cooper #ifndef _TESTS_NET_BPF_H_BPF_H_ 30*57718be8SEnji Cooper #define _TESTS_NET_BPF_H_BPF_H_ 31*57718be8SEnji Cooper 32*57718be8SEnji Cooper #include <sys/param.h> 33*57718be8SEnji Cooper #include <sys/mbuf.h> 34*57718be8SEnji Cooper 35*57718be8SEnji Cooper #include <net/bpf.h> 36*57718be8SEnji Cooper #include <net/bpfjit.h> 37*57718be8SEnji Cooper 38*57718be8SEnji Cooper #include <rump/rump.h> 39*57718be8SEnji Cooper #include <rump/rump_syscalls.h> 40*57718be8SEnji Cooper 41*57718be8SEnji Cooper #include <stdint.h> 42*57718be8SEnji Cooper #include <string.h> 43*57718be8SEnji Cooper 44*57718be8SEnji Cooper /* XXX These declarations don't look kosher. */ 45*57718be8SEnji Cooper int rumpns_bpf_validate(const struct bpf_insn *, int); 46*57718be8SEnji Cooper unsigned int rumpns_bpf_filter_ext(const bpf_ctx_t *, 47*57718be8SEnji Cooper const struct bpf_insn *, bpf_args_t *); 48*57718be8SEnji Cooper bpfjit_func_t rumpns_bpfjit_generate_code(const bpf_ctx_t *, 49*57718be8SEnji Cooper const struct bpf_insn *, size_t); 50*57718be8SEnji Cooper void rumpns_bpfjit_free_code(bpfjit_func_t); 51*57718be8SEnji Cooper 52*57718be8SEnji Cooper /* 53*57718be8SEnji Cooper * Init mbuf chain with one or two chunks. The first chunk holds 54*57718be8SEnji Cooper * [pkt, pkt + split] bytes, the second chunk (if it's not empty) 55*57718be8SEnji Cooper * holds (pkt + split, pkt + pktsize) bytes. 56*57718be8SEnji Cooper * The function returns (const uint8_t *)mb1. 57*57718be8SEnji Cooper */ 58*57718be8SEnji Cooper static inline const uint8_t * 59*57718be8SEnji Cooper init_mchain2(struct mbuf *mb1, struct mbuf *mb2, 60*57718be8SEnji Cooper unsigned char pkt[], size_t pktsize, size_t split) 61*57718be8SEnji Cooper { 62*57718be8SEnji Cooper 63*57718be8SEnji Cooper (void)memset(mb1, 0, sizeof(*mb1)); 64*57718be8SEnji Cooper mb1->m_data = (char *)pkt; 65*57718be8SEnji Cooper mb1->m_next = (split < pktsize) ? mb2 : NULL; 66*57718be8SEnji Cooper mb1->m_len = (split < pktsize) ? split : pktsize; 67*57718be8SEnji Cooper 68*57718be8SEnji Cooper if (split < pktsize) { 69*57718be8SEnji Cooper (void)memset(mb2, 0, sizeof(*mb2)); 70*57718be8SEnji Cooper mb2->m_next = NULL; 71*57718be8SEnji Cooper mb2->m_data = (char *)&pkt[split]; 72*57718be8SEnji Cooper mb2->m_len = pktsize - split; 73*57718be8SEnji Cooper } 74*57718be8SEnji Cooper 75*57718be8SEnji Cooper return (const uint8_t*)mb1; 76*57718be8SEnji Cooper } 77*57718be8SEnji Cooper 78*57718be8SEnji Cooper /* 79*57718be8SEnji Cooper * Compile and run a filter program. 80*57718be8SEnji Cooper */ 81*57718be8SEnji Cooper static inline unsigned int 82*57718be8SEnji Cooper exec_prog(struct bpf_insn *insns, size_t insn_count, 83*57718be8SEnji Cooper unsigned char pkt[], size_t pktsize) 84*57718be8SEnji Cooper { 85*57718be8SEnji Cooper bpfjit_func_t fn; 86*57718be8SEnji Cooper bpf_args_t args; 87*57718be8SEnji Cooper unsigned int res; 88*57718be8SEnji Cooper 89*57718be8SEnji Cooper args.pkt = (const uint8_t *)pkt; 90*57718be8SEnji Cooper args.buflen = pktsize; 91*57718be8SEnji Cooper args.wirelen = pktsize; 92*57718be8SEnji Cooper 93*57718be8SEnji Cooper rump_schedule(); 94*57718be8SEnji Cooper fn = rumpns_bpfjit_generate_code(NULL, insns, insn_count); 95*57718be8SEnji Cooper rump_unschedule(); 96*57718be8SEnji Cooper 97*57718be8SEnji Cooper res = fn(NULL, &args); 98*57718be8SEnji Cooper 99*57718be8SEnji Cooper rump_schedule(); 100*57718be8SEnji Cooper rumpns_bpfjit_free_code(fn); 101*57718be8SEnji Cooper rump_unschedule(); 102*57718be8SEnji Cooper 103*57718be8SEnji Cooper return res; 104*57718be8SEnji Cooper } 105*57718be8SEnji Cooper 106*57718be8SEnji Cooper /* 107*57718be8SEnji Cooper * Interpret a filter program with mbuf chain passed to bpf_filter_ext(). 108*57718be8SEnji Cooper */ 109*57718be8SEnji Cooper static inline unsigned int 110*57718be8SEnji Cooper interp_prog_mchain2(struct bpf_insn *insns, 111*57718be8SEnji Cooper unsigned char pkt[], size_t pktsize, size_t split) 112*57718be8SEnji Cooper { 113*57718be8SEnji Cooper uint32_t mem[BPF_MEMWORDS]; 114*57718be8SEnji Cooper struct mbuf mb1, mb2; 115*57718be8SEnji Cooper bpf_args_t args; 116*57718be8SEnji Cooper unsigned int res; 117*57718be8SEnji Cooper 118*57718be8SEnji Cooper args.pkt = init_mchain2(&mb1, &mb2, pkt, pktsize, split); 119*57718be8SEnji Cooper args.buflen = 0; 120*57718be8SEnji Cooper args.wirelen = pktsize; 121*57718be8SEnji Cooper args.mem = mem; 122*57718be8SEnji Cooper 123*57718be8SEnji Cooper rump_schedule(); 124*57718be8SEnji Cooper res = rumpns_bpf_filter_ext(NULL, insns, &args); 125*57718be8SEnji Cooper rump_unschedule(); 126*57718be8SEnji Cooper 127*57718be8SEnji Cooper return res; 128*57718be8SEnji Cooper } 129*57718be8SEnji Cooper 130*57718be8SEnji Cooper /* 131*57718be8SEnji Cooper * Compile and run a filter program with mbuf chain passed to compiled function. 132*57718be8SEnji Cooper */ 133*57718be8SEnji Cooper static inline unsigned int 134*57718be8SEnji Cooper exec_prog_mchain2(struct bpf_insn *insns, size_t insn_count, 135*57718be8SEnji Cooper unsigned char pkt[], size_t pktsize, size_t split) 136*57718be8SEnji Cooper { 137*57718be8SEnji Cooper bpfjit_func_t fn; 138*57718be8SEnji Cooper struct mbuf mb1, mb2; 139*57718be8SEnji Cooper bpf_args_t args; 140*57718be8SEnji Cooper unsigned int res; 141*57718be8SEnji Cooper 142*57718be8SEnji Cooper args.pkt = init_mchain2(&mb1, &mb2, pkt, pktsize, split); 143*57718be8SEnji Cooper args.buflen = 0; 144*57718be8SEnji Cooper args.wirelen = pktsize; 145*57718be8SEnji Cooper 146*57718be8SEnji Cooper rump_schedule(); 147*57718be8SEnji Cooper fn = rumpns_bpfjit_generate_code(NULL, insns, insn_count); 148*57718be8SEnji Cooper rump_unschedule(); 149*57718be8SEnji Cooper 150*57718be8SEnji Cooper res = fn(NULL, &args); 151*57718be8SEnji Cooper 152*57718be8SEnji Cooper rump_schedule(); 153*57718be8SEnji Cooper rumpns_bpfjit_free_code(fn); 154*57718be8SEnji Cooper rump_unschedule(); 155*57718be8SEnji Cooper 156*57718be8SEnji Cooper return res; 157*57718be8SEnji Cooper } 158*57718be8SEnji Cooper 159*57718be8SEnji Cooper static inline bool 160*57718be8SEnji Cooper prog_validate(struct bpf_insn *insns, size_t insn_count) 161*57718be8SEnji Cooper { 162*57718be8SEnji Cooper bool res; 163*57718be8SEnji Cooper 164*57718be8SEnji Cooper rump_schedule(); 165*57718be8SEnji Cooper res = rumpns_bpf_validate(insns, insn_count); 166*57718be8SEnji Cooper rump_unschedule(); 167*57718be8SEnji Cooper 168*57718be8SEnji Cooper return res; 169*57718be8SEnji Cooper } 170*57718be8SEnji Cooper 171*57718be8SEnji Cooper #endif /* _TESTS_NET_BPF_H_BPF_H_ */ 172