00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #if !(defined(lint) || defined(KERNEL) || defined(_KERNEL))
00042 static const char rcsid[] =
00043 "@(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf_filter.c,v 1.35 2000/10/23 19:32:21 fenner Exp $ (LBL)";
00044 #endif
00045
00046 #include <sys/param.h>
00047 #include <sys/types.h>
00048 #include <sys/time.h>
00049
00050 #define SOLARIS (defined(sun) && (defined(__SVR4) || defined(__svr4__)))
00051 #if defined(__hpux) || SOLARIS
00052 # include <sys/sysmacros.h>
00053 # include <sys/stream.h>
00054 # define mbuf msgb
00055 # define m_next b_cont
00056 # define MLEN(m) ((m)->b_wptr - (m)->b_rptr)
00057 # define mtod(m,t) ((t)(m)->b_rptr)
00058 #else
00059 # define MLEN(m) ((m)->m_len)
00060 #endif
00061
00062 #include <net/bpf.h>
00063
00064 #if !defined(KERNEL) && !defined(_KERNEL)
00065 #include <stdlib.h>
00066 #endif
00067
00068 #define int32 bpf_int32
00069 #define u_int32 bpf_u_int32
00070
00071 #ifndef LBL_ALIGN
00072 #if defined(sparc) || defined(mips) || defined(ibm032) || \
00073 defined(__alpha) || defined(__hpux)
00074 #define LBL_ALIGN
00075 #endif
00076 #endif
00077
00078 #ifndef LBL_ALIGN
00079 #include <netinet/in.h>
00080
00081 #define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p))
00082 #define EXTRACT_LONG(p) (ntohl(*(u_int32 *)p))
00083 #else
00084 #define EXTRACT_SHORT(p)\
00085 ((u_short)\
00086 ((u_short)*((u_char *)p+0)<<8|\
00087 (u_short)*((u_char *)p+1)<<0))
00088 #define EXTRACT_LONG(p)\
00089 ((u_int32)*((u_char *)p+0)<<24|\
00090 (u_int32)*((u_char *)p+1)<<16|\
00091 (u_int32)*((u_char *)p+2)<<8|\
00092 (u_int32)*((u_char *)p+3)<<0)
00093 #endif
00094
00095 #if defined(KERNEL) || defined(_KERNEL)
00096 # if !defined(__hpux) && !SOLARIS
00097 #include <sys/mbuf.h>
00098 # endif
00099 #define MINDEX(len, _m, _k) \
00100 { \
00101 len = MLEN(m); \
00102 while ((_k) >= len) { \
00103 (_k) -= len; \
00104 (_m) = (_m)->m_next; \
00105 if ((_m) == 0) \
00106 return 0; \
00107 len = MLEN(m); \
00108 } \
00109 }
00110
00111 static int
00112 m_xword(m, k, err)
00113 register struct mbuf *m;
00114 register int k, *err;
00115 {
00116 register int len;
00117 register u_char *cp, *np;
00118 register struct mbuf *m0;
00119
00120 MINDEX(len, m, k);
00121 cp = mtod(m, u_char *) + k;
00122 if (len - k >= 4) {
00123 *err = 0;
00124 return EXTRACT_LONG(cp);
00125 }
00126 m0 = m->m_next;
00127 if (m0 == 0 || MLEN(m0) + len - k < 4)
00128 goto bad;
00129 *err = 0;
00130 np = mtod(m0, u_char *);
00131 switch (len - k) {
00132
00133 case 1:
00134 return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
00135
00136 case 2:
00137 return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1];
00138
00139 default:
00140 return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0];
00141 }
00142 bad:
00143 *err = 1;
00144 return 0;
00145 }
00146
00147 static int
00148 m_xhalf(m, k, err)
00149 register struct mbuf *m;
00150 register int k, *err;
00151 {
00152 register int len;
00153 register u_char *cp;
00154 register struct mbuf *m0;
00155
00156 MINDEX(len, m, k);
00157 cp = mtod(m, u_char *) + k;
00158 if (len - k >= 2) {
00159 *err = 0;
00160 return EXTRACT_SHORT(cp);
00161 }
00162 m0 = m->m_next;
00163 if (m0 == 0)
00164 goto bad;
00165 *err = 0;
00166 return (cp[0] << 8) | mtod(m0, u_char *)[0];
00167 bad:
00168 *err = 1;
00169 return 0;
00170 }
00171 #endif
00172
00173
00174
00175
00176
00177
00178
00179
00180 u_int
00181 bpf_filter(pc, p, wirelen, buflen)
00182 register struct bpf_insn *pc;
00183 register u_char *p;
00184 u_int wirelen;
00185 register u_int buflen;
00186 {
00187 register u_int32 A, X;
00188 register int k;
00189 int32 mem[BPF_MEMWORDS];
00190 #if defined(KERNEL) || defined(_KERNEL)
00191 struct mbuf *m, *n;
00192 int merr, len;
00193
00194 if (buflen == 0) {
00195 m = (struct mbuf *)p;
00196 p = mtod(m, u_char *);
00197 buflen = MLEN(m);
00198 } else
00199 m = NULL;
00200 #endif
00201
00202 if (pc == 0)
00203
00204
00205
00206 return (u_int)-1;
00207 A = 0;
00208 X = 0;
00209 --pc;
00210 while (1) {
00211 ++pc;
00212 switch (pc->code) {
00213
00214 default:
00215 #if defined(KERNEL) || defined(_KERNEL)
00216 return 0;
00217 #else
00218 abort();
00219 #endif
00220 case BPF_RET|BPF_K:
00221 return (u_int)pc->k;
00222
00223 case BPF_RET|BPF_A:
00224 return (u_int)A;
00225
00226 case BPF_LD|BPF_W|BPF_ABS:
00227 k = pc->k;
00228 if (k + sizeof(int32) > buflen) {
00229 #if defined(KERNEL) || defined(_KERNEL)
00230 if (m == NULL)
00231 return 0;
00232 A = m_xword(m, k, &merr);
00233 if (merr != 0)
00234 return 0;
00235 continue;
00236 #else
00237 return 0;
00238 #endif
00239 }
00240 A = EXTRACT_LONG(&p[k]);
00241 continue;
00242
00243 case BPF_LD|BPF_H|BPF_ABS:
00244 k = pc->k;
00245 if (k + sizeof(short) > buflen) {
00246 #if defined(KERNEL) || defined(_KERNEL)
00247 if (m == NULL)
00248 return 0;
00249 A = m_xhalf(m, k, &merr);
00250 if (merr != 0)
00251 return 0;
00252 continue;
00253 #else
00254 return 0;
00255 #endif
00256 }
00257 A = EXTRACT_SHORT(&p[k]);
00258 continue;
00259
00260 case BPF_LD|BPF_B|BPF_ABS:
00261 k = pc->k;
00262 if (k >= buflen) {
00263 #if defined(KERNEL) || defined(_KERNEL)
00264 if (m == NULL)
00265 return 0;
00266 n = m;
00267 MINDEX(len, n, k);
00268 A = mtod(n, u_char *)[k];
00269 continue;
00270 #else
00271 return 0;
00272 #endif
00273 }
00274 A = p[k];
00275 continue;
00276
00277 case BPF_LD|BPF_W|BPF_LEN:
00278 A = wirelen;
00279 continue;
00280
00281 case BPF_LDX|BPF_W|BPF_LEN:
00282 X = wirelen;
00283 continue;
00284
00285 case BPF_LD|BPF_W|BPF_IND:
00286 k = X + pc->k;
00287 if (k + sizeof(int32) > buflen) {
00288 #if defined(KERNEL) || defined(_KERNEL)
00289 if (m == NULL)
00290 return 0;
00291 A = m_xword(m, k, &merr);
00292 if (merr != 0)
00293 return 0;
00294 continue;
00295 #else
00296 return 0;
00297 #endif
00298 }
00299 A = EXTRACT_LONG(&p[k]);
00300 continue;
00301
00302 case BPF_LD|BPF_H|BPF_IND:
00303 k = X + pc->k;
00304 if (k + sizeof(short) > buflen) {
00305 #if defined(KERNEL) || defined(_KERNEL)
00306 if (m == NULL)
00307 return 0;
00308 A = m_xhalf(m, k, &merr);
00309 if (merr != 0)
00310 return 0;
00311 continue;
00312 #else
00313 return 0;
00314 #endif
00315 }
00316 A = EXTRACT_SHORT(&p[k]);
00317 continue;
00318
00319 case BPF_LD|BPF_B|BPF_IND:
00320 k = X + pc->k;
00321 if (k >= buflen) {
00322 #if defined(KERNEL) || defined(_KERNEL)
00323 if (m == NULL)
00324 return 0;
00325 n = m;
00326 MINDEX(len, n, k);
00327 A = mtod(n, u_char *)[k];
00328 continue;
00329 #else
00330 return 0;
00331 #endif
00332 }
00333 A = p[k];
00334 continue;
00335
00336 case BPF_LDX|BPF_MSH|BPF_B:
00337 k = pc->k;
00338 if (k >= buflen) {
00339 #if defined(KERNEL) || defined(_KERNEL)
00340 if (m == NULL)
00341 return 0;
00342 n = m;
00343 MINDEX(len, n, k);
00344 X = (mtod(n, char *)[k] & 0xf) << 2;
00345 continue;
00346 #else
00347 return 0;
00348 #endif
00349 }
00350 X = (p[pc->k] & 0xf) << 2;
00351 continue;
00352
00353 case BPF_LD|BPF_IMM:
00354 A = pc->k;
00355 continue;
00356
00357 case BPF_LDX|BPF_IMM:
00358 X = pc->k;
00359 continue;
00360
00361 case BPF_LD|BPF_MEM:
00362 A = mem[pc->k];
00363 continue;
00364
00365 case BPF_LDX|BPF_MEM:
00366 X = mem[pc->k];
00367 continue;
00368
00369 case BPF_ST:
00370 mem[pc->k] = A;
00371 continue;
00372
00373 case BPF_STX:
00374 mem[pc->k] = X;
00375 continue;
00376
00377 case BPF_JMP|BPF_JA:
00378 pc += pc->k;
00379 continue;
00380
00381 case BPF_JMP|BPF_JGT|BPF_K:
00382 pc += (A > pc->k) ? pc->jt : pc->jf;
00383 continue;
00384
00385 case BPF_JMP|BPF_JGE|BPF_K:
00386 pc += (A >= pc->k) ? pc->jt : pc->jf;
00387 continue;
00388
00389 case BPF_JMP|BPF_JEQ|BPF_K:
00390 pc += (A == pc->k) ? pc->jt : pc->jf;
00391 continue;
00392
00393 case BPF_JMP|BPF_JSET|BPF_K:
00394 pc += (A & pc->k) ? pc->jt : pc->jf;
00395 continue;
00396
00397 case BPF_JMP|BPF_JGT|BPF_X:
00398 pc += (A > X) ? pc->jt : pc->jf;
00399 continue;
00400
00401 case BPF_JMP|BPF_JGE|BPF_X:
00402 pc += (A >= X) ? pc->jt : pc->jf;
00403 continue;
00404
00405 case BPF_JMP|BPF_JEQ|BPF_X:
00406 pc += (A == X) ? pc->jt : pc->jf;
00407 continue;
00408
00409 case BPF_JMP|BPF_JSET|BPF_X:
00410 pc += (A & X) ? pc->jt : pc->jf;
00411 continue;
00412
00413 case BPF_ALU|BPF_ADD|BPF_X:
00414 A += X;
00415 continue;
00416
00417 case BPF_ALU|BPF_SUB|BPF_X:
00418 A -= X;
00419 continue;
00420
00421 case BPF_ALU|BPF_MUL|BPF_X:
00422 A *= X;
00423 continue;
00424
00425 case BPF_ALU|BPF_DIV|BPF_X:
00426 if (X == 0)
00427 return 0;
00428 A /= X;
00429 continue;
00430
00431 case BPF_ALU|BPF_AND|BPF_X:
00432 A &= X;
00433 continue;
00434
00435 case BPF_ALU|BPF_OR|BPF_X:
00436 A |= X;
00437 continue;
00438
00439 case BPF_ALU|BPF_LSH|BPF_X:
00440 A <<= X;
00441 continue;
00442
00443 case BPF_ALU|BPF_RSH|BPF_X:
00444 A >>= X;
00445 continue;
00446
00447 case BPF_ALU|BPF_ADD|BPF_K:
00448 A += pc->k;
00449 continue;
00450
00451 case BPF_ALU|BPF_SUB|BPF_K:
00452 A -= pc->k;
00453 continue;
00454
00455 case BPF_ALU|BPF_MUL|BPF_K:
00456 A *= pc->k;
00457 continue;
00458
00459 case BPF_ALU|BPF_DIV|BPF_K:
00460 A /= pc->k;
00461 continue;
00462
00463 case BPF_ALU|BPF_AND|BPF_K:
00464 A &= pc->k;
00465 continue;
00466
00467 case BPF_ALU|BPF_OR|BPF_K:
00468 A |= pc->k;
00469 continue;
00470
00471 case BPF_ALU|BPF_LSH|BPF_K:
00472 A <<= pc->k;
00473 continue;
00474
00475 case BPF_ALU|BPF_RSH|BPF_K:
00476 A >>= pc->k;
00477 continue;
00478
00479 case BPF_ALU|BPF_NEG:
00480 A = -A;
00481 continue;
00482
00483 case BPF_MISC|BPF_TAX:
00484 X = A;
00485 continue;
00486
00487 case BPF_MISC|BPF_TXA:
00488 A = X;
00489 continue;
00490 }
00491 }
00492 }
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 int
00506 bpf_validate(f, len)
00507 struct bpf_insn *f;
00508 int len;
00509 {
00510 register int i;
00511 register struct bpf_insn *p;
00512
00513 for (i = 0; i < len; ++i) {
00514
00515
00516
00517
00518 p = &f[i];
00519 if (BPF_CLASS(p->code) == BPF_JMP) {
00520 register int from = i + 1;
00521
00522 if (BPF_OP(p->code) == BPF_JA) {
00523 if (from + p->k >= (unsigned)len)
00524 return 0;
00525 }
00526 else if (from + p->jt >= len || from + p->jf >= len)
00527 return 0;
00528 }
00529
00530
00531
00532 if ((BPF_CLASS(p->code) == BPF_ST ||
00533 (BPF_CLASS(p->code) == BPF_LD &&
00534 (p->code & 0xe0) == BPF_MEM)) &&
00535 (p->k >= BPF_MEMWORDS || p->k < 0))
00536 return 0;
00537
00538
00539
00540 if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
00541 return 0;
00542 }
00543 return BPF_CLASS(f[len - 1].code) == BPF_RET;
00544 }