xref: /netbsd-src/sys/net/bpf_filter.c (revision 6ea46cb5e46c49111a6ecf3bcbe3c7e2730fe9f6)
1 /*	$NetBSD: bpf_filter.c,v 1.6 1994/06/29 06:35:56 cgd Exp $	*/
2 
3 /*
4  * Copyright (c) 1990, 1991, 1993
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 #include <sys/param.h>
44 #include <sys/types.h>
45 #include <sys/time.h>
46 
47 #ifdef sun
48 #include <netinet/in.h>
49 #endif
50 
51 #if defined(sparc) || defined(mips) || defined(ibm032)
52 #define BPF_ALIGN
53 #endif
54 
55 #ifndef BPF_ALIGN
56 #define EXTRACT_SHORT(p)	((u_short)ntohs(*(u_short *)p))
57 #define EXTRACT_LONG(p)		(ntohl(*(u_long *)p))
58 #else
59 #define EXTRACT_SHORT(p)\
60 	((u_short)\
61 		((u_short)*((u_char *)p+0)<<8|\
62 		 (u_short)*((u_char *)p+1)<<0))
63 #define EXTRACT_LONG(p)\
64 		((u_long)*((u_char *)p+0)<<24|\
65 		 (u_long)*((u_char *)p+1)<<16|\
66 		 (u_long)*((u_char *)p+2)<<8|\
67 		 (u_long)*((u_char *)p+3)<<0)
68 #endif
69 
70 #ifdef KERNEL
71 #include <sys/mbuf.h>
72 #define MINDEX(m, k) \
73 { \
74 	register int len = m->m_len; \
75  \
76 	while (k >= len) { \
77 		k -= len; \
78 		m = m->m_next; \
79 		if (m == 0) \
80 			return 0; \
81 		len = m->m_len; \
82 	} \
83 }
84 
85 static int
86 m_xword(m, k, err)
87 	register struct mbuf *m;
88 	register int k, *err;
89 {
90 	register int len;
91 	register u_char *cp, *np;
92 	register struct mbuf *m0;
93 
94 	len = m->m_len;
95 	while (k >= len) {
96 		k -= len;
97 		m = m->m_next;
98 		if (m == 0)
99 			goto bad;
100 		len = m->m_len;
101 	}
102 	cp = mtod(m, u_char *) + k;
103 	if (len - k >= 4) {
104 		*err = 0;
105 		return EXTRACT_LONG(cp);
106 	}
107 	m0 = m->m_next;
108 	if (m0 == 0 || m0->m_len + len - k < 4)
109 		goto bad;
110 	*err = 0;
111 	np = mtod(m0, u_char *);
112 	switch (len - k) {
113 
114 	case 1:
115 		return (cp[k] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
116 
117 	case 2:
118 		return (cp[k] << 24) | (cp[k + 1] << 16) | (np[0] << 8) |
119 			np[1];
120 
121 	default:
122 		return (cp[k] << 24) | (cp[k + 1] << 16) | (cp[k + 2] << 8) |
123 			np[0];
124 	}
125     bad:
126 	*err = 1;
127 	return 0;
128 }
129 
130 static int
131 m_xhalf(m, k, err)
132 	register struct mbuf *m;
133 	register int k, *err;
134 {
135 	register int len;
136 	register u_char *cp;
137 	register struct mbuf *m0;
138 
139 	len = m->m_len;
140 	while (k >= len) {
141 		k -= len;
142 		m = m->m_next;
143 		if (m == 0)
144 			goto bad;
145 		len = m->m_len;
146 	}
147 	cp = mtod(m, u_char *) + k;
148 	if (len - k >= 2) {
149 		*err = 0;
150 		return EXTRACT_SHORT(cp);
151 	}
152 	m0 = m->m_next;
153 	if (m0 == 0)
154 		goto bad;
155 	*err = 0;
156 	return (cp[k] << 8) | mtod(m0, u_char *)[0];
157  bad:
158 	*err = 1;
159 	return 0;
160 }
161 #endif
162 
163 #include <net/bpf.h>
164 /*
165  * Execute the filter program starting at pc on the packet p
166  * wirelen is the length of the original packet
167  * buflen is the amount of data present
168  */
169 u_int
170 bpf_filter(pc, p, wirelen, buflen)
171 	register struct bpf_insn *pc;
172 	register u_char *p;
173 	u_int wirelen;
174 	register u_int buflen;
175 {
176 	register u_long A, X;
177 	register int k;
178 	long mem[BPF_MEMWORDS];
179 
180 	if (pc == 0)
181 		/*
182 		 * No filter means accept all.
183 		 */
184 		return (u_int)-1;
185 #ifdef lint
186 	A = 0;
187 	X = 0;
188 #endif
189 	--pc;
190 	while (1) {
191 		++pc;
192 		switch (pc->code) {
193 
194 		default:
195 #ifdef KERNEL
196 			return 0;
197 #else
198 			abort();
199 #endif
200 		case BPF_RET|BPF_K:
201 			return (u_int)pc->k;
202 
203 		case BPF_RET|BPF_A:
204 			return (u_int)A;
205 
206 		case BPF_LD|BPF_W|BPF_ABS:
207 			k = pc->k;
208 			if (k + sizeof(long) > buflen) {
209 #ifdef KERNEL
210 				int merr;
211 
212 				if (buflen != 0)
213 					return 0;
214 				A = m_xword((struct mbuf *)p, k, &merr);
215 				if (merr != 0)
216 					return 0;
217 				continue;
218 #else
219 				return 0;
220 #endif
221 			}
222 #ifdef BPF_ALIGN
223 			if (((int)(p + k) & 3) != 0)
224 				A = EXTRACT_LONG(&p[k]);
225 			else
226 #endif
227 				A = ntohl(*(long *)(p + k));
228 			continue;
229 
230 		case BPF_LD|BPF_H|BPF_ABS:
231 			k = pc->k;
232 			if (k + sizeof(short) > buflen) {
233 #ifdef KERNEL
234 				int merr;
235 
236 				if (buflen != 0)
237 					return 0;
238 				A = m_xhalf((struct mbuf *)p, k, &merr);
239 				continue;
240 #else
241 				return 0;
242 #endif
243 			}
244 			A = EXTRACT_SHORT(&p[k]);
245 			continue;
246 
247 		case BPF_LD|BPF_B|BPF_ABS:
248 			k = pc->k;
249 			if (k >= buflen) {
250 #ifdef KERNEL
251 				register struct mbuf *m;
252 
253 				if (buflen != 0)
254 					return 0;
255 				m = (struct mbuf *)p;
256 				MINDEX(m, k);
257 				A = mtod(m, u_char *)[k];
258 				continue;
259 #else
260 				return 0;
261 #endif
262 			}
263 			A = p[k];
264 			continue;
265 
266 		case BPF_LD|BPF_W|BPF_LEN:
267 			A = wirelen;
268 			continue;
269 
270 		case BPF_LDX|BPF_W|BPF_LEN:
271 			X = wirelen;
272 			continue;
273 
274 		case BPF_LD|BPF_W|BPF_IND:
275 			k = X + pc->k;
276 			if (k + sizeof(long) > buflen) {
277 #ifdef KERNEL
278 				int merr;
279 
280 				if (buflen != 0)
281 					return 0;
282 				A = m_xword((struct mbuf *)p, k, &merr);
283 				if (merr != 0)
284 					return 0;
285 				continue;
286 #else
287 				return 0;
288 #endif
289 			}
290 #ifdef BPF_ALIGN
291 			if (((int)(p + k) & 3) != 0)
292 				A = EXTRACT_LONG(&p[k]);
293 			else
294 #endif
295 				A = ntohl(*(long *)(p + k));
296 			continue;
297 
298 		case BPF_LD|BPF_H|BPF_IND:
299 			k = X + pc->k;
300 			if (k + sizeof(short) > buflen) {
301 #ifdef KERNEL
302 				int merr;
303 
304 				if (buflen != 0)
305 					return 0;
306 				A = m_xhalf((struct mbuf *)p, k, &merr);
307 				if (merr != 0)
308 					return 0;
309 				continue;
310 #else
311 				return 0;
312 #endif
313 			}
314 			A = EXTRACT_SHORT(&p[k]);
315 			continue;
316 
317 		case BPF_LD|BPF_B|BPF_IND:
318 			k = X + pc->k;
319 			if (k >= buflen) {
320 #ifdef KERNEL
321 				register struct mbuf *m;
322 
323 				if (buflen != 0)
324 					return 0;
325 				m = (struct mbuf *)p;
326 				MINDEX(m, k);
327 				A = mtod(m, char *)[k];
328 				continue;
329 #else
330 				return 0;
331 #endif
332 			}
333 			A = p[k];
334 			continue;
335 
336 		case BPF_LDX|BPF_MSH|BPF_B:
337 			k = pc->k;
338 			if (k >= buflen) {
339 #ifdef KERNEL
340 				register struct mbuf *m;
341 
342 				if (buflen != 0)
343 					return 0;
344 				m = (struct mbuf *)p;
345 				MINDEX(m, k);
346 				X = (mtod(m, char *)[k] & 0xf) << 2;
347 				continue;
348 #else
349 				return 0;
350 #endif
351 			}
352 			X = (p[pc->k] & 0xf) << 2;
353 			continue;
354 
355 		case BPF_LD|BPF_IMM:
356 			A = pc->k;
357 			continue;
358 
359 		case BPF_LDX|BPF_IMM:
360 			X = pc->k;
361 			continue;
362 
363 		case BPF_LD|BPF_MEM:
364 			A = mem[pc->k];
365 			continue;
366 
367 		case BPF_LDX|BPF_MEM:
368 			X = mem[pc->k];
369 			continue;
370 
371 		case BPF_ST:
372 			mem[pc->k] = A;
373 			continue;
374 
375 		case BPF_STX:
376 			mem[pc->k] = X;
377 			continue;
378 
379 		case BPF_JMP|BPF_JA:
380 			pc += pc->k;
381 			continue;
382 
383 		case BPF_JMP|BPF_JGT|BPF_K:
384 			pc += (A > pc->k) ? pc->jt : pc->jf;
385 			continue;
386 
387 		case BPF_JMP|BPF_JGE|BPF_K:
388 			pc += (A >= pc->k) ? pc->jt : pc->jf;
389 			continue;
390 
391 		case BPF_JMP|BPF_JEQ|BPF_K:
392 			pc += (A == pc->k) ? pc->jt : pc->jf;
393 			continue;
394 
395 		case BPF_JMP|BPF_JSET|BPF_K:
396 			pc += (A & pc->k) ? pc->jt : pc->jf;
397 			continue;
398 
399 		case BPF_JMP|BPF_JGT|BPF_X:
400 			pc += (A > X) ? pc->jt : pc->jf;
401 			continue;
402 
403 		case BPF_JMP|BPF_JGE|BPF_X:
404 			pc += (A >= X) ? pc->jt : pc->jf;
405 			continue;
406 
407 		case BPF_JMP|BPF_JEQ|BPF_X:
408 			pc += (A == X) ? pc->jt : pc->jf;
409 			continue;
410 
411 		case BPF_JMP|BPF_JSET|BPF_X:
412 			pc += (A & X) ? pc->jt : pc->jf;
413 			continue;
414 
415 		case BPF_ALU|BPF_ADD|BPF_X:
416 			A += X;
417 			continue;
418 
419 		case BPF_ALU|BPF_SUB|BPF_X:
420 			A -= X;
421 			continue;
422 
423 		case BPF_ALU|BPF_MUL|BPF_X:
424 			A *= X;
425 			continue;
426 
427 		case BPF_ALU|BPF_DIV|BPF_X:
428 			if (X == 0)
429 				return 0;
430 			A /= X;
431 			continue;
432 
433 		case BPF_ALU|BPF_AND|BPF_X:
434 			A &= X;
435 			continue;
436 
437 		case BPF_ALU|BPF_OR|BPF_X:
438 			A |= X;
439 			continue;
440 
441 		case BPF_ALU|BPF_LSH|BPF_X:
442 			A <<= X;
443 			continue;
444 
445 		case BPF_ALU|BPF_RSH|BPF_X:
446 			A >>= X;
447 			continue;
448 
449 		case BPF_ALU|BPF_ADD|BPF_K:
450 			A += pc->k;
451 			continue;
452 
453 		case BPF_ALU|BPF_SUB|BPF_K:
454 			A -= pc->k;
455 			continue;
456 
457 		case BPF_ALU|BPF_MUL|BPF_K:
458 			A *= pc->k;
459 			continue;
460 
461 		case BPF_ALU|BPF_DIV|BPF_K:
462 			A /= pc->k;
463 			continue;
464 
465 		case BPF_ALU|BPF_AND|BPF_K:
466 			A &= pc->k;
467 			continue;
468 
469 		case BPF_ALU|BPF_OR|BPF_K:
470 			A |= pc->k;
471 			continue;
472 
473 		case BPF_ALU|BPF_LSH|BPF_K:
474 			A <<= pc->k;
475 			continue;
476 
477 		case BPF_ALU|BPF_RSH|BPF_K:
478 			A >>= pc->k;
479 			continue;
480 
481 		case BPF_ALU|BPF_NEG:
482 			A = -A;
483 			continue;
484 
485 		case BPF_MISC|BPF_TAX:
486 			X = A;
487 			continue;
488 
489 		case BPF_MISC|BPF_TXA:
490 			A = X;
491 			continue;
492 		}
493 	}
494 }
495 
496 #ifdef KERNEL
497 /*
498  * Return true if the 'fcode' is a valid filter program.
499  * The constraints are that each jump be forward and to a valid
500  * code.  The code must terminate with either an accept or reject.
501  * 'valid' is an array for use by the routine (it must be at least
502  * 'len' bytes long).
503  *
504  * The kernel needs to be able to verify an application's filter code.
505  * Otherwise, a bogus program could easily crash the system.
506  */
507 int
508 bpf_validate(f, len)
509 	struct bpf_insn *f;
510 	int len;
511 {
512 	register int i;
513 	register struct bpf_insn *p;
514 
515 	for (i = 0; i < len; ++i) {
516 		/*
517 		 * Check that that jumps are forward, and within
518 		 * the code block.
519 		 */
520 		p = &f[i];
521 		if (BPF_CLASS(p->code) == BPF_JMP) {
522 			register int from = i + 1;
523 
524 			if (BPF_OP(p->code) == BPF_JA) {
525 				if (from + p->k >= len)
526 					return 0;
527 			}
528 			else if (from + p->jt >= len || from + p->jf >= len)
529 				return 0;
530 		}
531 		/*
532 		 * Check that memory operations use valid addresses.
533 		 */
534 		if ((BPF_CLASS(p->code) == BPF_ST ||
535 		     (BPF_CLASS(p->code) == BPF_LD &&
536 		      (p->code & 0xe0) == BPF_MEM)) &&
537 		    (p->k >= BPF_MEMWORDS || p->k < 0))
538 			return 0;
539 		/*
540 		 * Check for constant division by 0.
541 		 */
542 		if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
543 			return 0;
544 	}
545 	return BPF_CLASS(f[len - 1].code) == BPF_RET;
546 }
547 #endif
548