]> git.saurik.com Git - apple/xnu.git/blame - bsd/net/bpf_filter.c
xnu-201.14.tar.gz
[apple/xnu.git] / bsd / net / bpf_filter.c
CommitLineData
1c79356b
A
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
11 *
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
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * Copyright (c) 1990, 1991, 1993
24 * The Regents of the University of California. All rights reserved.
25 *
26 * This code is derived from the Stanford/CMU enet packet filter,
27 * (net/enet.c) distributed as part of 4.3BSD, and code contributed
28 * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
29 * Berkeley Laboratory.
30 *
31 * Redistribution and use in source and binary forms, with or without
32 * modification, are permitted provided that the following conditions
33 * are met:
34 * 1. Redistributions of source code must retain the above copyright
35 * notice, this list of conditions and the following disclaimer.
36 * 2. Redistributions in binary form must reproduce the above copyright
37 * notice, this list of conditions and the following disclaimer in the
38 * documentation and/or other materials provided with the distribution.
39 * 3. All advertising materials mentioning features or use of this software
40 * must display the following acknowledgement:
41 * This product includes software developed by the University of
42 * California, Berkeley and its contributors.
43 * 4. Neither the name of the University nor the names of its contributors
44 * may be used to endorse or promote products derived from this software
45 * without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
48 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
51 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
52 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
53 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
55 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
56 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
57 * SUCH DAMAGE.
58 *
59 * @(#)bpf_filter.c 8.1 (Berkeley) 6/10/93
60 *
61 */
62
63#include <sys/param.h>
64
65#ifdef sun
66#include <netinet/in.h>
67#endif
68
69#if defined(sparc) || defined(mips) || defined(ibm032) || defined(__alpha__)
70#define BPF_ALIGN
71#endif
72
73#ifndef BPF_ALIGN
74#define EXTRACT_SHORT(p) ((u_int16_t)ntohs(*(u_int16_t *)p))
75#define EXTRACT_LONG(p) (ntohl(*(u_int32_t *)p))
76#else
77#define EXTRACT_SHORT(p)\
78 ((u_int16_t)\
79 ((u_int16_t)*((u_char *)p+0)<<8|\
80 (u_int16_t)*((u_char *)p+1)<<0))
81#define EXTRACT_LONG(p)\
82 ((u_int32_t)*((u_char *)p+0)<<24|\
83 (u_int32_t)*((u_char *)p+1)<<16|\
84 (u_int32_t)*((u_char *)p+2)<<8|\
85 (u_int32_t)*((u_char *)p+3)<<0)
86#endif
87
88#ifdef KERNEL
89#include <sys/mbuf.h>
90#endif
91#include <net/bpf.h>
92#ifdef KERNEL
93#define MINDEX(m, k) \
94{ \
95 register int len = m->m_len; \
96 \
97 while (k >= len) { \
98 k -= len; \
99 m = m->m_next; \
100 if (m == 0) \
101 return 0; \
102 len = m->m_len; \
103 } \
104}
105
106static u_int16_t m_xhalf __P((struct mbuf *m, bpf_u_int32 k, int *err));
107static u_int32_t m_xword __P((struct mbuf *m, bpf_u_int32 k, int *err));
108
109static u_int32_t
110m_xword(m, k, err)
111 register struct mbuf *m;
112 register bpf_u_int32 k;
113 register int *err;
114{
115 register size_t len;
116 register u_char *cp, *np;
117 register struct mbuf *m0;
118
119 len = m->m_len;
120 while (k >= len) {
121 k -= len;
122 m = m->m_next;
123 if (m == 0)
124 goto bad;
125 len = m->m_len;
126 }
127 cp = mtod(m, u_char *) + k;
128 if (len - k >= 4) {
129 *err = 0;
130 return EXTRACT_LONG(cp);
131 }
132 m0 = m->m_next;
133 if (m0 == 0 || m0->m_len + len - k < 4)
134 goto bad;
135 *err = 0;
136 np = mtod(m0, u_char *);
137 switch (len - k) {
138
139 case 1:
140 return
141 ((u_int32_t)cp[0] << 24) |
142 ((u_int32_t)np[0] << 16) |
143 ((u_int32_t)np[1] << 8) |
144 (u_int32_t)np[2];
145
146 case 2:
147 return
148 ((u_int32_t)cp[0] << 24) |
149 ((u_int32_t)cp[1] << 16) |
150 ((u_int32_t)np[0] << 8) |
151 (u_int32_t)np[1];
152
153 default:
154 return
155 ((u_int32_t)cp[0] << 24) |
156 ((u_int32_t)cp[1] << 16) |
157 ((u_int32_t)cp[2] << 8) |
158 (u_int32_t)np[0];
159 }
160 bad:
161 *err = 1;
162 return 0;
163}
164
165static u_int16_t
166m_xhalf(m, k, err)
167 register struct mbuf *m;
168 register bpf_u_int32 k;
169 register int *err;
170{
171 register size_t len;
172 register u_char *cp;
173 register struct mbuf *m0;
174
175 len = m->m_len;
176 while (k >= len) {
177 k -= len;
178 m = m->m_next;
179 if (m == 0)
180 goto bad;
181 len = m->m_len;
182 }
183 cp = mtod(m, u_char *) + k;
184 if (len - k >= 2) {
185 *err = 0;
186 return EXTRACT_SHORT(cp);
187 }
188 m0 = m->m_next;
189 if (m0 == 0)
190 goto bad;
191 *err = 0;
192 return (cp[0] << 8) | mtod(m0, u_char *)[0];
193 bad:
194 *err = 1;
195 return 0;
196}
197#endif
198
199/*
200 * Execute the filter program starting at pc on the packet p
201 * wirelen is the length of the original packet
202 * buflen is the amount of data present
203 */
204u_int
205bpf_filter(pc, p, wirelen, buflen)
206 register struct bpf_insn *pc;
207 register u_char *p;
208 u_int wirelen;
209 register u_int buflen;
210{
211 register u_int32_t A = 0, X = 0;
212 register bpf_u_int32 k;
213 int32_t mem[BPF_MEMWORDS];
214
215 if (pc == 0)
216 /*
217 * No filter means accept all.
218 */
219 return (u_int)-1;
220
221 --pc;
222 while (1) {
223 ++pc;
224 switch (pc->code) {
225
226 default:
227#ifdef KERNEL
228 return 0;
229#else
230 abort();
231#endif
232 case BPF_RET|BPF_K:
233 return (u_int)pc->k;
234
235 case BPF_RET|BPF_A:
236 return (u_int)A;
237
238 case BPF_LD|BPF_W|BPF_ABS:
239 k = pc->k;
240 if (k > buflen || sizeof(int32_t) > buflen - k) {
241#ifdef KERNEL
242 int merr;
243
244 if (buflen != 0)
245 return 0;
246 A = m_xword((struct mbuf *)p, k, &merr);
247 if (merr != 0)
248 return 0;
249 continue;
250#else
251 return 0;
252#endif
253 }
254#if BPF_ALIGN
255 if (((intptr_t)(p + k) & 3) != 0)
256 A = EXTRACT_LONG(&p[k]);
257 else
258#endif
259 A = ntohl(*(int32_t *)(p + k));
260 continue;
261
262 case BPF_LD|BPF_H|BPF_ABS:
263 k = pc->k;
264 if (k > buflen || sizeof(int16_t) > buflen - k) {
265#ifdef KERNEL
266 int merr;
267
268 if (buflen != 0)
269 return 0;
270 A = m_xhalf((struct mbuf *)p, k, &merr);
271 continue;
272#else
273 return 0;
274#endif
275 }
276 A = EXTRACT_SHORT(&p[k]);
277 continue;
278
279 case BPF_LD|BPF_B|BPF_ABS:
280 k = pc->k;
281 if (k >= buflen) {
282#ifdef KERNEL
283 register struct mbuf *m;
284
285 if (buflen != 0)
286 return 0;
287 m = (struct mbuf *)p;
288 MINDEX(m, k);
289 A = mtod(m, u_char *)[k];
290 continue;
291#else
292 return 0;
293#endif
294 }
295 A = p[k];
296 continue;
297
298 case BPF_LD|BPF_W|BPF_LEN:
299 A = wirelen;
300 continue;
301
302 case BPF_LDX|BPF_W|BPF_LEN:
303 X = wirelen;
304 continue;
305
306 case BPF_LD|BPF_W|BPF_IND:
307 k = X + pc->k;
308 if (pc->k > buflen || X > buflen - pc->k || sizeof(int32_t) > buflen - k) {
309#ifdef KERNEL
310 int merr;
311
312 if (buflen != 0)
313 return 0;
314 A = m_xword((struct mbuf *)p, k, &merr);
315 if (merr != 0)
316 return 0;
317 continue;
318#else
319 return 0;
320#endif
321 }
322#if BPF_ALIGN
323 if (((intptr_t)(p + k) & 3) != 0)
324 A = EXTRACT_LONG(&p[k]);
325 else
326#endif
327 A = ntohl(*(int32_t *)(p + k));
328 continue;
329
330 case BPF_LD|BPF_H|BPF_IND:
331 k = X + pc->k;
332 if (X > buflen || pc->k > buflen - X || sizeof(int16_t) > buflen - pc->k) {
333#ifdef KERNEL
334 int merr;
335
336 if (buflen != 0)
337 return 0;
338 A = m_xhalf((struct mbuf *)p, k, &merr);
339 if (merr != 0)
340 return 0;
341 continue;
342#else
343 return 0;
344#endif
345 }
346 A = EXTRACT_SHORT(&p[k]);
347 continue;
348
349 case BPF_LD|BPF_B|BPF_IND:
350 k = X + pc->k;
351 if (pc->k >= buflen || X >= buflen - pc->k) {
352#ifdef KERNEL
353 register struct mbuf *m;
354
355 if (buflen != 0)
356 return 0;
357 m = (struct mbuf *)p;
358 MINDEX(m, k);
359 A = mtod(m, char *)[k];
360 continue;
361#else
362 return 0;
363#endif
364 }
365 A = p[k];
366 continue;
367
368 case BPF_LDX|BPF_MSH|BPF_B:
369 k = pc->k;
370 if (k >= buflen) {
371#ifdef KERNEL
372 register struct mbuf *m;
373
374 if (buflen != 0)
375 return 0;
376 m = (struct mbuf *)p;
377 MINDEX(m, k);
378 X = (mtod(m, char *)[k] & 0xf) << 2;
379 continue;
380#else
381 return 0;
382#endif
383 }
384 X = (p[pc->k] & 0xf) << 2;
385 continue;
386
387 case BPF_LD|BPF_IMM:
388 A = pc->k;
389 continue;
390
391 case BPF_LDX|BPF_IMM:
392 X = pc->k;
393 continue;
394
395 case BPF_LD|BPF_MEM:
396 A = mem[pc->k];
397 continue;
398
399 case BPF_LDX|BPF_MEM:
400 X = mem[pc->k];
401 continue;
402
403 case BPF_ST:
404 mem[pc->k] = A;
405 continue;
406
407 case BPF_STX:
408 mem[pc->k] = X;
409 continue;
410
411 case BPF_JMP|BPF_JA:
412 pc += pc->k;
413 continue;
414
415 case BPF_JMP|BPF_JGT|BPF_K:
416 pc += (A > pc->k) ? pc->jt : pc->jf;
417 continue;
418
419 case BPF_JMP|BPF_JGE|BPF_K:
420 pc += (A >= pc->k) ? pc->jt : pc->jf;
421 continue;
422
423 case BPF_JMP|BPF_JEQ|BPF_K:
424 pc += (A == pc->k) ? pc->jt : pc->jf;
425 continue;
426
427 case BPF_JMP|BPF_JSET|BPF_K:
428 pc += (A & pc->k) ? pc->jt : pc->jf;
429 continue;
430
431 case BPF_JMP|BPF_JGT|BPF_X:
432 pc += (A > X) ? pc->jt : pc->jf;
433 continue;
434
435 case BPF_JMP|BPF_JGE|BPF_X:
436 pc += (A >= X) ? pc->jt : pc->jf;
437 continue;
438
439 case BPF_JMP|BPF_JEQ|BPF_X:
440 pc += (A == X) ? pc->jt : pc->jf;
441 continue;
442
443 case BPF_JMP|BPF_JSET|BPF_X:
444 pc += (A & X) ? pc->jt : pc->jf;
445 continue;
446
447 case BPF_ALU|BPF_ADD|BPF_X:
448 A += X;
449 continue;
450
451 case BPF_ALU|BPF_SUB|BPF_X:
452 A -= X;
453 continue;
454
455 case BPF_ALU|BPF_MUL|BPF_X:
456 A *= X;
457 continue;
458
459 case BPF_ALU|BPF_DIV|BPF_X:
460 if (X == 0)
461 return 0;
462 A /= X;
463 continue;
464
465 case BPF_ALU|BPF_AND|BPF_X:
466 A &= X;
467 continue;
468
469 case BPF_ALU|BPF_OR|BPF_X:
470 A |= X;
471 continue;
472
473 case BPF_ALU|BPF_LSH|BPF_X:
474 A <<= X;
475 continue;
476
477 case BPF_ALU|BPF_RSH|BPF_X:
478 A >>= X;
479 continue;
480
481 case BPF_ALU|BPF_ADD|BPF_K:
482 A += pc->k;
483 continue;
484
485 case BPF_ALU|BPF_SUB|BPF_K:
486 A -= pc->k;
487 continue;
488
489 case BPF_ALU|BPF_MUL|BPF_K:
490 A *= pc->k;
491 continue;
492
493 case BPF_ALU|BPF_DIV|BPF_K:
494 A /= pc->k;
495 continue;
496
497 case BPF_ALU|BPF_AND|BPF_K:
498 A &= pc->k;
499 continue;
500
501 case BPF_ALU|BPF_OR|BPF_K:
502 A |= pc->k;
503 continue;
504
505 case BPF_ALU|BPF_LSH|BPF_K:
506 A <<= pc->k;
507 continue;
508
509 case BPF_ALU|BPF_RSH|BPF_K:
510 A >>= pc->k;
511 continue;
512
513 case BPF_ALU|BPF_NEG:
514 A = -A;
515 continue;
516
517 case BPF_MISC|BPF_TAX:
518 X = A;
519 continue;
520
521 case BPF_MISC|BPF_TXA:
522 A = X;
523 continue;
524 }
525 }
526}
527
528#ifdef KERNEL
529/*
530 * Return true if the 'fcode' is a valid filter program.
531 * The constraints are that each jump be forward and to a valid
532 * code. The code must terminate with either an accept or reject.
533 * 'valid' is an array for use by the routine (it must be at least
534 * 'len' bytes long).
535 *
536 * The kernel needs to be able to verify an application's filter code.
537 * Otherwise, a bogus program could easily crash the system.
538 */
539int
540bpf_validate(f, len)
541 struct bpf_insn *f;
542 int len;
543{
544 register int i;
545 register struct bpf_insn *p;
546
547 for (i = 0; i < len; ++i) {
548 /*
549 * Check that that jumps are forward, and within
550 * the code block.
551 */
552 p = &f[i];
553 if (BPF_CLASS(p->code) == BPF_JMP) {
554 register int from = i + 1;
555
556 if (BPF_OP(p->code) == BPF_JA) {
557 if (from >= len || p->k >= len - from)
558 return 0;
559 }
560 else if (from >= len || p->jt >= len - from || p->jf >= len - from)
561 return 0;
562 }
563 /*
564 * Check that memory operations use valid addresses.
565 */
566 if ((BPF_CLASS(p->code) == BPF_ST ||
567 (BPF_CLASS(p->code) == BPF_LD &&
568 (p->code & 0xe0) == BPF_MEM)) &&
569 p->k >= BPF_MEMWORDS)
570 return 0;
571 /*
572 * Check for constant division by 0.
573 */
574 if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
575 return 0;
576 }
577 return BPF_CLASS(f[len - 1].code) == BPF_RET;
578}
579#endif