bpf_filter.c revision 182454
1139823Simp/*-
21541Srgrimes * Copyright (c) 1990, 1991, 1993
31541Srgrimes *	The Regents of the University of California.  All rights reserved.
41541Srgrimes *
51541Srgrimes * This code is derived from the Stanford/CMU enet packet filter,
61541Srgrimes * (net/enet.c) distributed as part of 4.3BSD, and code contributed
71541Srgrimes * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
81541Srgrimes * Berkeley Laboratory.
91541Srgrimes *
101541Srgrimes * Redistribution and use in source and binary forms, with or without
111541Srgrimes * modification, are permitted provided that the following conditions
121541Srgrimes * are met:
131541Srgrimes * 1. Redistributions of source code must retain the above copyright
141541Srgrimes *    notice, this list of conditions and the following disclaimer.
151541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
161541Srgrimes *    notice, this list of conditions and the following disclaimer in the
171541Srgrimes *    documentation and/or other materials provided with the distribution.
181541Srgrimes * 4. Neither the name of the University nor the names of its contributors
191541Srgrimes *    may be used to endorse or promote products derived from this software
201541Srgrimes *    without specific prior written permission.
211541Srgrimes *
221541Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
231541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
241541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
251541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
261541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
271541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
281541Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
291541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
301541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
311541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
321541Srgrimes * SUCH DAMAGE.
331541Srgrimes *
341541Srgrimes *      @(#)bpf_filter.c	8.1 (Berkeley) 6/10/93
351541Srgrimes */
361541Srgrimes
37174895Srwatson#include <sys/cdefs.h>
38174895Srwatson__FBSDID("$FreeBSD: head/sys/net/bpf_filter.c 182454 2008-08-29 19:10:51Z jkim $");
39174895Srwatson
401541Srgrimes#include <sys/param.h>
411541Srgrimes
42182184Sjkim#if !defined(_KERNEL) || defined(sun)
431541Srgrimes#include <netinet/in.h>
441541Srgrimes#endif
451541Srgrimes
4699419Speter#ifndef __i386__
471541Srgrimes#define BPF_ALIGN
481541Srgrimes#endif
491541Srgrimes
501541Srgrimes#ifndef BPF_ALIGN
5140779Sdfr#define EXTRACT_SHORT(p)	((u_int16_t)ntohs(*(u_int16_t *)p))
5240779Sdfr#define EXTRACT_LONG(p)		(ntohl(*(u_int32_t *)p))
531541Srgrimes#else
541541Srgrimes#define EXTRACT_SHORT(p)\
5540779Sdfr	((u_int16_t)\
5640779Sdfr		((u_int16_t)*((u_char *)p+0)<<8|\
5740779Sdfr		 (u_int16_t)*((u_char *)p+1)<<0))
581541Srgrimes#define EXTRACT_LONG(p)\
5940779Sdfr		((u_int32_t)*((u_char *)p+0)<<24|\
6040779Sdfr		 (u_int32_t)*((u_char *)p+1)<<16|\
6140779Sdfr		 (u_int32_t)*((u_char *)p+2)<<8|\
6240779Sdfr		 (u_int32_t)*((u_char *)p+3)<<0)
631541Srgrimes#endif
641541Srgrimes
6555205Speter#ifdef _KERNEL
661541Srgrimes#include <sys/mbuf.h>
67182184Sjkim#else
68182184Sjkim#include <stdlib.h>
6941588Seivind#endif
7041588Seivind#include <net/bpf.h>
7155205Speter#ifdef _KERNEL
721541Srgrimes#define MINDEX(m, k) \
731541Srgrimes{ \
741541Srgrimes	register int len = m->m_len; \
751541Srgrimes \
761541Srgrimes	while (k >= len) { \
771541Srgrimes		k -= len; \
781541Srgrimes		m = m->m_next; \
791541Srgrimes		if (m == 0) \
801541Srgrimes			return 0; \
811541Srgrimes		len = m->m_len; \
821541Srgrimes	} \
831541Srgrimes}
841541Srgrimes
8592725Salfredstatic u_int16_t	m_xhalf(struct mbuf *m, bpf_u_int32 k, int *err);
8692725Salfredstatic u_int32_t	m_xword(struct mbuf *m, bpf_u_int32 k, int *err);
8712579Sbde
8841588Seivindstatic u_int32_t
89177003Srwatsonm_xword(struct mbuf *m, bpf_u_int32 k, int *err)
901541Srgrimes{
91177003Srwatson	size_t len;
92177003Srwatson	u_char *cp, *np;
93177003Srwatson	struct mbuf *m0;
941541Srgrimes
951541Srgrimes	len = m->m_len;
961541Srgrimes	while (k >= len) {
971541Srgrimes		k -= len;
981541Srgrimes		m = m->m_next;
991541Srgrimes		if (m == 0)
1001541Srgrimes			goto bad;
1011541Srgrimes		len = m->m_len;
1021541Srgrimes	}
1031541Srgrimes	cp = mtod(m, u_char *) + k;
1041541Srgrimes	if (len - k >= 4) {
1051541Srgrimes		*err = 0;
1061541Srgrimes		return EXTRACT_LONG(cp);
1071541Srgrimes	}
1081541Srgrimes	m0 = m->m_next;
1091541Srgrimes	if (m0 == 0 || m0->m_len + len - k < 4)
1101541Srgrimes		goto bad;
1111541Srgrimes	*err = 0;
1121541Srgrimes	np = mtod(m0, u_char *);
1131541Srgrimes	switch (len - k) {
1141541Srgrimes	case 1:
11541588Seivind		return
11641588Seivind		    ((u_int32_t)cp[0] << 24) |
11741588Seivind		    ((u_int32_t)np[0] << 16) |
11841588Seivind		    ((u_int32_t)np[1] << 8)  |
11941588Seivind		    (u_int32_t)np[2];
1201541Srgrimes
1211541Srgrimes	case 2:
12241588Seivind		return
12341588Seivind		    ((u_int32_t)cp[0] << 24) |
12441588Seivind		    ((u_int32_t)cp[1] << 16) |
12541588Seivind		    ((u_int32_t)np[0] << 8) |
12641588Seivind		    (u_int32_t)np[1];
1271541Srgrimes
1281541Srgrimes	default:
12941588Seivind		return
13041588Seivind		    ((u_int32_t)cp[0] << 24) |
13141588Seivind		    ((u_int32_t)cp[1] << 16) |
13241588Seivind		    ((u_int32_t)cp[2] << 8) |
13341588Seivind		    (u_int32_t)np[0];
1341541Srgrimes	}
1351541Srgrimes    bad:
1361541Srgrimes	*err = 1;
137177003Srwatson	return (0);
1381541Srgrimes}
1391541Srgrimes
14041588Seivindstatic u_int16_t
141177003Srwatsonm_xhalf(struct mbuf *m, bpf_u_int32 k, int *err)
1421541Srgrimes{
143177003Srwatson	size_t len;
144177003Srwatson	u_char *cp;
145177003Srwatson	struct mbuf *m0;
1461541Srgrimes
1471541Srgrimes	len = m->m_len;
1481541Srgrimes	while (k >= len) {
1491541Srgrimes		k -= len;
1501541Srgrimes		m = m->m_next;
1511541Srgrimes		if (m == 0)
1521541Srgrimes			goto bad;
1531541Srgrimes		len = m->m_len;
1541541Srgrimes	}
1551541Srgrimes	cp = mtod(m, u_char *) + k;
1561541Srgrimes	if (len - k >= 2) {
1571541Srgrimes		*err = 0;
158177003Srwatson		return (EXTRACT_SHORT(cp));
1591541Srgrimes	}
1601541Srgrimes	m0 = m->m_next;
1611541Srgrimes	if (m0 == 0)
1621541Srgrimes		goto bad;
1631541Srgrimes	*err = 0;
164177003Srwatson	return ((cp[0] << 8) | mtod(m0, u_char *)[0]);
1651541Srgrimes bad:
1661541Srgrimes	*err = 1;
167177003Srwatson	return (0);
1681541Srgrimes}
1691541Srgrimes#endif
1701541Srgrimes
1711541Srgrimes/*
1721541Srgrimes * Execute the filter program starting at pc on the packet p
1731541Srgrimes * wirelen is the length of the original packet
1741541Srgrimes * buflen is the amount of data present
1751541Srgrimes */
1761541Srgrimesu_int
177177003Srwatsonbpf_filter(const struct bpf_insn *pc, u_char *p, u_int wirelen, u_int buflen)
1781541Srgrimes{
179177003Srwatson	u_int32_t A = 0, X = 0;
180177003Srwatson	bpf_u_int32 k;
181172154Sdwmalone	u_int32_t mem[BPF_MEMWORDS];
1821541Srgrimes
183177003Srwatson	if (pc == NULL)
1841541Srgrimes		/*
1851541Srgrimes		 * No filter means accept all.
1861541Srgrimes		 */
187177003Srwatson		return ((u_int)-1);
1881549Srgrimes
1891541Srgrimes	--pc;
1901541Srgrimes	while (1) {
1911541Srgrimes		++pc;
1921541Srgrimes		switch (pc->code) {
1931541Srgrimes		default:
19455205Speter#ifdef _KERNEL
1951541Srgrimes			return 0;
1961541Srgrimes#else
1971541Srgrimes			abort();
1988876Srgrimes#endif
199177003Srwatson
2001541Srgrimes		case BPF_RET|BPF_K:
201177003Srwatson			return ((u_int)pc->k);
2021541Srgrimes
2031541Srgrimes		case BPF_RET|BPF_A:
204177003Srwatson			return ((u_int)A);
2051541Srgrimes
2061541Srgrimes		case BPF_LD|BPF_W|BPF_ABS:
2071541Srgrimes			k = pc->k;
20841588Seivind			if (k > buflen || sizeof(int32_t) > buflen - k) {
20955205Speter#ifdef _KERNEL
2101541Srgrimes				int merr;
2111541Srgrimes
2121541Srgrimes				if (buflen != 0)
2131541Srgrimes					return 0;
2141541Srgrimes				A = m_xword((struct mbuf *)p, k, &merr);
2151541Srgrimes				if (merr != 0)
2161541Srgrimes					return 0;
2171541Srgrimes				continue;
2181541Srgrimes#else
219177003Srwatson				return (0);
2201541Srgrimes#endif
2211541Srgrimes			}
2221541Srgrimes#ifdef BPF_ALIGN
22340779Sdfr			if (((intptr_t)(p + k) & 3) != 0)
2241541Srgrimes				A = EXTRACT_LONG(&p[k]);
2251541Srgrimes			else
2261541Srgrimes#endif
22740779Sdfr				A = ntohl(*(int32_t *)(p + k));
2281541Srgrimes			continue;
2291541Srgrimes
2301541Srgrimes		case BPF_LD|BPF_H|BPF_ABS:
2311541Srgrimes			k = pc->k;
23241588Seivind			if (k > buflen || sizeof(int16_t) > buflen - k) {
23355205Speter#ifdef _KERNEL
2341541Srgrimes				int merr;
2351541Srgrimes
2361541Srgrimes				if (buflen != 0)
2371541Srgrimes					return 0;
2381541Srgrimes				A = m_xhalf((struct mbuf *)p, k, &merr);
2391541Srgrimes				continue;
2401541Srgrimes#else
2411541Srgrimes				return 0;
2421541Srgrimes#endif
2431541Srgrimes			}
2441541Srgrimes			A = EXTRACT_SHORT(&p[k]);
2451541Srgrimes			continue;
2461541Srgrimes
2471541Srgrimes		case BPF_LD|BPF_B|BPF_ABS:
2481541Srgrimes			k = pc->k;
2491541Srgrimes			if (k >= buflen) {
25055205Speter#ifdef _KERNEL
251177003Srwatson				struct mbuf *m;
2521541Srgrimes
2531541Srgrimes				if (buflen != 0)
2541541Srgrimes					return 0;
2551541Srgrimes				m = (struct mbuf *)p;
2561541Srgrimes				MINDEX(m, k);
2571541Srgrimes				A = mtod(m, u_char *)[k];
2581541Srgrimes				continue;
2591541Srgrimes#else
2601541Srgrimes				return 0;
2611541Srgrimes#endif
2621541Srgrimes			}
2631541Srgrimes			A = p[k];
2641541Srgrimes			continue;
2651541Srgrimes
2661541Srgrimes		case BPF_LD|BPF_W|BPF_LEN:
2671541Srgrimes			A = wirelen;
2681541Srgrimes			continue;
2691541Srgrimes
2701541Srgrimes		case BPF_LDX|BPF_W|BPF_LEN:
2711541Srgrimes			X = wirelen;
2721541Srgrimes			continue;
2731541Srgrimes
2741541Srgrimes		case BPF_LD|BPF_W|BPF_IND:
2751541Srgrimes			k = X + pc->k;
27645574Seivind			if (pc->k > buflen || X > buflen - pc->k ||
27745574Seivind			    sizeof(int32_t) > buflen - k) {
27855205Speter#ifdef _KERNEL
2791541Srgrimes				int merr;
2801541Srgrimes
2811541Srgrimes				if (buflen != 0)
282177003Srwatson					return (0);
2831541Srgrimes				A = m_xword((struct mbuf *)p, k, &merr);
2841541Srgrimes				if (merr != 0)
285177003Srwatson					return (0);
2861541Srgrimes				continue;
2871541Srgrimes#else
288177003Srwatson				return (0);
2891541Srgrimes#endif
2901541Srgrimes			}
2911541Srgrimes#ifdef BPF_ALIGN
29240779Sdfr			if (((intptr_t)(p + k) & 3) != 0)
2931541Srgrimes				A = EXTRACT_LONG(&p[k]);
2941541Srgrimes			else
2951541Srgrimes#endif
29640779Sdfr				A = ntohl(*(int32_t *)(p + k));
2971541Srgrimes			continue;
2981541Srgrimes
2991541Srgrimes		case BPF_LD|BPF_H|BPF_IND:
3001541Srgrimes			k = X + pc->k;
30145574Seivind			if (X > buflen || pc->k > buflen - X ||
30245574Seivind			    sizeof(int16_t) > buflen - k) {
30355205Speter#ifdef _KERNEL
3041541Srgrimes				int merr;
3051541Srgrimes
3061541Srgrimes				if (buflen != 0)
3071541Srgrimes					return 0;
3081541Srgrimes				A = m_xhalf((struct mbuf *)p, k, &merr);
3091541Srgrimes				if (merr != 0)
310177003Srwatson					return (0);
3111541Srgrimes				continue;
3121541Srgrimes#else
313177003Srwatson				return (0);
3141541Srgrimes#endif
3151541Srgrimes			}
3161541Srgrimes			A = EXTRACT_SHORT(&p[k]);
3171541Srgrimes			continue;
3181541Srgrimes
3191541Srgrimes		case BPF_LD|BPF_B|BPF_IND:
3201541Srgrimes			k = X + pc->k;
32148548Sbde			if (pc->k >= buflen || X >= buflen - pc->k) {
32255205Speter#ifdef _KERNEL
323177003Srwatson				struct mbuf *m;
3241541Srgrimes
3251541Srgrimes				if (buflen != 0)
3261541Srgrimes					return 0;
3271541Srgrimes				m = (struct mbuf *)p;
3281541Srgrimes				MINDEX(m, k);
329159018Sdwmalone				A = mtod(m, u_char *)[k];
3301541Srgrimes				continue;
3311541Srgrimes#else
332177003Srwatson				return (0);
3331541Srgrimes#endif
3341541Srgrimes			}
3351541Srgrimes			A = p[k];
3361541Srgrimes			continue;
3371541Srgrimes
3381541Srgrimes		case BPF_LDX|BPF_MSH|BPF_B:
3391541Srgrimes			k = pc->k;
3401541Srgrimes			if (k >= buflen) {
34155205Speter#ifdef _KERNEL
3421541Srgrimes				register struct mbuf *m;
3431541Srgrimes
3441541Srgrimes				if (buflen != 0)
3451541Srgrimes					return 0;
3461541Srgrimes				m = (struct mbuf *)p;
3471541Srgrimes				MINDEX(m, k);
348159018Sdwmalone				X = (mtod(m, u_char *)[k] & 0xf) << 2;
3491541Srgrimes				continue;
3501541Srgrimes#else
3511541Srgrimes				return 0;
3521541Srgrimes#endif
3531541Srgrimes			}
3541541Srgrimes			X = (p[pc->k] & 0xf) << 2;
3551541Srgrimes			continue;
3561541Srgrimes
3571541Srgrimes		case BPF_LD|BPF_IMM:
3581541Srgrimes			A = pc->k;
3591541Srgrimes			continue;
3601541Srgrimes
3611541Srgrimes		case BPF_LDX|BPF_IMM:
3621541Srgrimes			X = pc->k;
3631541Srgrimes			continue;
3641541Srgrimes
3651541Srgrimes		case BPF_LD|BPF_MEM:
3661541Srgrimes			A = mem[pc->k];
3671541Srgrimes			continue;
3688876Srgrimes
3691541Srgrimes		case BPF_LDX|BPF_MEM:
3701541Srgrimes			X = mem[pc->k];
3711541Srgrimes			continue;
3721541Srgrimes
3731541Srgrimes		case BPF_ST:
3741541Srgrimes			mem[pc->k] = A;
3751541Srgrimes			continue;
3761541Srgrimes
3771541Srgrimes		case BPF_STX:
3781541Srgrimes			mem[pc->k] = X;
3791541Srgrimes			continue;
3801541Srgrimes
3811541Srgrimes		case BPF_JMP|BPF_JA:
3821541Srgrimes			pc += pc->k;
3831541Srgrimes			continue;
3841541Srgrimes
3851541Srgrimes		case BPF_JMP|BPF_JGT|BPF_K:
3861541Srgrimes			pc += (A > pc->k) ? pc->jt : pc->jf;
3871541Srgrimes			continue;
3881541Srgrimes
3891541Srgrimes		case BPF_JMP|BPF_JGE|BPF_K:
3901541Srgrimes			pc += (A >= pc->k) ? pc->jt : pc->jf;
3911541Srgrimes			continue;
3921541Srgrimes
3931541Srgrimes		case BPF_JMP|BPF_JEQ|BPF_K:
3941541Srgrimes			pc += (A == pc->k) ? pc->jt : pc->jf;
3951541Srgrimes			continue;
3961541Srgrimes
3971541Srgrimes		case BPF_JMP|BPF_JSET|BPF_K:
3981541Srgrimes			pc += (A & pc->k) ? pc->jt : pc->jf;
3991541Srgrimes			continue;
4001541Srgrimes
4011541Srgrimes		case BPF_JMP|BPF_JGT|BPF_X:
4021541Srgrimes			pc += (A > X) ? pc->jt : pc->jf;
4031541Srgrimes			continue;
4041541Srgrimes
4051541Srgrimes		case BPF_JMP|BPF_JGE|BPF_X:
4061541Srgrimes			pc += (A >= X) ? pc->jt : pc->jf;
4071541Srgrimes			continue;
4081541Srgrimes
4091541Srgrimes		case BPF_JMP|BPF_JEQ|BPF_X:
4101541Srgrimes			pc += (A == X) ? pc->jt : pc->jf;
4111541Srgrimes			continue;
4121541Srgrimes
4131541Srgrimes		case BPF_JMP|BPF_JSET|BPF_X:
4141541Srgrimes			pc += (A & X) ? pc->jt : pc->jf;
4151541Srgrimes			continue;
4161541Srgrimes
4171541Srgrimes		case BPF_ALU|BPF_ADD|BPF_X:
4181541Srgrimes			A += X;
4191541Srgrimes			continue;
4208876Srgrimes
4211541Srgrimes		case BPF_ALU|BPF_SUB|BPF_X:
4221541Srgrimes			A -= X;
4231541Srgrimes			continue;
4248876Srgrimes
4251541Srgrimes		case BPF_ALU|BPF_MUL|BPF_X:
4261541Srgrimes			A *= X;
4271541Srgrimes			continue;
4288876Srgrimes
4291541Srgrimes		case BPF_ALU|BPF_DIV|BPF_X:
4301541Srgrimes			if (X == 0)
4311541Srgrimes				return 0;
4321541Srgrimes			A /= X;
4331541Srgrimes			continue;
4348876Srgrimes
4351541Srgrimes		case BPF_ALU|BPF_AND|BPF_X:
4361541Srgrimes			A &= X;
4371541Srgrimes			continue;
4388876Srgrimes
4391541Srgrimes		case BPF_ALU|BPF_OR|BPF_X:
4401541Srgrimes			A |= X;
4411541Srgrimes			continue;
4421541Srgrimes
4431541Srgrimes		case BPF_ALU|BPF_LSH|BPF_X:
4441541Srgrimes			A <<= X;
4451541Srgrimes			continue;
4461541Srgrimes
4471541Srgrimes		case BPF_ALU|BPF_RSH|BPF_X:
4481541Srgrimes			A >>= X;
4491541Srgrimes			continue;
4501541Srgrimes
4511541Srgrimes		case BPF_ALU|BPF_ADD|BPF_K:
4521541Srgrimes			A += pc->k;
4531541Srgrimes			continue;
4548876Srgrimes
4551541Srgrimes		case BPF_ALU|BPF_SUB|BPF_K:
4561541Srgrimes			A -= pc->k;
4571541Srgrimes			continue;
4588876Srgrimes
4591541Srgrimes		case BPF_ALU|BPF_MUL|BPF_K:
4601541Srgrimes			A *= pc->k;
4611541Srgrimes			continue;
4628876Srgrimes
4631541Srgrimes		case BPF_ALU|BPF_DIV|BPF_K:
4641541Srgrimes			A /= pc->k;
4651541Srgrimes			continue;
4668876Srgrimes
4671541Srgrimes		case BPF_ALU|BPF_AND|BPF_K:
4681541Srgrimes			A &= pc->k;
4691541Srgrimes			continue;
4708876Srgrimes
4711541Srgrimes		case BPF_ALU|BPF_OR|BPF_K:
4721541Srgrimes			A |= pc->k;
4731541Srgrimes			continue;
4741541Srgrimes
4751541Srgrimes		case BPF_ALU|BPF_LSH|BPF_K:
4761541Srgrimes			A <<= pc->k;
4771541Srgrimes			continue;
4781541Srgrimes
4791541Srgrimes		case BPF_ALU|BPF_RSH|BPF_K:
4801541Srgrimes			A >>= pc->k;
4811541Srgrimes			continue;
4821541Srgrimes
4831541Srgrimes		case BPF_ALU|BPF_NEG:
4841541Srgrimes			A = -A;
4851541Srgrimes			continue;
4861541Srgrimes
4871541Srgrimes		case BPF_MISC|BPF_TAX:
4881541Srgrimes			X = A;
4891541Srgrimes			continue;
4901541Srgrimes
4911541Srgrimes		case BPF_MISC|BPF_TXA:
4921541Srgrimes			A = X;
4931541Srgrimes			continue;
4941541Srgrimes		}
4951541Srgrimes	}
4961541Srgrimes}
4971541Srgrimes
49855205Speter#ifdef _KERNEL
499182454Sjkimstatic const u_short	bpf_code_map[] = {
500182412Sjkim	0x10ff,	/* 0x00-0x0f: 1111111100001000 */
501182412Sjkim	0x3070,	/* 0x10-0x1f: 0000111000001100 */
502182412Sjkim	0x3131,	/* 0x20-0x2f: 1000110010001100 */
503182412Sjkim	0x3031,	/* 0x30-0x3f: 1000110000001100 */
504182412Sjkim	0x3131,	/* 0x40-0x4f: 1000110010001100 */
505182412Sjkim	0x1011,	/* 0x50-0x5f: 1000100000001000 */
506182412Sjkim	0x1013,	/* 0x60-0x6f: 1100100000001000 */
507182412Sjkim	0x1010,	/* 0x70-0x7f: 0000100000001000 */
508182412Sjkim	0x0093,	/* 0x80-0x8f: 1100100100000000 */
509182412Sjkim	0x0000,	/* 0x90-0x9f: 0000000000000000 */
510182412Sjkim	0x0000,	/* 0xa0-0xaf: 0000000000000000 */
511182412Sjkim	0x0002,	/* 0xb0-0xbf: 0100000000000000 */
512182412Sjkim	0x0000,	/* 0xc0-0xcf: 0000000000000000 */
513182412Sjkim	0x0000,	/* 0xd0-0xdf: 0000000000000000 */
514182412Sjkim	0x0000,	/* 0xe0-0xef: 0000000000000000 */
515182412Sjkim	0x0000	/* 0xf0-0xff: 0000000000000000 */
516182412Sjkim};
517182412Sjkim
518182454Sjkim#define	BPF_VALIDATE_CODE(c)	\
519182454Sjkim    ((c) <= 0xff && (bpf_code_map[(c) >> 4] & (1 << ((c) & 0xf))) != 0)
520182454Sjkim
5211541Srgrimes/*
5221541Srgrimes * Return true if the 'fcode' is a valid filter program.
5231541Srgrimes * The constraints are that each jump be forward and to a valid
5248876Srgrimes * code.  The code must terminate with either an accept or reject.
5251541Srgrimes *
5261541Srgrimes * The kernel needs to be able to verify an application's filter code.
5271541Srgrimes * Otherwise, a bogus program could easily crash the system.
5281541Srgrimes */
5291541Srgrimesint
5301541Srgrimesbpf_validate(f, len)
53154038Sarchie	const struct bpf_insn *f;
5321541Srgrimes	int len;
5331541Srgrimes{
5341541Srgrimes	register int i;
53554038Sarchie	register const struct bpf_insn *p;
5361541Srgrimes
537153996Sjkim	/* Do not accept negative length filter. */
538153996Sjkim	if (len < 0)
539153996Sjkim		return 0;
540153996Sjkim
541153996Sjkim	/* An empty filter means accept all. */
542153996Sjkim	if (len == 0)
543153995Sjkim		return 1;
544153221Sjkim
5451541Srgrimes	for (i = 0; i < len; ++i) {
546182412Sjkim		p = &f[i];
5471541Srgrimes		/*
548182412Sjkim		 * Check that the code is valid.
549182412Sjkim		 */
550182454Sjkim		if (!BPF_VALIDATE_CODE(p->code))
551182412Sjkim			return 0;
552182412Sjkim		/*
5538876Srgrimes		 * Check that that jumps are forward, and within
5541541Srgrimes		 * the code block.
5551541Srgrimes		 */
5561541Srgrimes		if (BPF_CLASS(p->code) == BPF_JMP) {
557182425Sjkim			register u_int offset;
5581541Srgrimes
559182454Sjkim			if (p->code == (BPF_JMP|BPF_JA))
560182425Sjkim				offset = p->k;
561182425Sjkim			else
562182425Sjkim				offset = p->jt > p->jf ? p->jt : p->jf;
563182425Sjkim			if (offset >= (u_int)(len - i) - 1)
5641541Srgrimes				return 0;
565182454Sjkim			continue;
5661541Srgrimes		}
5671541Srgrimes		/*
5681541Srgrimes		 * Check that memory operations use valid addresses.
5691541Srgrimes		 */
570182454Sjkim		if (p->code == BPF_ST || p->code == BPF_STX ||
571182454Sjkim		    p->code == (BPF_LD|BPF_MEM) ||
572182454Sjkim		    p->code == (BPF_LDX|BPF_MEM)) {
573182454Sjkim			if (p->k >= BPF_MEMWORDS)
574182454Sjkim				return 0;
575182454Sjkim			continue;
576182454Sjkim		}
5771541Srgrimes		/*
5781541Srgrimes		 * Check for constant division by 0.
5791541Srgrimes		 */
5801541Srgrimes		if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
5811541Srgrimes			return 0;
5821541Srgrimes	}
5831541Srgrimes	return BPF_CLASS(f[len - 1].code) == BPF_RET;
5841541Srgrimes}
5851541Srgrimes#endif
586