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