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