2 * Copyright (c) 1999 - 2003
3 * NetGroup, Politecnico di Torino (Italy)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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
40 /** @defgroup win_bpf win_bpf.c
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)";
51 #include <sys/param.h>
56 #include <sys/types.h>
59 #define int32 bpf_int32
60 #define u_int32 bpf_u_int32
64 #if defined(sparc) || defined(mips) || defined(ibm032) || \
65 defined(__alpha) || defined(__hpux)
72 #include <netinet/in.h>
75 #define EXTRACT_SHORT(p)\
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)
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
;
95 register u_int buflen
;
97 register u_int32 A
, X
;
99 int32 mem
[BPF_MEMWORDS
];
103 * No filter means accept all.
123 case BPF_LD
|BPF_W
|BPF_ABS
:
125 if (k
+ sizeof(int32
) > buflen
) {
128 A
= EXTRACT_LONG(&p
[k
]);
131 case BPF_LD
|BPF_H
|BPF_ABS
:
133 if (k
+ sizeof(short) > buflen
) {
136 A
= EXTRACT_SHORT(&p
[k
]);
139 case BPF_LD
|BPF_B
|BPF_ABS
:
141 if ((int)k
>= (int)buflen
) {
147 case BPF_LD
|BPF_W
|BPF_LEN
:
151 case BPF_LDX
|BPF_W
|BPF_LEN
:
155 case BPF_LD
|BPF_W
|BPF_IND
:
157 if (k
+ sizeof(int32
) > buflen
) {
160 A
= EXTRACT_LONG(&p
[k
]);
163 case BPF_LD
|BPF_H
|BPF_IND
:
165 if (k
+ sizeof(short) > buflen
) {
168 A
= EXTRACT_SHORT(&p
[k
]);
171 case BPF_LD
|BPF_B
|BPF_IND
:
173 if ((int)k
>= (int)buflen
) {
179 case BPF_LDX
|BPF_MSH
|BPF_B
:
181 if ((int)k
>= (int)buflen
) {
184 X
= (p
[pc
->k
] & 0xf) << 2;
191 case BPF_LDX
|BPF_IMM
:
199 case BPF_LDX
|BPF_MEM
:
215 case BPF_JMP
|BPF_JGT
|BPF_K
:
216 pc
+= ((int)A
> (int)pc
->k
) ? pc
->jt
: pc
->jf
;
219 case BPF_JMP
|BPF_JGE
|BPF_K
:
220 pc
+= ((int)A
>= (int)pc
->k
) ? pc
->jt
: pc
->jf
;
223 case BPF_JMP
|BPF_JEQ
|BPF_K
:
224 pc
+= ((int)A
== (int)pc
->k
) ? pc
->jt
: pc
->jf
;
227 case BPF_JMP
|BPF_JSET
|BPF_K
:
228 pc
+= (A
& pc
->k
) ? pc
->jt
: pc
->jf
;
231 case BPF_JMP
|BPF_JGT
|BPF_X
:
232 pc
+= (A
> X
) ? pc
->jt
: pc
->jf
;
235 case BPF_JMP
|BPF_JGE
|BPF_X
:
236 pc
+= (A
>= X
) ? pc
->jt
: pc
->jf
;
239 case BPF_JMP
|BPF_JEQ
|BPF_X
:
240 pc
+= (A
== X
) ? pc
->jt
: pc
->jf
;
243 case BPF_JMP
|BPF_JSET
|BPF_X
:
244 pc
+= (A
& X
) ? pc
->jt
: pc
->jf
;
247 case BPF_ALU
|BPF_ADD
|BPF_X
:
251 case BPF_ALU
|BPF_SUB
|BPF_X
:
255 case BPF_ALU
|BPF_MUL
|BPF_X
:
259 case BPF_ALU
|BPF_DIV
|BPF_X
:
265 case BPF_ALU
|BPF_AND
|BPF_X
:
269 case BPF_ALU
|BPF_OR
|BPF_X
:
273 case BPF_ALU
|BPF_LSH
|BPF_X
:
277 case BPF_ALU
|BPF_RSH
|BPF_X
:
281 case BPF_ALU
|BPF_ADD
|BPF_K
:
285 case BPF_ALU
|BPF_SUB
|BPF_K
:
289 case BPF_ALU
|BPF_MUL
|BPF_K
:
293 case BPF_ALU
|BPF_DIV
|BPF_K
:
297 case BPF_ALU
|BPF_AND
|BPF_K
:
301 case BPF_ALU
|BPF_OR
|BPF_K
:
305 case BPF_ALU
|BPF_LSH
|BPF_K
:
309 case BPF_ALU
|BPF_RSH
|BPF_K
:
313 case BPF_ALU
|BPF_NEG
:
317 case BPF_MISC
|BPF_TAX
:
321 case BPF_MISC
|BPF_TXA
:
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
;
341 register int headersize
;
343 register u_int buflen
;
345 register u_int32 A
, X
;
347 int32 mem
[BPF_MEMWORDS
];
351 * No filter means accept all.
371 case BPF_LD
|BPF_W
|BPF_ABS
:
373 if (k
+ sizeof(int32
) > buflen
) {
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
]);
400 case BPF_LD
|BPF_H
|BPF_ABS
:
402 if (k
+ sizeof(short) > buflen
) {
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
]);
415 case BPF_LD
|BPF_B
|BPF_ABS
:
417 if ((int)k
>= (int)buflen
) {
421 if(k
<headersize
) A
= p
[k
];
422 else A
= pd
[k
-headersize
];
426 case BPF_LD
|BPF_W
|BPF_LEN
:
430 case BPF_LDX
|BPF_W
|BPF_LEN
:
434 case BPF_LD
|BPF_W
|BPF_IND
:
436 if (k
+ sizeof(int32
) > buflen
) {
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
]);
463 case BPF_LD
|BPF_H
|BPF_IND
:
465 if (k
+ sizeof(short) > buflen
) {
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
]);
478 case BPF_LD
|BPF_B
|BPF_IND
:
480 if ((int)k
>= (int)buflen
) {
484 if(k
<headersize
) A
= p
[k
];
485 else A
= pd
[k
-headersize
];
489 case BPF_LDX
|BPF_MSH
|BPF_B
:
491 if ((int)k
>= (int)buflen
) {
495 if((pc
->k
)<headersize
) X
= (p
[pc
->k
] & 0xf) << 2;
496 else X
= (pd
[(pc
->k
)-headersize
] & 0xf) << 2;
504 case BPF_LDX
|BPF_IMM
:
512 case BPF_LDX
|BPF_MEM
:
528 case BPF_JMP
|BPF_JGT
|BPF_K
:
529 pc
+= ((int)A
> (int)pc
->k
) ? pc
->jt
: pc
->jf
;
532 case BPF_JMP
|BPF_JGE
|BPF_K
:
533 pc
+= ((int)A
>= (int)pc
->k
) ? pc
->jt
: pc
->jf
;
536 case BPF_JMP
|BPF_JEQ
|BPF_K
:
537 pc
+= ((int)A
== (int)pc
->k
) ? pc
->jt
: pc
->jf
;
540 case BPF_JMP
|BPF_JSET
|BPF_K
:
541 pc
+= (A
& pc
->k
) ? pc
->jt
: pc
->jf
;
544 case BPF_JMP
|BPF_JGT
|BPF_X
:
545 pc
+= (A
> X
) ? pc
->jt
: pc
->jf
;
548 case BPF_JMP
|BPF_JGE
|BPF_X
:
549 pc
+= (A
>= X
) ? pc
->jt
: pc
->jf
;
552 case BPF_JMP
|BPF_JEQ
|BPF_X
:
553 pc
+= (A
== X
) ? pc
->jt
: pc
->jf
;
556 case BPF_JMP
|BPF_JSET
|BPF_X
:
557 pc
+= (A
& X
) ? pc
->jt
: pc
->jf
;
560 case BPF_ALU
|BPF_ADD
|BPF_X
:
564 case BPF_ALU
|BPF_SUB
|BPF_X
:
568 case BPF_ALU
|BPF_MUL
|BPF_X
:
572 case BPF_ALU
|BPF_DIV
|BPF_X
:
578 case BPF_ALU
|BPF_AND
|BPF_X
:
582 case BPF_ALU
|BPF_OR
|BPF_X
:
586 case BPF_ALU
|BPF_LSH
|BPF_X
:
590 case BPF_ALU
|BPF_RSH
|BPF_X
:
594 case BPF_ALU
|BPF_ADD
|BPF_K
:
598 case BPF_ALU
|BPF_SUB
|BPF_K
:
602 case BPF_ALU
|BPF_MUL
|BPF_K
:
606 case BPF_ALU
|BPF_DIV
|BPF_K
:
610 case BPF_ALU
|BPF_AND
|BPF_K
:
614 case BPF_ALU
|BPF_OR
|BPF_K
:
618 case BPF_ALU
|BPF_LSH
|BPF_K
:
622 case BPF_ALU
|BPF_RSH
|BPF_K
:
626 case BPF_ALU
|BPF_NEG
:
630 case BPF_MISC
|BPF_TAX
:
634 case BPF_MISC
|BPF_TXA
:
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.
658 register u_int32 i
, from
;
659 register struct bpf_insn
*p
;
664 for (i
= 0; i
< len
; ++i
) {
666 switch (BPF_CLASS(p
->code
)) {
668 * Check that memory operations use valid addresses.
672 switch (BPF_MODE(p
->code
)) {
680 if (p
->k
>= BPF_MEMWORDS
)
691 if (p
->k
>= BPF_MEMWORDS
)
695 switch (BPF_OP(p
->code
)) {
706 * Check for constant division by 0.
708 if (BPF_RVAL(p
->code
) == BPF_K
&& p
->k
== 0)
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
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.
732 switch (BPF_OP(p
->code
)) {
734 if (from
+ p
->k
< from
|| from
+ p
->k
>= len
)
741 if (from
+ p
->jt
>= len
|| from
+ p
->jf
>= len
)
747 IF_LOUD(DbgPrint("Validating program: no wrong JUMPS");)
757 return BPF_CLASS(f
[len
- 1].code
) == BPF_RET
;