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