]>
git.saurik.com Git - apple/xnu.git/blob - iokit/Drivers/network/AppleBPF/bpf_filter.c
09f025c250f99d8053a3c88cf7288894b30e6bbf
2 * Copyright (c) 1998-2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
22 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
24 * Copyright (c) 1990, 1991, 1992, 1993
25 * The Regents of the University of California. All rights reserved.
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55 * @(#)bpf_filter.c 8.1 (Berkeley) 6/10/93
60 #include <sys/param.h>
61 #include <sys/types.h>
64 #if defined(sparc) || defined(hppa)
69 #define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p))
70 #define EXTRACT_LONG(p) (ntohl(*(u_int32_t *)p))
72 #define EXTRACT_SHORT(p)\
74 ((u_short)*((u_char *)p+0)<<8|\
75 (u_short)*((u_char *)p+1)<<0))
76 #define EXTRACT_LONG(p)\
77 ((u_int32_t)*((u_char *)p+0)<<24|\
78 (u_int32_t)*((u_char *)p+1)<<16|\
79 (u_int32_t)*((u_char *)p+2)<<8|\
80 (u_int32_t)*((u_char *)p+3)<<0)
86 #define MINDEX(m, k) \
88 register int len = m->m_len; \
101 register struct mbuf
*m
;
102 register int k
, *err
;
105 register u_char
*cp
, *np
;
106 register struct mbuf
*m0
;
116 cp
= mtod(m
, u_char
*) + k
;
119 return EXTRACT_LONG(cp
);
122 if (m0
== 0 || m0
->m_len
+ len
- k
< 4)
125 np
= mtod(m0
, u_char
*);
129 return (cp
[k
] << 24) | (np
[0] << 16) | (np
[1] << 8) | np
[2];
132 return (cp
[k
] << 24) | (cp
[k
+ 1] << 16) | (np
[0] << 8) |
136 return (cp
[k
] << 24) | (cp
[k
+ 1] << 16) | (cp
[k
+ 2] << 8) |
146 register struct mbuf
*m
;
147 register int k
, *err
;
151 register struct mbuf
*m0
;
161 cp
= mtod(m
, u_char
*) + k
;
164 return EXTRACT_SHORT(cp
);
170 return (cp
[k
] << 8) | mtod(m0
, u_char
*)[0];
180 * Execute the filter program starting at pc on the packet p
181 * wirelen is the length of the original packet
182 * buflen is the amount of data present
185 bpf_filter(pc
, p
, wirelen
, buflen
)
186 register struct bpf_insn
*pc
;
189 register u_int buflen
;
191 register u_int32_t A
, X
;
193 int32_t mem
[BPF_MEMWORDS
];
197 * No filter means accept all.
221 case BPF_LD
|BPF_W
|BPF_ABS
:
223 if (k
+ sizeof(int32_t) > buflen
) {
229 A
= m_xword((struct mbuf
*)p
, k
, &merr
);
238 if (((int)(p
+ k
) & 3) != 0)
239 A
= EXTRACT_LONG(&p
[k
]);
242 A
= ntohl(*(long *)(p
+ k
));
245 case BPF_LD
|BPF_H
|BPF_ABS
:
247 if (k
+ sizeof(short) > buflen
) {
253 A
= m_xhalf((struct mbuf
*)p
, k
, &merr
);
259 A
= EXTRACT_SHORT(&p
[k
]);
262 case BPF_LD
|BPF_B
|BPF_ABS
:
266 register struct mbuf
*m
;
270 m
= (struct mbuf
*)p
;
272 A
= mtod(m
, u_char
*)[k
];
281 case BPF_LD
|BPF_W
|BPF_LEN
:
285 case BPF_LDX
|BPF_W
|BPF_LEN
:
289 case BPF_LD
|BPF_W
|BPF_IND
:
291 if (k
+ sizeof(int32_t) > buflen
) {
297 A
= m_xword((struct mbuf
*)p
, k
, &merr
);
306 if (((int)(p
+ k
) & 3) != 0)
307 A
= EXTRACT_LONG(&p
[k
]);
310 A
= ntohl(*(long *)(p
+ k
));
313 case BPF_LD
|BPF_H
|BPF_IND
:
315 if (k
+ sizeof(short) > buflen
) {
321 A
= m_xhalf((struct mbuf
*)p
, k
, &merr
);
329 A
= EXTRACT_SHORT(&p
[k
]);
332 case BPF_LD
|BPF_B
|BPF_IND
:
336 register struct mbuf
*m
;
340 m
= (struct mbuf
*)p
;
342 A
= mtod(m
, char *)[k
];
351 case BPF_LDX
|BPF_MSH
|BPF_B
:
355 register struct mbuf
*m
;
359 m
= (struct mbuf
*)p
;
361 X
= (mtod(m
, char *)[k
] & 0xf) << 2;
367 X
= (p
[pc
->k
] & 0xf) << 2;
374 case BPF_LDX
|BPF_IMM
:
382 case BPF_LDX
|BPF_MEM
:
398 case BPF_JMP
|BPF_JGT
|BPF_K
:
399 pc
+= (A
> pc
->k
) ? pc
->jt
: pc
->jf
;
402 case BPF_JMP
|BPF_JGE
|BPF_K
:
403 pc
+= (A
>= pc
->k
) ? pc
->jt
: pc
->jf
;
406 case BPF_JMP
|BPF_JEQ
|BPF_K
:
407 pc
+= (A
== pc
->k
) ? pc
->jt
: pc
->jf
;
410 case BPF_JMP
|BPF_JSET
|BPF_K
:
411 pc
+= (A
& pc
->k
) ? pc
->jt
: pc
->jf
;
414 case BPF_JMP
|BPF_JGT
|BPF_X
:
415 pc
+= (A
> X
) ? pc
->jt
: pc
->jf
;
418 case BPF_JMP
|BPF_JGE
|BPF_X
:
419 pc
+= (A
>= X
) ? pc
->jt
: pc
->jf
;
422 case BPF_JMP
|BPF_JEQ
|BPF_X
:
423 pc
+= (A
== X
) ? pc
->jt
: pc
->jf
;
426 case BPF_JMP
|BPF_JSET
|BPF_X
:
427 pc
+= (A
& X
) ? pc
->jt
: pc
->jf
;
430 case BPF_ALU
|BPF_ADD
|BPF_X
:
434 case BPF_ALU
|BPF_SUB
|BPF_X
:
438 case BPF_ALU
|BPF_MUL
|BPF_X
:
442 case BPF_ALU
|BPF_DIV
|BPF_X
:
448 case BPF_ALU
|BPF_AND
|BPF_X
:
452 case BPF_ALU
|BPF_OR
|BPF_X
:
456 case BPF_ALU
|BPF_LSH
|BPF_X
:
460 case BPF_ALU
|BPF_RSH
|BPF_X
:
464 case BPF_ALU
|BPF_ADD
|BPF_K
:
468 case BPF_ALU
|BPF_SUB
|BPF_K
:
472 case BPF_ALU
|BPF_MUL
|BPF_K
:
476 case BPF_ALU
|BPF_DIV
|BPF_K
:
480 case BPF_ALU
|BPF_AND
|BPF_K
:
484 case BPF_ALU
|BPF_OR
|BPF_K
:
488 case BPF_ALU
|BPF_LSH
|BPF_K
:
492 case BPF_ALU
|BPF_RSH
|BPF_K
:
496 case BPF_ALU
|BPF_NEG
:
500 case BPF_MISC
|BPF_TAX
:
504 case BPF_MISC
|BPF_TXA
:
513 * Return true if the 'fcode' is a valid filter program.
514 * The constraints are that each jump be forward and to a valid
515 * code. The code must terminate with either an accept or reject.
516 * 'valid' is an array for use by the routine (it must be at least
519 * The kernel needs to be able to verify an application's filter code.
520 * Otherwise, a bogus program could easily crash the system.
528 register struct bpf_insn
*p
;
530 for (i
= 0; i
< len
; ++i
) {
532 * Check that that jumps are forward, and within
536 if (BPF_CLASS(p
->code
) == BPF_JMP
) {
537 register int from
= i
+ 1;
539 if (BPF_OP(p
->code
) == BPF_JA
) {
540 if (from
+ p
->k
>= len
)
543 else if (from
+ p
->jt
>= len
|| from
+ p
->jf
>= len
)
547 * Check that memory operations use valid addresses.
549 if ((BPF_CLASS(p
->code
) == BPF_ST
||
550 (BPF_CLASS(p
->code
) == BPF_LD
&&
551 (p
->code
& 0xe0) == BPF_MEM
)) &&
552 (p
->k
>= BPF_MEMWORDS
|| p
->k
< 0))
555 * Check for constant division by 0.
557 if (p
->code
== (BPF_ALU
|BPF_DIV
|BPF_K
) && p
->k
== 0)
560 return BPF_CLASS(f
[len
- 1].code
) == BPF_RET
;