1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from the Stanford/CMU enet packet filter, 6 * (net/enet.c) distributed as part of 4.3BSD, and code contributed 7 * to Berkeley by Steven McCanne of Lawrence Berkeley Laboratory. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)bpf_filter.c 7.2 (Berkeley) 05/14/91 12 * 13 * static char rcsid[] = 14 * "@(#) $Header: bpf_filter.c,v 1.10 91/04/24 22:07:07 mccanne Locked $ (LBL)"; 15 */ 16 17 #include <sys/param.h> 18 #include <sys/types.h> 19 #include <sys/time.h> 20 #include <net/bpf.h> 21 22 #ifdef sun 23 #include <netinet/in.h> 24 #endif 25 26 #if defined(sparc) || defined(mips) 27 #define ALIGN 28 #endif 29 30 #ifndef ALIGN 31 #define EXTRACT_SHORT(p) (ntohs(*(u_short *)p)) 32 #define EXTRACT_LONG(p) (ntohl(*(u_long *)p)) 33 #else 34 #define EXTRACT_SHORT(p)\ 35 ((u_short)\ 36 (*((u_char *)(p)+0)<<8|\ 37 *((u_char *)(p)+1)<<0)) 38 #define EXTRACT_LONG(p)\ 39 (*((u_char *)(p)+0)<<24|\ 40 *((u_char *)(p)+1)<<16|\ 41 *((u_char *)(p)+2)<<8|\ 42 *((u_char *)(p)+3)<<0) 43 #endif 44 45 #ifdef KERNEL 46 #include <sys/mbuf.h> 47 #define MINDEX(m, k) \ 48 { \ 49 register int len = m->m_len; \ 50 \ 51 while (k >= len) { \ 52 k -= len; \ 53 m = m->m_next; \ 54 if (m == 0) \ 55 return 0; \ 56 len = m->m_len; \ 57 } \ 58 } 59 60 static int 61 m_xword(m, k, err) 62 register struct mbuf *m; 63 register int k, *err; 64 { 65 register int len; 66 register u_char *cp, *np; 67 register struct mbuf *m0; 68 69 len = m->m_len; 70 while (k >= len) { 71 k -= len; 72 m = m->m_next; 73 if (m == 0) 74 goto bad; 75 len = m->m_len; 76 } 77 cp = mtod(m, u_char *) + k; 78 if (len - k >= 4) { 79 *err = 0; 80 return EXTRACT_LONG(cp); 81 } 82 m0 = m->m_next; 83 if (m0 == 0 || m0->m_len + len - k < 4) 84 goto bad; 85 *err = 0; 86 np = mtod(m0, u_char *); 87 switch (len - k) { 88 89 case 1: 90 return (cp[k] << 24) | (np[0] << 16) | (np[1] << 8) | np[2]; 91 92 case 2: 93 return (cp[k] << 24) | (cp[k + 1] << 16) | (np[0] << 8) | 94 np[1]; 95 96 default: 97 return (cp[k] << 24) | (cp[k + 1] << 16) | (cp[k + 2] << 8) | 98 np[0]; 99 } 100 bad: 101 *err = 1; 102 return 0; 103 } 104 105 static int 106 m_xhalf(m, k, err) 107 register struct mbuf *m; 108 register int k, *err; 109 { 110 register int len; 111 register u_char *cp, *np; 112 register struct mbuf *m0; 113 114 len = m->m_len; 115 while (k >= len) { 116 k -= len; 117 m = m->m_next; 118 if (m == 0) 119 goto bad; 120 len = m->m_len; 121 } 122 cp = mtod(m, u_char *) + k; 123 if (len - k >= 2) { 124 *err = 0; 125 return EXTRACT_SHORT(cp); 126 } 127 m0 = m->m_next; 128 if (m0 == 0) 129 goto bad; 130 *err = 0; 131 return (cp[k] << 8) | mtod(m0, u_char *)[0]; 132 bad: 133 *err = 1; 134 return 0; 135 } 136 137 138 #endif 139 140 /* 141 * Execute the filter program starting at pc on the packet p 142 * wirelen is the length of the original packet 143 * buflen is the amount of data present 144 */ 145 u_int 146 bpf_filter(pc, p, wirelen, buflen) 147 register struct bpf_insn *pc; 148 register u_char *p; 149 u_int wirelen; 150 register u_int buflen; 151 { 152 register long A, X; 153 register int k; 154 long mem[BPF_MEMWORDS]; 155 156 if (pc == 0) 157 /* 158 * No filter means accept all. 159 */ 160 return (u_int)-1; 161 #ifdef lint 162 A = 0; 163 X = 0; 164 #endif 165 --pc; 166 while (1) { 167 ++pc; 168 switch (pc->code) { 169 170 default: 171 #ifdef KERNEL 172 return 0; 173 #else 174 abort(); 175 #endif 176 case BPF_RET|BPF_K: 177 return (u_int)pc->k; 178 179 case BPF_RET|BPF_A: 180 return (u_int)A; 181 182 case BPF_LD|BPF_W|BPF_ABS: 183 k = pc->k; 184 if (k + sizeof(long) > buflen) { 185 #ifdef KERNEL 186 int merr; 187 188 if (buflen != 0) 189 return 0; 190 A = m_xword((struct mbuf *)p, k, &merr); 191 if (merr != 0) 192 return 0; 193 continue; 194 #else 195 return 0; 196 #endif 197 } 198 #ifdef ALIGN 199 if (((int)(p + k) & 3) != 0) 200 A = EXTRACT_LONG(&p[k]); 201 else 202 #endif 203 A = *(long *)(p + k); 204 continue; 205 206 case BPF_LD|BPF_H|BPF_ABS: 207 k = pc->k; 208 if (k + sizeof(short) > buflen) { 209 #ifdef KERNEL 210 int merr; 211 212 if (buflen != 0) 213 return 0; 214 A = m_xhalf((struct mbuf *)p, k, &merr); 215 continue; 216 #else 217 return 0; 218 #endif 219 } 220 A = EXTRACT_SHORT(&p[k]); 221 continue; 222 223 case BPF_LD|BPF_B|BPF_ABS: 224 k = pc->k; 225 if (k >= buflen) { 226 #ifdef KERNEL 227 register struct mbuf *m; 228 229 if (buflen != 0) 230 return 0; 231 m = (struct mbuf *)p; 232 MINDEX(m, k); 233 A = mtod(m, u_char *)[k]; 234 continue; 235 #else 236 return 0; 237 #endif 238 } 239 A = p[k]; 240 continue; 241 242 case BPF_LD|BPF_W|BPF_LEN: 243 A = wirelen; 244 continue; 245 246 case BPF_LDX|BPF_W|BPF_LEN: 247 X = wirelen; 248 continue; 249 250 case BPF_LD|BPF_W|BPF_IND: 251 k = X + pc->k; 252 if (k + sizeof(long) > buflen) { 253 #ifdef KERNEL 254 int merr; 255 256 if (buflen != 0) 257 return 0; 258 A = m_xword((struct mbuf *)p, k, &merr); 259 if (merr != 0) 260 return 0; 261 continue; 262 #else 263 return 0; 264 #endif 265 } 266 #ifdef ALIGN 267 if (((int)(p + k) & 3) != 0) 268 A = EXTRACT_LONG(&p[k]); 269 else 270 #endif 271 A = *(long *)(p + k); 272 continue; 273 274 case BPF_LD|BPF_H|BPF_IND: 275 k = X + pc->k; 276 if (k + sizeof(short) > buflen) { 277 #ifdef KERNEL 278 int merr; 279 280 if (buflen != 0) 281 return 0; 282 A = m_xhalf((struct mbuf *)p, k, &merr); 283 if (merr != 0) 284 return 0; 285 continue; 286 #else 287 return 0; 288 #endif 289 } 290 A = EXTRACT_SHORT(&p[k]); 291 continue; 292 293 case BPF_LD|BPF_B|BPF_IND: 294 k = X + pc->k; 295 if (k >= buflen) { 296 #ifdef KERNEL 297 register struct mbuf *m; 298 299 if (buflen != 0) 300 return 0; 301 m = (struct mbuf *)p; 302 MINDEX(m, k); 303 A = mtod(m, char *)[k]; 304 continue; 305 #else 306 return 0; 307 #endif 308 } 309 A = p[k]; 310 continue; 311 312 case BPF_LDX|BPF_MSH|BPF_B: 313 k = pc->k; 314 if (k >= buflen) { 315 #ifdef KERNEL 316 register struct mbuf *m; 317 318 if (buflen != 0) 319 return 0; 320 m = (struct mbuf *)p; 321 MINDEX(m, k); 322 X = (mtod(m, char *)[k] & 0xf) << 2; 323 continue; 324 #else 325 return 0; 326 #endif 327 } 328 X = (p[pc->k] & 0xf) << 2; 329 continue; 330 331 case BPF_LD|BPF_IMM: 332 A = pc->k; 333 continue; 334 335 case BPF_LDX|BPF_IMM: 336 X = pc->k; 337 continue; 338 339 case BPF_LD|BPF_MEM: 340 A = mem[pc->k]; 341 continue; 342 343 case BPF_LDX|BPF_MEM: 344 X = mem[pc->k]; 345 continue; 346 347 case BPF_ST: 348 mem[pc->k] = A; 349 continue; 350 351 case BPF_STX: 352 mem[pc->k] = X; 353 continue; 354 355 case BPF_JMP|BPF_JA: 356 pc += pc->k; 357 continue; 358 359 case BPF_JMP|BPF_JGT|BPF_K: 360 pc += (A > pc->k) ? pc->jt : pc->jf; 361 continue; 362 363 case BPF_JMP|BPF_JGE|BPF_K: 364 pc += (A >= pc->k) ? pc->jt : pc->jf; 365 continue; 366 367 case BPF_JMP|BPF_JEQ|BPF_K: 368 pc += (A == pc->k) ? pc->jt : pc->jf; 369 continue; 370 371 case BPF_JMP|BPF_JSET|BPF_K: 372 pc += (A & pc->k) ? pc->jt : pc->jf; 373 continue; 374 375 case BPF_JMP|BPF_JGT|BPF_X: 376 pc += (A > X) ? pc->jt : pc->jf; 377 continue; 378 379 case BPF_JMP|BPF_JGE|BPF_X: 380 pc += (A >= X) ? pc->jt : pc->jf; 381 continue; 382 383 case BPF_JMP|BPF_JEQ|BPF_X: 384 pc += (A == X) ? pc->jt : pc->jf; 385 continue; 386 387 case BPF_JMP|BPF_JSET|BPF_X: 388 pc += (A & X) ? pc->jt : pc->jf; 389 continue; 390 391 case BPF_ALU|BPF_ADD|BPF_X: 392 A += X; 393 continue; 394 395 case BPF_ALU|BPF_SUB|BPF_X: 396 A -= X; 397 continue; 398 399 case BPF_ALU|BPF_MUL|BPF_X: 400 A *= X; 401 continue; 402 403 case BPF_ALU|BPF_DIV|BPF_X: 404 if (X == 0) 405 return 0; 406 A /= X; 407 continue; 408 409 case BPF_ALU|BPF_AND|BPF_X: 410 A &= X; 411 continue; 412 413 case BPF_ALU|BPF_OR|BPF_X: 414 A |= X; 415 continue; 416 417 case BPF_ALU|BPF_LSH|BPF_X: 418 A <<= X; 419 continue; 420 421 case BPF_ALU|BPF_RSH|BPF_X: 422 A >>= X; 423 continue; 424 425 case BPF_ALU|BPF_ADD|BPF_K: 426 A += pc->k; 427 continue; 428 429 case BPF_ALU|BPF_SUB|BPF_K: 430 A -= pc->k; 431 continue; 432 433 case BPF_ALU|BPF_MUL|BPF_K: 434 A *= pc->k; 435 continue; 436 437 case BPF_ALU|BPF_DIV|BPF_K: 438 A /= pc->k; 439 continue; 440 441 case BPF_ALU|BPF_AND|BPF_K: 442 A &= pc->k; 443 continue; 444 445 case BPF_ALU|BPF_OR|BPF_K: 446 A |= pc->k; 447 continue; 448 449 case BPF_ALU|BPF_LSH|BPF_K: 450 A <<= pc->k; 451 continue; 452 453 case BPF_ALU|BPF_RSH|BPF_K: 454 A >>= pc->k; 455 continue; 456 457 case BPF_ALU|BPF_NEG: 458 A = -A; 459 continue; 460 461 case BPF_MISC|BPF_TAX: 462 X = A; 463 continue; 464 465 case BPF_MISC|BPF_TXA: 466 A = X; 467 continue; 468 } 469 } 470 } 471 472 #ifdef KERNEL 473 /* 474 * Return true if the 'fcode' is a valid filter program. 475 * The constraints are that each jump be forward and to a valid 476 * code. The code must terminate with either an accept or reject. 477 * 'valid' is an array for use by the routine (it must be at least 478 * 'len' bytes long). 479 * 480 * The kernel needs to be able to verify an application's filter code. 481 * Otherwise, a bogus program could easily crash the system. 482 */ 483 int 484 bpf_validate(f, len) 485 struct bpf_insn *f; 486 int len; 487 { 488 register int i; 489 register struct bpf_insn *p; 490 491 for (i = 0; i < len; ++i) { 492 /* 493 * Check that that jumps are forward, and within 494 * the code block. 495 */ 496 p = &f[i]; 497 if (BPF_CLASS(p->code) == BPF_JMP) { 498 register int from = i + 1; 499 500 if (BPF_OP(p->code) == BPF_JA) { 501 if (from + p->k >= len) 502 return 0; 503 } 504 else if (from + p->jt >= len || from + p->jf >= len) 505 return 0; 506 } 507 /* 508 * Check that memory operations use valid addresses. 509 */ 510 if ((BPF_CLASS(p->code) == BPF_ST || 511 (BPF_CLASS(p->code) == BPF_LD && 512 (p->code & 0xe0) == BPF_MEM)) && 513 (p->k >= BPF_MEMWORDS || p->k < 0)) 514 return 0; 515 /* 516 * Check for constant division by 0. 517 */ 518 if (p->code == BPF_ALU|BPF_DIV|BPF_K && p->k == 0) 519 return; 520 } 521 return BPF_CLASS(f[len - 1].code) == BPF_RET; 522 } 523 #endif 524