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