1 /*- 2 * Copyright (C) 2008-2009 Jung-uk Kim <jkim@FreeBSD.org>. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 #include <sys/cdefs.h> 27 #include <signal.h> 28 #include <stdio.h> 29 #include <stdlib.h> 30 31 #include <sys/types.h> 32 33 #include <net/bpf.h> 34 35 #include BPF_TEST_H 36 37 #define PASSED 0 38 #define FAILED 1 39 #define FATAL -1 40 41 #ifndef LOG_LEVEL 42 #define LOG_LEVEL 1 43 #endif 44 45 #ifdef BPF_BENCHMARK 46 #define BPF_NRUNS 10000000 47 #else 48 #define BPF_NRUNS 1 49 #endif 50 51 static void sig_handler(int); 52 53 static int nins = sizeof(pc) / sizeof(pc[0]); 54 static int verbose = LOG_LEVEL; 55 56 #ifdef BPF_JIT_COMPILER 57 58 #include <libutil.h> 59 60 #include <net/bpf_jitter.h> 61 62 static u_int 63 bpf_compile_and_filter(void) 64 { 65 bpf_jit_filter *filter; 66 u_int i, ret; 67 68 /* Compile the BPF filter program and generate native code. */ 69 if ((filter = bpf_jitter(pc, nins)) == NULL) { 70 if (verbose > 1) 71 printf("Failed to allocate memory:\t"); 72 if (verbose > 0) 73 printf("FATAL\n"); 74 exit(FATAL); 75 } 76 if (verbose > 2) { 77 printf("\n"); 78 hexdump(filter->func, filter->size, NULL, HD_OMIT_CHARS); 79 } 80 81 for (i = 0; i < BPF_NRUNS; i++) 82 ret = (*(filter->func))(pkt, wirelen, buflen); 83 84 bpf_destroy_jit_filter(filter); 85 86 return (ret); 87 } 88 89 #else 90 91 u_int bpf_filter(const struct bpf_insn *, u_char *, u_int, u_int); 92 93 #endif 94 95 #ifdef BPF_VALIDATE 96 static const u_short bpf_code_map[] = { 97 0x10ff, /* 0x00-0x0f: 1111111100001000 */ 98 0x3070, /* 0x10-0x1f: 0000111000001100 */ 99 0x3131, /* 0x20-0x2f: 1000110010001100 */ 100 0x3031, /* 0x30-0x3f: 1000110000001100 */ 101 0x3131, /* 0x40-0x4f: 1000110010001100 */ 102 0x1011, /* 0x50-0x5f: 1000100000001000 */ 103 0x1013, /* 0x60-0x6f: 1100100000001000 */ 104 0x1010, /* 0x70-0x7f: 0000100000001000 */ 105 0x0093, /* 0x80-0x8f: 1100100100000000 */ 106 0x1010, /* 0x90-0x9f: 0000100000001000 */ 107 0x1010, /* 0xa0-0xaf: 0000100000001000 */ 108 0x0002, /* 0xb0-0xbf: 0100000000000000 */ 109 0x0000, /* 0xc0-0xcf: 0000000000000000 */ 110 0x0000, /* 0xd0-0xdf: 0000000000000000 */ 111 0x0000, /* 0xe0-0xef: 0000000000000000 */ 112 0x0000 /* 0xf0-0xff: 0000000000000000 */ 113 }; 114 115 #define BPF_VALIDATE_CODE(c) \ 116 ((c) <= 0xff && (bpf_code_map[(c) >> 4] & (1 << ((c) & 0xf))) != 0) 117 118 /* 119 * XXX Copied from sys/net/bpf_filter.c and modified. 120 * 121 * Return true if the 'fcode' is a valid filter program. 122 * The constraints are that each jump be forward and to a valid 123 * code. The code must terminate with either an accept or reject. 124 * 125 * The kernel needs to be able to verify an application's filter code. 126 * Otherwise, a bogus program could easily crash the system. 127 */ 128 static int 129 bpf_validate(const struct bpf_insn *f, int len) 130 { 131 register int i; 132 register const struct bpf_insn *p; 133 134 /* Do not accept negative length filter. */ 135 if (len < 0) 136 return (0); 137 138 /* An empty filter means accept all. */ 139 if (len == 0) 140 return (1); 141 142 for (i = 0; i < len; ++i) { 143 p = &f[i]; 144 /* 145 * Check that the code is valid. 146 */ 147 if (!BPF_VALIDATE_CODE(p->code)) 148 return (0); 149 /* 150 * Check that jumps are forward, and within 151 * the code block. 152 */ 153 if (BPF_CLASS(p->code) == BPF_JMP) { 154 register u_int offset; 155 156 if (p->code == (BPF_JMP|BPF_JA)) 157 offset = p->k; 158 else 159 offset = p->jt > p->jf ? p->jt : p->jf; 160 if (offset >= (u_int)(len - i) - 1) 161 return (0); 162 continue; 163 } 164 /* 165 * Check that memory operations use valid addresses. 166 */ 167 if (p->code == BPF_ST || p->code == BPF_STX || 168 p->code == (BPF_LD|BPF_MEM) || 169 p->code == (BPF_LDX|BPF_MEM)) { 170 if (p->k >= BPF_MEMWORDS) 171 return (0); 172 continue; 173 } 174 /* 175 * Check for constant division by 0. 176 */ 177 if ((p->code == (BPF_ALU|BPF_DIV|BPF_K) || 178 p->code == (BPF_ALU|BPF_MOD|BPF_K)) && p->k == 0) 179 return (0); 180 } 181 return (BPF_CLASS(f[len - 1].code) == BPF_RET); 182 } 183 #endif 184 185 int 186 main(void) 187 { 188 #ifndef BPF_JIT_COMPILER 189 u_int i; 190 #endif 191 u_int ret; 192 int sig; 193 #ifdef BPF_VALIDATE 194 int valid; 195 #endif 196 197 /* Try to catch all signals */ 198 for (sig = SIGHUP; sig <= SIGUSR2; sig++) 199 signal(sig, sig_handler); 200 201 #ifdef BPF_VALIDATE 202 valid = bpf_validate(pc, nins); 203 if (valid != 0 && invalid != 0) { 204 if (verbose > 1) 205 printf("Validated invalid instruction(s):\t"); 206 if (verbose > 0) 207 printf("FAILED\n"); 208 return (FAILED); 209 } else if (valid == 0 && invalid == 0) { 210 if (verbose > 1) 211 printf("Invalidated valid instruction(s):\t"); 212 if (verbose > 0) 213 printf("FAILED\n"); 214 return (FAILED); 215 } else if (invalid != 0) { 216 if (verbose > 1) 217 printf("Expected and invalidated:\t"); 218 if (verbose > 0) 219 printf("PASSED\n"); 220 return (PASSED); 221 } 222 #endif 223 224 #ifdef BPF_JIT_COMPILER 225 ret = bpf_compile_and_filter(); 226 #else 227 for (i = 0; i < BPF_NRUNS; i++) 228 ret = bpf_filter(nins != 0 ? pc : NULL, pkt, wirelen, buflen); 229 #endif 230 if (expect_signal != 0) { 231 if (verbose > 1) 232 printf("Expected signal %d but got none:\t", 233 expect_signal); 234 if (verbose > 0) 235 printf("FAILED\n"); 236 return (FAILED); 237 } 238 if (ret != expect) { 239 if (verbose > 1) 240 printf("Expected 0x%x but got 0x%x:\t", expect, ret); 241 if (verbose > 0) 242 printf("FAILED\n"); 243 return (FAILED); 244 } 245 if (verbose > 1) 246 printf("Expected and got 0x%x:\t", ret); 247 if (verbose > 0) 248 printf("PASSED\n"); 249 250 return (PASSED); 251 } 252 253 static void 254 sig_handler(int sig) 255 { 256 257 if (expect_signal == 0) { 258 if (verbose > 1) 259 printf("Received unexpected signal %d:\t", sig); 260 if (verbose > 0) 261 printf("FATAL\n"); 262 exit(FATAL); 263 } 264 if (expect_signal != sig) { 265 if (verbose > 1) 266 printf("Expected signal %d but got %d:\t", 267 expect_signal, sig); 268 if (verbose > 0) 269 printf("FAILED\n"); 270 exit(FAILED); 271 } 272 273 if (verbose > 1) 274 printf("Expected and got signal %d:\t", sig); 275 if (verbose > 0) 276 printf("PASSED\n"); 277 278 exit(PASSED); 279 } 280