1 /* 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 */ 21 #if !(defined(lint) || defined(KERNEL)) 22 static char rcsid[] = 23 "@(#) $Header: bpf_filter.c,v 1.10 91/04/24 22:07:07 mccanne Locked $ (LBL)"; 24 #endif 25 26 #include <sys/param.h> 27 #include <sys/types.h> 28 #include <sys/time.h> 29 #include <net/bpf.h> 30 31 #if defined(sparc) || defined(mips) 32 #define ALIGN 33 #endif 34 35 #ifndef ALIGN 36 #define EXTRACT_SHORT(p) (ntohs(*(u_short *)p)) 37 #define EXTRACT_LONG(p) (ntohl(*(u_long *)p)) 38 #else 39 #define EXTRACT_SHORT(p)\ 40 ((u_short)\ 41 (*((u_char *)p+0)<<8|\ 42 *((u_char *)p+1)<<0)) 43 #define EXTRACT_LONG(p)\ 44 (*((u_char *)p+0)<<24|\ 45 *((u_char *)p+1)<<16|\ 46 *((u_char *)p+2)<<8|\ 47 *((u_char *)p+3)<<0) 48 #endif 49 50 #ifdef KERNEL 51 #include <sys/mbuf.h> 52 #define MINDEX(m, k) \ 53 { \ 54 register int len = m->m_len; \ 55 \ 56 while (k >= len) { \ 57 k -= len; \ 58 m = m->m_next; \ 59 if (m == 0) \ 60 return 0; \ 61 len = m->m_len; \ 62 } \ 63 } 64 #endif 65 66 /* 67 * Execute the filter program starting at pc on the packet p 68 * wirelen is the length of the original packet 69 * buflen is the amount of data present 70 */ 71 u_int 72 bpf_filter(pc, p, wirelen, buflen) 73 register struct bpf_insn *pc; 74 register u_char *p; 75 u_int wirelen; 76 register u_int buflen; 77 { 78 register long A, X; 79 register int k; 80 long mem[BPF_MEMWORDS]; 81 82 if (pc == 0) 83 /* 84 * No filter means accept all. 85 */ 86 return (u_int)-1; 87 #ifdef lint 88 A = 0; 89 X = 0; 90 #endif 91 --pc; 92 while (1) { 93 ++pc; 94 switch (pc->code) { 95 96 default: 97 #ifdef KERNEL 98 return 0; 99 #else 100 abort(); 101 #endif 102 case BPF_RET|BPF_K: 103 return (u_int)pc->k; 104 105 case BPF_RET|BPF_A: 106 return (u_int)A; 107 108 case BPF_LD|BPF_W|BPF_ABS: 109 k = pc->k; 110 if (k + sizeof(long) > buflen) { 111 #ifdef KERNEL 112 register struct mbuf *m; 113 114 if (buflen != 0) 115 return 0; 116 m = (struct mbuf *)p; 117 MINDEX(m, k); 118 A = EXTRACT_LONG(mtod(m, char *) + k); 119 break; 120 #else 121 return 0; 122 #endif 123 } 124 #ifdef ALIGN 125 if (((int)(p + k) & 3) != 0) 126 A = EXTRACT_LONG(&p[k]); 127 else 128 #endif 129 A = *(long *)(p + k); 130 break; 131 132 case BPF_LD|BPF_H|BPF_ABS: 133 k = pc->k; 134 if (k + sizeof(short) > buflen) { 135 #ifdef KERNEL 136 register struct mbuf *m; 137 138 if (buflen != 0) 139 return 0; 140 m = (struct mbuf *)p; 141 MINDEX(m, k); 142 A = EXTRACT_SHORT(mtod(m, char *) + k); 143 break; 144 #else 145 return 0; 146 #endif 147 } 148 A = EXTRACT_SHORT(&p[k]); 149 break; 150 151 case BPF_LD|BPF_B|BPF_ABS: 152 k = pc->k; 153 if (k >= buflen) { 154 #ifdef KERNEL 155 register struct mbuf *m; 156 157 if (buflen != 0) 158 return 0; 159 m = (struct mbuf *)p; 160 MINDEX(m, k); 161 A = mtod(m, char *)[k]; 162 break; 163 #else 164 return 0; 165 #endif 166 } 167 A = p[k]; 168 break; 169 170 case BPF_LD|BPF_W|BPF_LEN: 171 A = wirelen; 172 break; 173 174 case BPF_LDX|BPF_W|BPF_LEN: 175 X = wirelen; 176 break; 177 178 case BPF_LD|BPF_W|BPF_IND: 179 k = X + pc->k; 180 if (k + sizeof(long) > buflen) { 181 #ifdef KERNEL 182 register struct mbuf *m; 183 184 if (buflen != 0) 185 return 0; 186 m = (struct mbuf *)p; 187 MINDEX(m, k); 188 A = EXTRACT_LONG(mtod(m, char *) + k); 189 break; 190 #else 191 return 0; 192 #endif 193 } 194 #ifdef ALIGN 195 if (((int)(p + k) & 3) != 0) 196 A = EXTRACT_LONG(&p[k]); 197 else 198 #endif 199 A = *(long *)(p + k); 200 break; 201 202 case BPF_LD|BPF_H|BPF_IND: 203 k = X + pc->k; 204 if (k + sizeof(short) > buflen) { 205 #ifdef KERNEL 206 register struct mbuf *m; 207 208 if (buflen != 0) 209 return 0; 210 m = (struct mbuf *)p; 211 MINDEX(m, k); 212 A = EXTRACT_SHORT(mtod(m, char *) + k); 213 break; 214 #else 215 return 0; 216 #endif 217 } 218 A = EXTRACT_SHORT(&p[k]); 219 break; 220 221 case BPF_LD|BPF_B|BPF_IND: 222 k = X + pc->k; 223 if (k >= buflen) { 224 #ifdef KERNEL 225 register struct mbuf *m; 226 227 if (buflen != 0) 228 return 0; 229 m = (struct mbuf *)p; 230 MINDEX(m, k); 231 A = mtod(m, char *)[k]; 232 break; 233 #else 234 return 0; 235 #endif 236 } 237 A = p[k]; 238 break; 239 240 case BPF_LDX|BPF_MSH|BPF_B: 241 k = pc->k; 242 if (k >= buflen) { 243 #ifdef KERNEL 244 register struct mbuf *m; 245 246 if (buflen != 0) 247 return 0; 248 m = (struct mbuf *)p; 249 MINDEX(m, k); 250 X = (mtod(m, char *)[k] & 0xf) << 2; 251 break; 252 #else 253 return 0; 254 #endif 255 } 256 X = (p[pc->k] & 0xf) << 2; 257 break; 258 259 case BPF_LD|BPF_IMM: 260 A = pc->k; 261 break; 262 263 case BPF_LDX|BPF_IMM: 264 X = pc->k; 265 break; 266 267 case BPF_LD|BPF_MEM: 268 A = mem[pc->k]; 269 break; 270 271 case BPF_LDX|BPF_MEM: 272 X = mem[pc->k]; 273 break; 274 275 case BPF_ST: 276 mem[pc->k] = A; 277 break; 278 279 case BPF_STX: 280 mem[pc->k] = X; 281 break; 282 283 case BPF_JMP|BPF_JA: 284 pc += pc->k; 285 break; 286 287 case BPF_JMP|BPF_JGT|BPF_K: 288 pc += (A > pc->k) ? pc->jt : pc->jf; 289 break; 290 291 case BPF_JMP|BPF_JGE|BPF_K: 292 pc += (A >= pc->k) ? pc->jt : pc->jf; 293 break; 294 295 case BPF_JMP|BPF_JEQ|BPF_K: 296 pc += (A == pc->k) ? pc->jt : pc->jf; 297 break; 298 299 case BPF_JMP|BPF_JSET|BPF_K: 300 pc += (A & pc->k) ? pc->jt : pc->jf; 301 break; 302 303 case BPF_JMP|BPF_JGT|BPF_X: 304 pc += (A > X) ? pc->jt : pc->jf; 305 break; 306 307 case BPF_JMP|BPF_JGE|BPF_X: 308 pc += (A >= X) ? pc->jt : pc->jf; 309 break; 310 311 case BPF_JMP|BPF_JEQ|BPF_X: 312 pc += (A == X) ? pc->jt : pc->jf; 313 break; 314 315 case BPF_JMP|BPF_JSET|BPF_X: 316 pc += (A & X) ? pc->jt : pc->jf; 317 break; 318 319 case BPF_ALU|BPF_ADD|BPF_X: 320 A += X; 321 break; 322 323 case BPF_ALU|BPF_SUB|BPF_X: 324 A -= X; 325 break; 326 327 case BPF_ALU|BPF_MUL|BPF_X: 328 A *= X; 329 break; 330 331 case BPF_ALU|BPF_DIV|BPF_X: 332 if (X == 0) 333 return 0; 334 A /= X; 335 break; 336 337 case BPF_ALU|BPF_AND|BPF_X: 338 A &= X; 339 break; 340 341 case BPF_ALU|BPF_OR|BPF_X: 342 A |= X; 343 break; 344 345 case BPF_ALU|BPF_LSH|BPF_X: 346 A <<= X; 347 break; 348 349 case BPF_ALU|BPF_RSH|BPF_X: 350 A >>= X; 351 break; 352 353 case BPF_ALU|BPF_ADD|BPF_K: 354 A += pc->k; 355 break; 356 357 case BPF_ALU|BPF_SUB|BPF_K: 358 A -= pc->k; 359 break; 360 361 case BPF_ALU|BPF_MUL|BPF_K: 362 A *= pc->k; 363 break; 364 365 case BPF_ALU|BPF_DIV|BPF_K: 366 A /= pc->k; 367 break; 368 369 case BPF_ALU|BPF_AND|BPF_K: 370 A &= pc->k; 371 break; 372 373 case BPF_ALU|BPF_OR|BPF_K: 374 A |= pc->k; 375 break; 376 377 case BPF_ALU|BPF_LSH|BPF_K: 378 A <<= pc->k; 379 break; 380 381 case BPF_ALU|BPF_RSH|BPF_K: 382 A >>= pc->k; 383 break; 384 385 case BPF_ALU|BPF_NEG: 386 A = -A; 387 break; 388 389 case BPF_MISC|BPF_TAX: 390 X = A; 391 break; 392 393 case BPF_MISC|BPF_TXA: 394 A = X; 395 break; 396 } 397 } 398 } 399 400 #ifdef KERNEL 401 /* 402 * Return true if the 'fcode' is a valid filter program. 403 * The constraints are that each jump be forward and to a valid 404 * code. The code must terminate with either an accept or reject. 405 * 'valid' is an array for use by the routine (it must be at least 406 * 'len' bytes long). 407 * 408 * The kernel needs to be able to verify an application's filter code. 409 * Otherwise, a bogus program could easily crash the system. 410 */ 411 int 412 bpf_validate(f, len) 413 struct bpf_insn *f; 414 int len; 415 { 416 register int i; 417 register struct bpf_insn *p; 418 419 for (i = 0; i < len; ++i) { 420 /* 421 * Check that that jumps are forward, and within 422 * the code block. 423 */ 424 p = &f[i]; 425 if (BPF_CLASS(p->code) == BPF_JMP) { 426 register int from = i + 1; 427 428 if (BPF_OP(p->code) == BPF_JA) { 429 if (from + p->k >= len) 430 return 0; 431 } 432 else if (from + p->jt >= len || from + p->jf >= len) 433 return 0; 434 } 435 /* 436 * Check that memory operations use valid addresses. 437 */ 438 if ((BPF_CLASS(p->code) == BPF_ST || 439 (BPF_CLASS(p->code) == BPF_LD && 440 (p->code & 0xe0) == BPF_MEM)) && 441 (p->k >= BPF_MEMWORDS || p->k < 0)) 442 return 0; 443 /* 444 * Check for constant division by 0. 445 */ 446 if (p->code == BPF_ALU|BPF_DIV|BPF_K && p->k == 0) 447 return; 448 } 449 return BPF_CLASS(f[len - 1].code) == BPF_RET; 450 } 451 #endif 452