add winpcap 4.0.2 from url http://www.winpcap.org/
[natblaster.git] / winpcap / Packet9x / VXD / win_bpf_filter.c
blob3fa012e7948baa2eecb8182bbe76b865ab3643d8
1 /*
2 * Copyright (c) 1999 - 2003
3 * NetGroup, Politecnico di Torino (Italy)
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the Politecnico di Torino nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * @(#)bpf.c 7.5 (Berkeley) 7/15/91
36 /** @ingroup NPF
37 * @{
40 /** @defgroup win_bpf win_bpf.c
41 * XXX todo.
42 * @{
45 #if !(defined(lint) || defined(KERNEL))
46 static const char rcsid[] =
47 "@(#) $Header: /usr/cvsroot_private/winpcap/Packet9x/VXD/win_bpf_filter.c,v 1.5 2005/12/02 22:31:26 gianlucav Exp $ (LBL)";
48 #endif
50 #ifndef WIN32
51 #include <sys/param.h>
52 #include <sys/time.h>
53 #else
54 #include <winsock2.h>
55 #endif
56 #include <sys/types.h>
57 #include "win_bpf.h"
59 #define int32 bpf_int32
60 #define u_int32 bpf_u_int32
63 #ifndef LBL_ALIGN
64 #if defined(sparc) || defined(mips) || defined(ibm032) || \
65 defined(__alpha) || defined(__hpux)
66 #define LBL_ALIGN
67 #endif
68 #endif
70 #ifndef LBL_ALIGN
71 #ifndef WIN32
72 #include <netinet/in.h>
73 #endif
75 #define EXTRACT_SHORT(p)\
76 ((u_short)\
77 ((u_short)*((u_char *)p+0)<<8|\
78 (u_short)*((u_char *)p+1)<<0))
79 #define EXTRACT_LONG(p)\
80 ((u_int32)*((u_char *)p+0)<<24|\
81 (u_int32)*((u_char *)p+1)<<16|\
82 (u_int32)*((u_char *)p+2)<<8|\
83 (u_int32)*((u_char *)p+3)<<0)
84 #endif
87 * Execute the filter program starting at pc on the packet p
88 * wirelen is the length of the original packet
89 * buflen is the amount of data present
91 u_int bpf_filter(pc, p, wirelen, buflen)
92 register struct bpf_insn *pc;
93 register u_char *p;
94 u_int wirelen;
95 register u_int buflen;
97 register u_int32 A, X;
98 register int k;
99 int32 mem[BPF_MEMWORDS];
101 if (pc == 0)
103 * No filter means accept all.
105 return (u_int)-1;
106 A = 0;
107 X = 0;
108 --pc;
109 while (1) {
110 ++pc;
111 switch (pc->code) {
113 default:
115 return 0;
117 case BPF_RET|BPF_K:
118 return (u_int)pc->k;
120 case BPF_RET|BPF_A:
121 return (u_int)A;
123 case BPF_LD|BPF_W|BPF_ABS:
124 k = pc->k;
125 if (k + sizeof(int32) > buflen) {
126 return 0;
128 A = EXTRACT_LONG(&p[k]);
129 continue;
131 case BPF_LD|BPF_H|BPF_ABS:
132 k = pc->k;
133 if (k + sizeof(short) > buflen) {
134 return 0;
136 A = EXTRACT_SHORT(&p[k]);
137 continue;
139 case BPF_LD|BPF_B|BPF_ABS:
140 k = pc->k;
141 if ((int)k >= (int)buflen) {
142 return 0;
144 A = p[k];
145 continue;
147 case BPF_LD|BPF_W|BPF_LEN:
148 A = wirelen;
149 continue;
151 case BPF_LDX|BPF_W|BPF_LEN:
152 X = wirelen;
153 continue;
155 case BPF_LD|BPF_W|BPF_IND:
156 k = X + pc->k;
157 if (k + sizeof(int32) > buflen) {
158 return 0;
160 A = EXTRACT_LONG(&p[k]);
161 continue;
163 case BPF_LD|BPF_H|BPF_IND:
164 k = X + pc->k;
165 if (k + sizeof(short) > buflen) {
166 return 0;
168 A = EXTRACT_SHORT(&p[k]);
169 continue;
171 case BPF_LD|BPF_B|BPF_IND:
172 k = X + pc->k;
173 if ((int)k >= (int)buflen) {
174 return 0;
176 A = p[k];
177 continue;
179 case BPF_LDX|BPF_MSH|BPF_B:
180 k = pc->k;
181 if ((int)k >= (int)buflen) {
182 return 0;
184 X = (p[pc->k] & 0xf) << 2;
185 continue;
187 case BPF_LD|BPF_IMM:
188 A = pc->k;
189 continue;
191 case BPF_LDX|BPF_IMM:
192 X = pc->k;
193 continue;
195 case BPF_LD|BPF_MEM:
196 A = mem[pc->k];
197 continue;
199 case BPF_LDX|BPF_MEM:
200 X = mem[pc->k];
201 continue;
203 case BPF_ST:
204 mem[pc->k] = A;
205 continue;
207 case BPF_STX:
208 mem[pc->k] = X;
209 continue;
211 case BPF_JMP|BPF_JA:
212 pc += pc->k;
213 continue;
215 case BPF_JMP|BPF_JGT|BPF_K:
216 pc += ((int)A > (int)pc->k) ? pc->jt : pc->jf;
217 continue;
219 case BPF_JMP|BPF_JGE|BPF_K:
220 pc += ((int)A >= (int)pc->k) ? pc->jt : pc->jf;
221 continue;
223 case BPF_JMP|BPF_JEQ|BPF_K:
224 pc += ((int)A == (int)pc->k) ? pc->jt : pc->jf;
225 continue;
227 case BPF_JMP|BPF_JSET|BPF_K:
228 pc += (A & pc->k) ? pc->jt : pc->jf;
229 continue;
231 case BPF_JMP|BPF_JGT|BPF_X:
232 pc += (A > X) ? pc->jt : pc->jf;
233 continue;
235 case BPF_JMP|BPF_JGE|BPF_X:
236 pc += (A >= X) ? pc->jt : pc->jf;
237 continue;
239 case BPF_JMP|BPF_JEQ|BPF_X:
240 pc += (A == X) ? pc->jt : pc->jf;
241 continue;
243 case BPF_JMP|BPF_JSET|BPF_X:
244 pc += (A & X) ? pc->jt : pc->jf;
245 continue;
247 case BPF_ALU|BPF_ADD|BPF_X:
248 A += X;
249 continue;
251 case BPF_ALU|BPF_SUB|BPF_X:
252 A -= X;
253 continue;
255 case BPF_ALU|BPF_MUL|BPF_X:
256 A *= X;
257 continue;
259 case BPF_ALU|BPF_DIV|BPF_X:
260 if (X == 0)
261 return 0;
262 A /= X;
263 continue;
265 case BPF_ALU|BPF_AND|BPF_X:
266 A &= X;
267 continue;
269 case BPF_ALU|BPF_OR|BPF_X:
270 A |= X;
271 continue;
273 case BPF_ALU|BPF_LSH|BPF_X:
274 A <<= X;
275 continue;
277 case BPF_ALU|BPF_RSH|BPF_X:
278 A >>= X;
279 continue;
281 case BPF_ALU|BPF_ADD|BPF_K:
282 A += pc->k;
283 continue;
285 case BPF_ALU|BPF_SUB|BPF_K:
286 A -= pc->k;
287 continue;
289 case BPF_ALU|BPF_MUL|BPF_K:
290 A *= pc->k;
291 continue;
293 case BPF_ALU|BPF_DIV|BPF_K:
294 A /= pc->k;
295 continue;
297 case BPF_ALU|BPF_AND|BPF_K:
298 A &= pc->k;
299 continue;
301 case BPF_ALU|BPF_OR|BPF_K:
302 A |= pc->k;
303 continue;
305 case BPF_ALU|BPF_LSH|BPF_K:
306 A <<= pc->k;
307 continue;
309 case BPF_ALU|BPF_RSH|BPF_K:
310 A >>= pc->k;
311 continue;
313 case BPF_ALU|BPF_NEG:
314 (int)A = -((int)A);
315 continue;
317 case BPF_MISC|BPF_TAX:
318 X = A;
319 continue;
321 case BPF_MISC|BPF_TXA:
322 A = X;
323 continue;
330 * Execute the filter program starting at pc on the packet whose header is
331 * pointed by p and whose data is pointed by pd.
332 * headersize is the size of the the header
333 * wirelen is the length of the original packet
334 * buflen is the amount of data present
337 u_int bpf_filter_with_2_buffers(pc, p, pd, headersize, wirelen, buflen)
338 register struct bpf_insn *pc;
339 register u_char *p;
340 register u_char *pd;
341 register int headersize;
342 u_int wirelen;
343 register u_int buflen;
345 register u_int32 A, X;
346 register int k;
347 int32 mem[BPF_MEMWORDS];
349 if (pc == 0)
351 * No filter means accept all.
353 return (u_int)-1;
354 A = 0;
355 X = 0;
356 --pc;
357 while (1) {
358 ++pc;
359 switch (pc->code) {
361 default:
363 return 0;
365 case BPF_RET|BPF_K:
366 return (u_int)pc->k;
368 case BPF_RET|BPF_A:
369 return (u_int)A;
371 case BPF_LD|BPF_W|BPF_ABS:
372 k = pc->k;
373 if (k + sizeof(int32) > buflen) {
374 return 0;
377 if(k + (int)sizeof(int32) < headersize) A = EXTRACT_LONG(&p[k]);
378 else if(k + 2 == headersize){
379 A=(u_int32)*((u_char *)p+k)<<24|
380 (u_int32)*((u_char *)p+k+1)<<16|
381 (u_int32)*((u_char *)p+k+2)<<8|
382 (u_int32)*((u_char *)pd+k-headersize);
384 else if(k == headersize-1){
385 A=(u_int32)*((u_char *)p+k)<<24|
386 (u_int32)*((u_char *)p+k+1)<<16|
387 (u_int32)*((u_char *)pd+k-headersize)<<8|
388 (u_int32)*((u_char *)pd+k-headersize+1);
390 else if(k == headersize){
391 A=(u_int32)*((u_char *)p+k)<<24|
392 (u_int32)*((u_char *)pd+k-headersize+1)<<16|
393 (u_int32)*((u_char *)pd+k-headersize+2)<<8|
394 (u_int32)*((u_char *)pd+k-headersize+3);
396 A = EXTRACT_LONG(&pd[k-headersize]);
398 continue;
400 case BPF_LD|BPF_H|BPF_ABS:
401 k = pc->k;
402 if (k + sizeof(short) > buflen) {
403 return 0;
406 if(k + (int)sizeof(short) < headersize) A = EXTRACT_SHORT(&p[k]);
407 else if(k == headersize){
408 A=(u_short)*((u_char *)p+k)<<8|
409 (u_short)*((u_char *)pd+k-headersize);
411 A = EXTRACT_SHORT(&pd[k-headersize]);
413 continue;
415 case BPF_LD|BPF_B|BPF_ABS:
416 k = pc->k;
417 if ((int)k >= (int)buflen) {
418 return 0;
421 if(k<headersize) A = p[k];
422 else A = pd[k-headersize];
424 continue;
426 case BPF_LD|BPF_W|BPF_LEN:
427 A = wirelen;
428 continue;
430 case BPF_LDX|BPF_W|BPF_LEN:
431 X = wirelen;
432 continue;
434 case BPF_LD|BPF_W|BPF_IND:
435 k = X + pc->k;
436 if (k + sizeof(int32) > buflen) {
437 return 0;
440 if(k + (int)sizeof(int32) < headersize) A = EXTRACT_LONG(&p[k]);
441 else if(k + (int)sizeof(int32) == headersize+2){
442 A=(u_int32)*((u_char *)p+k)<<24|
443 (u_int32)*((u_char *)p+k+1)<<16|
444 (u_int32)*((u_char *)p+k+2)<<8|
445 (u_int32)*((u_char *)pd+k-headersize);
447 else if(k + (int)sizeof(int32) == headersize+3){
448 A=(u_int32)*((u_char *)p+k)<<24|
449 (u_int32)*((u_char *)p+k+1)<<16|
450 (u_int32)*((u_char *)pd+k-headersize)<<8|
451 (u_int32)*((u_char *)pd+k-headersize+1);
453 else if(k + (int)sizeof(int32) == headersize+4){
454 A=(u_int32)*((u_char *)p+k)<<24|
455 (u_int32)*((u_char *)pd+k-headersize+1)<<16|
456 (u_int32)*((u_char *)pd+k-headersize+2)<<8|
457 (u_int32)*((u_char *)pd+k-headersize+3);
459 A = EXTRACT_LONG(&pd[k-headersize]);
461 continue;
463 case BPF_LD|BPF_H|BPF_IND:
464 k = X + pc->k;
465 if (k + sizeof(short) > buflen) {
466 return 0;
469 if(k + (int)sizeof(short) < headersize) A = EXTRACT_SHORT(&p[k]);
470 else if(k == headersize){
471 A=(u_short)*((u_char *)p+k)<<8|
472 (u_short)*((u_char *)pd+k-headersize);
474 A = EXTRACT_SHORT(&pd[k-headersize]);
476 continue;
478 case BPF_LD|BPF_B|BPF_IND:
479 k = X + pc->k;
480 if ((int)k >= (int)buflen) {
481 return 0;
484 if(k<headersize) A = p[k];
485 else A = pd[k-headersize];
487 continue;
489 case BPF_LDX|BPF_MSH|BPF_B:
490 k = pc->k;
491 if ((int)k >= (int)buflen) {
492 return 0;
495 if((pc->k)<headersize) X = (p[pc->k] & 0xf) << 2;
496 else X = (pd[(pc->k)-headersize] & 0xf) << 2;
498 continue;
500 case BPF_LD|BPF_IMM:
501 A = pc->k;
502 continue;
504 case BPF_LDX|BPF_IMM:
505 X = pc->k;
506 continue;
508 case BPF_LD|BPF_MEM:
509 A = mem[pc->k];
510 continue;
512 case BPF_LDX|BPF_MEM:
513 X = mem[pc->k];
514 continue;
516 case BPF_ST:
517 mem[pc->k] = A;
518 continue;
520 case BPF_STX:
521 mem[pc->k] = X;
522 continue;
524 case BPF_JMP|BPF_JA:
525 pc += pc->k;
526 continue;
528 case BPF_JMP|BPF_JGT|BPF_K:
529 pc += ((int)A > (int)pc->k) ? pc->jt : pc->jf;
530 continue;
532 case BPF_JMP|BPF_JGE|BPF_K:
533 pc += ((int)A >= (int)pc->k) ? pc->jt : pc->jf;
534 continue;
536 case BPF_JMP|BPF_JEQ|BPF_K:
537 pc += ((int)A == (int)pc->k) ? pc->jt : pc->jf;
538 continue;
540 case BPF_JMP|BPF_JSET|BPF_K:
541 pc += (A & pc->k) ? pc->jt : pc->jf;
542 continue;
544 case BPF_JMP|BPF_JGT|BPF_X:
545 pc += (A > X) ? pc->jt : pc->jf;
546 continue;
548 case BPF_JMP|BPF_JGE|BPF_X:
549 pc += (A >= X) ? pc->jt : pc->jf;
550 continue;
552 case BPF_JMP|BPF_JEQ|BPF_X:
553 pc += (A == X) ? pc->jt : pc->jf;
554 continue;
556 case BPF_JMP|BPF_JSET|BPF_X:
557 pc += (A & X) ? pc->jt : pc->jf;
558 continue;
560 case BPF_ALU|BPF_ADD|BPF_X:
561 A += X;
562 continue;
564 case BPF_ALU|BPF_SUB|BPF_X:
565 A -= X;
566 continue;
568 case BPF_ALU|BPF_MUL|BPF_X:
569 A *= X;
570 continue;
572 case BPF_ALU|BPF_DIV|BPF_X:
573 if (X == 0)
574 return 0;
575 A /= X;
576 continue;
578 case BPF_ALU|BPF_AND|BPF_X:
579 A &= X;
580 continue;
582 case BPF_ALU|BPF_OR|BPF_X:
583 A |= X;
584 continue;
586 case BPF_ALU|BPF_LSH|BPF_X:
587 A <<= X;
588 continue;
590 case BPF_ALU|BPF_RSH|BPF_X:
591 A >>= X;
592 continue;
594 case BPF_ALU|BPF_ADD|BPF_K:
595 A += pc->k;
596 continue;
598 case BPF_ALU|BPF_SUB|BPF_K:
599 A -= pc->k;
600 continue;
602 case BPF_ALU|BPF_MUL|BPF_K:
603 A *= pc->k;
604 continue;
606 case BPF_ALU|BPF_DIV|BPF_K:
607 A /= pc->k;
608 continue;
610 case BPF_ALU|BPF_AND|BPF_K:
611 A &= pc->k;
612 continue;
614 case BPF_ALU|BPF_OR|BPF_K:
615 A |= pc->k;
616 continue;
618 case BPF_ALU|BPF_LSH|BPF_K:
619 A <<= pc->k;
620 continue;
622 case BPF_ALU|BPF_RSH|BPF_K:
623 A >>= pc->k;
624 continue;
626 case BPF_ALU|BPF_NEG:
627 (int)A = -((int)A);
628 continue;
630 case BPF_MISC|BPF_TAX:
631 X = A;
632 continue;
634 case BPF_MISC|BPF_TXA:
635 A = X;
636 continue;
643 * Return true if the 'fcode' is a valid filter program.
644 * The constraints are that each jump be forward and to a valid
645 * code, that memory accesses are within valid ranges (to the
646 * extent that this can be checked statically; loads of packet
647 * data have to be, and are, also checked at run time), and that
648 * the code terminates with either an accept or reject.
650 * The kernel needs to be able to verify an application's filter code.
651 * Otherwise, a bogus program could easily crash the system.
654 bpf_validate(f, len)
655 struct bpf_insn *f;
656 int len;
658 register u_int32 i, from;
659 register struct bpf_insn *p;
661 if (len < 1)
662 return 0;
664 for (i = 0; i < len; ++i) {
665 p = &f[i];
666 switch (BPF_CLASS(p->code)) {
668 * Check that memory operations use valid addresses.
670 case BPF_LD:
671 case BPF_LDX:
672 switch (BPF_MODE(p->code)) {
673 case BPF_IMM:
674 break;
675 case BPF_ABS:
676 case BPF_IND:
677 case BPF_MSH:
678 break;
679 case BPF_MEM:
680 if (p->k >= BPF_MEMWORDS)
681 return 0;
682 break;
683 case BPF_LEN:
684 break;
685 default:
686 return 0;
688 break;
689 case BPF_ST:
690 case BPF_STX:
691 if (p->k >= BPF_MEMWORDS)
692 return 0;
693 break;
694 case BPF_ALU:
695 switch (BPF_OP(p->code)) {
696 case BPF_ADD:
697 case BPF_SUB:
698 case BPF_OR:
699 case BPF_AND:
700 case BPF_LSH:
701 case BPF_RSH:
702 case BPF_NEG:
703 break;
704 case BPF_DIV:
706 * Check for constant division by 0.
708 if (BPF_RVAL(p->code) == BPF_K && p->k == 0)
709 return 0;
710 default:
711 return 0;
713 break;
714 case BPF_JMP:
716 * Check that jumps are within the code block,
717 * and that unconditional branches don't go
718 * backwards as a result of an overflow.
719 * Unconditional branches have a 32-bit offset,
720 * so they could overflow; we check to make
721 * sure they don't. Conditional branches have
722 * an 8-bit offset, and the from address is <=
723 * BPF_MAXINSNS, and we assume that BPF_MAXINSNS
724 * is sufficiently small that adding 255 to it
725 * won't overflow.
727 * We know that len is <= BPF_MAXINSNS, and we
728 * assume that BPF_MAXINSNS is < the maximum size
729 * of a u_int, so that i + 1 doesn't overflow.
731 from = i + 1;
732 switch (BPF_OP(p->code)) {
733 case BPF_JA:
734 if (from + p->k < from || from + p->k >= len)
735 return 0;
736 break;
737 case BPF_JEQ:
738 case BPF_JGT:
739 case BPF_JGE:
740 case BPF_JSET:
741 if (from + p->jt >= len || from + p->jf >= len)
742 return 0;
743 break;
744 default:
745 return 0;
747 IF_LOUD(DbgPrint("Validating program: no wrong JUMPS");)
748 break;
749 case BPF_RET:
750 break;
751 case BPF_MISC:
752 break;
753 default:
754 return 0;
757 return BPF_CLASS(f[len - 1].code) == BPF_RET;