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