bpf_filter.c revision 174895
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 174895 2007-12-25 13:24:02Z rwatson $");
39174895Srwatson
401541Srgrimes#include <sys/param.h>
411541Srgrimes
421541Srgrimes#ifdef 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>
6741588Seivind#endif
6841588Seivind#include <net/bpf.h>
6955205Speter#ifdef _KERNEL
701541Srgrimes#define MINDEX(m, k) \
711541Srgrimes{ \
721541Srgrimes	register int len = m->m_len; \
731541Srgrimes \
741541Srgrimes	while (k >= len) { \
751541Srgrimes		k -= len; \
761541Srgrimes		m = m->m_next; \
771541Srgrimes		if (m == 0) \
781541Srgrimes			return 0; \
791541Srgrimes		len = m->m_len; \
801541Srgrimes	} \
811541Srgrimes}
821541Srgrimes
8392725Salfredstatic u_int16_t	m_xhalf(struct mbuf *m, bpf_u_int32 k, int *err);
8492725Salfredstatic u_int32_t	m_xword(struct mbuf *m, bpf_u_int32 k, int *err);
8512579Sbde
8641588Seivindstatic u_int32_t
871541Srgrimesm_xword(m, k, err)
881541Srgrimes	register struct mbuf *m;
8941588Seivind	register bpf_u_int32 k;
9041588Seivind	register int *err;
911541Srgrimes{
9241588Seivind	register size_t len;
931541Srgrimes	register u_char *cp, *np;
941541Srgrimes	register struct mbuf *m0;
951541Srgrimes
961541Srgrimes	len = m->m_len;
971541Srgrimes	while (k >= len) {
981541Srgrimes		k -= len;
991541Srgrimes		m = m->m_next;
1001541Srgrimes		if (m == 0)
1011541Srgrimes			goto bad;
1021541Srgrimes		len = m->m_len;
1031541Srgrimes	}
1041541Srgrimes	cp = mtod(m, u_char *) + k;
1051541Srgrimes	if (len - k >= 4) {
1061541Srgrimes		*err = 0;
1071541Srgrimes		return EXTRACT_LONG(cp);
1081541Srgrimes	}
1091541Srgrimes	m0 = m->m_next;
1101541Srgrimes	if (m0 == 0 || m0->m_len + len - k < 4)
1111541Srgrimes		goto bad;
1121541Srgrimes	*err = 0;
1131541Srgrimes	np = mtod(m0, u_char *);
1141541Srgrimes	switch (len - k) {
1151541Srgrimes
1161541Srgrimes	case 1:
11741588Seivind		return
11841588Seivind		    ((u_int32_t)cp[0] << 24) |
11941588Seivind		    ((u_int32_t)np[0] << 16) |
12041588Seivind		    ((u_int32_t)np[1] << 8)  |
12141588Seivind		    (u_int32_t)np[2];
1221541Srgrimes
1231541Srgrimes	case 2:
12441588Seivind		return
12541588Seivind		    ((u_int32_t)cp[0] << 24) |
12641588Seivind		    ((u_int32_t)cp[1] << 16) |
12741588Seivind		    ((u_int32_t)np[0] << 8) |
12841588Seivind		    (u_int32_t)np[1];
1291541Srgrimes
1301541Srgrimes	default:
13141588Seivind		return
13241588Seivind		    ((u_int32_t)cp[0] << 24) |
13341588Seivind		    ((u_int32_t)cp[1] << 16) |
13441588Seivind		    ((u_int32_t)cp[2] << 8) |
13541588Seivind		    (u_int32_t)np[0];
1361541Srgrimes	}
1371541Srgrimes    bad:
1381541Srgrimes	*err = 1;
1391541Srgrimes	return 0;
1401541Srgrimes}
1411541Srgrimes
14241588Seivindstatic u_int16_t
1431541Srgrimesm_xhalf(m, k, err)
1441541Srgrimes	register struct mbuf *m;
14541588Seivind	register bpf_u_int32 k;
14641588Seivind	register int *err;
1471541Srgrimes{
14841588Seivind	register size_t len;
1491541Srgrimes	register u_char *cp;
1501541Srgrimes	register struct mbuf *m0;
1511541Srgrimes
1521541Srgrimes	len = m->m_len;
1531541Srgrimes	while (k >= len) {
1541541Srgrimes		k -= len;
1551541Srgrimes		m = m->m_next;
1561541Srgrimes		if (m == 0)
1571541Srgrimes			goto bad;
1581541Srgrimes		len = m->m_len;
1591541Srgrimes	}
1601541Srgrimes	cp = mtod(m, u_char *) + k;
1611541Srgrimes	if (len - k >= 2) {
1621541Srgrimes		*err = 0;
1631541Srgrimes		return EXTRACT_SHORT(cp);
1641541Srgrimes	}
1651541Srgrimes	m0 = m->m_next;
1661541Srgrimes	if (m0 == 0)
1671541Srgrimes		goto bad;
1681541Srgrimes	*err = 0;
1697543Sdg	return (cp[0] << 8) | mtod(m0, u_char *)[0];
1701541Srgrimes bad:
1711541Srgrimes	*err = 1;
1721541Srgrimes	return 0;
1731541Srgrimes}
1741541Srgrimes#endif
1751541Srgrimes
1761541Srgrimes/*
1771541Srgrimes * Execute the filter program starting at pc on the packet p
1781541Srgrimes * wirelen is the length of the original packet
1791541Srgrimes * buflen is the amount of data present
1801541Srgrimes */
1811541Srgrimesu_int
1821541Srgrimesbpf_filter(pc, p, wirelen, buflen)
18354038Sarchie	register const struct bpf_insn *pc;
1841541Srgrimes	register u_char *p;
1851541Srgrimes	u_int wirelen;
1861541Srgrimes	register u_int buflen;
1871541Srgrimes{
18840779Sdfr	register u_int32_t A = 0, X = 0;
18941588Seivind	register bpf_u_int32 k;
190172154Sdwmalone	u_int32_t mem[BPF_MEMWORDS];
1911541Srgrimes
1921541Srgrimes	if (pc == 0)
1931541Srgrimes		/*
1941541Srgrimes		 * No filter means accept all.
1951541Srgrimes		 */
1961541Srgrimes		return (u_int)-1;
1971549Srgrimes
1981541Srgrimes	--pc;
1991541Srgrimes	while (1) {
2001541Srgrimes		++pc;
2011541Srgrimes		switch (pc->code) {
2021541Srgrimes
2031541Srgrimes		default:
20455205Speter#ifdef _KERNEL
2051541Srgrimes			return 0;
2061541Srgrimes#else
2071541Srgrimes			abort();
2088876Srgrimes#endif
2091541Srgrimes		case BPF_RET|BPF_K:
2101541Srgrimes			return (u_int)pc->k;
2111541Srgrimes
2121541Srgrimes		case BPF_RET|BPF_A:
2131541Srgrimes			return (u_int)A;
2141541Srgrimes
2151541Srgrimes		case BPF_LD|BPF_W|BPF_ABS:
2161541Srgrimes			k = pc->k;
21741588Seivind			if (k > buflen || sizeof(int32_t) > buflen - k) {
21855205Speter#ifdef _KERNEL
2191541Srgrimes				int merr;
2201541Srgrimes
2211541Srgrimes				if (buflen != 0)
2221541Srgrimes					return 0;
2231541Srgrimes				A = m_xword((struct mbuf *)p, k, &merr);
2241541Srgrimes				if (merr != 0)
2251541Srgrimes					return 0;
2261541Srgrimes				continue;
2271541Srgrimes#else
2281541Srgrimes				return 0;
2291541Srgrimes#endif
2301541Srgrimes			}
2311541Srgrimes#ifdef BPF_ALIGN
23240779Sdfr			if (((intptr_t)(p + k) & 3) != 0)
2331541Srgrimes				A = EXTRACT_LONG(&p[k]);
2341541Srgrimes			else
2351541Srgrimes#endif
23640779Sdfr				A = ntohl(*(int32_t *)(p + k));
2371541Srgrimes			continue;
2381541Srgrimes
2391541Srgrimes		case BPF_LD|BPF_H|BPF_ABS:
2401541Srgrimes			k = pc->k;
24141588Seivind			if (k > buflen || sizeof(int16_t) > buflen - k) {
24255205Speter#ifdef _KERNEL
2431541Srgrimes				int merr;
2441541Srgrimes
2451541Srgrimes				if (buflen != 0)
2461541Srgrimes					return 0;
2471541Srgrimes				A = m_xhalf((struct mbuf *)p, k, &merr);
2481541Srgrimes				continue;
2491541Srgrimes#else
2501541Srgrimes				return 0;
2511541Srgrimes#endif
2521541Srgrimes			}
2531541Srgrimes			A = EXTRACT_SHORT(&p[k]);
2541541Srgrimes			continue;
2551541Srgrimes
2561541Srgrimes		case BPF_LD|BPF_B|BPF_ABS:
2571541Srgrimes			k = pc->k;
2581541Srgrimes			if (k >= buflen) {
25955205Speter#ifdef _KERNEL
2601541Srgrimes				register struct mbuf *m;
2611541Srgrimes
2621541Srgrimes				if (buflen != 0)
2631541Srgrimes					return 0;
2641541Srgrimes				m = (struct mbuf *)p;
2651541Srgrimes				MINDEX(m, k);
2661541Srgrimes				A = mtod(m, u_char *)[k];
2671541Srgrimes				continue;
2681541Srgrimes#else
2691541Srgrimes				return 0;
2701541Srgrimes#endif
2711541Srgrimes			}
2721541Srgrimes			A = p[k];
2731541Srgrimes			continue;
2741541Srgrimes
2751541Srgrimes		case BPF_LD|BPF_W|BPF_LEN:
2761541Srgrimes			A = wirelen;
2771541Srgrimes			continue;
2781541Srgrimes
2791541Srgrimes		case BPF_LDX|BPF_W|BPF_LEN:
2801541Srgrimes			X = wirelen;
2811541Srgrimes			continue;
2821541Srgrimes
2831541Srgrimes		case BPF_LD|BPF_W|BPF_IND:
2841541Srgrimes			k = X + pc->k;
28545574Seivind			if (pc->k > buflen || X > buflen - pc->k ||
28645574Seivind			    sizeof(int32_t) > buflen - k) {
28755205Speter#ifdef _KERNEL
2881541Srgrimes				int merr;
2891541Srgrimes
2901541Srgrimes				if (buflen != 0)
2911541Srgrimes					return 0;
2921541Srgrimes				A = m_xword((struct mbuf *)p, k, &merr);
2931541Srgrimes				if (merr != 0)
2941541Srgrimes					return 0;
2951541Srgrimes				continue;
2961541Srgrimes#else
2971541Srgrimes				return 0;
2981541Srgrimes#endif
2991541Srgrimes			}
3001541Srgrimes#ifdef BPF_ALIGN
30140779Sdfr			if (((intptr_t)(p + k) & 3) != 0)
3021541Srgrimes				A = EXTRACT_LONG(&p[k]);
3031541Srgrimes			else
3041541Srgrimes#endif
30540779Sdfr				A = ntohl(*(int32_t *)(p + k));
3061541Srgrimes			continue;
3071541Srgrimes
3081541Srgrimes		case BPF_LD|BPF_H|BPF_IND:
3091541Srgrimes			k = X + pc->k;
31045574Seivind			if (X > buflen || pc->k > buflen - X ||
31145574Seivind			    sizeof(int16_t) > buflen - k) {
31255205Speter#ifdef _KERNEL
3131541Srgrimes				int merr;
3141541Srgrimes
3151541Srgrimes				if (buflen != 0)
3161541Srgrimes					return 0;
3171541Srgrimes				A = m_xhalf((struct mbuf *)p, k, &merr);
3181541Srgrimes				if (merr != 0)
3191541Srgrimes					return 0;
3201541Srgrimes				continue;
3211541Srgrimes#else
3221541Srgrimes				return 0;
3231541Srgrimes#endif
3241541Srgrimes			}
3251541Srgrimes			A = EXTRACT_SHORT(&p[k]);
3261541Srgrimes			continue;
3271541Srgrimes
3281541Srgrimes		case BPF_LD|BPF_B|BPF_IND:
3291541Srgrimes			k = X + pc->k;
33048548Sbde			if (pc->k >= buflen || X >= buflen - pc->k) {
33155205Speter#ifdef _KERNEL
3321541Srgrimes				register struct mbuf *m;
3331541Srgrimes
3341541Srgrimes				if (buflen != 0)
3351541Srgrimes					return 0;
3361541Srgrimes				m = (struct mbuf *)p;
3371541Srgrimes				MINDEX(m, k);
338159018Sdwmalone				A = mtod(m, u_char *)[k];
3391541Srgrimes				continue;
3401541Srgrimes#else
3411541Srgrimes				return 0;
3421541Srgrimes#endif
3431541Srgrimes			}
3441541Srgrimes			A = p[k];
3451541Srgrimes			continue;
3461541Srgrimes
3471541Srgrimes		case BPF_LDX|BPF_MSH|BPF_B:
3481541Srgrimes			k = pc->k;
3491541Srgrimes			if (k >= buflen) {
35055205Speter#ifdef _KERNEL
3511541Srgrimes				register struct mbuf *m;
3521541Srgrimes
3531541Srgrimes				if (buflen != 0)
3541541Srgrimes					return 0;
3551541Srgrimes				m = (struct mbuf *)p;
3561541Srgrimes				MINDEX(m, k);
357159018Sdwmalone				X = (mtod(m, u_char *)[k] & 0xf) << 2;
3581541Srgrimes				continue;
3591541Srgrimes#else
3601541Srgrimes				return 0;
3611541Srgrimes#endif
3621541Srgrimes			}
3631541Srgrimes			X = (p[pc->k] & 0xf) << 2;
3641541Srgrimes			continue;
3651541Srgrimes
3661541Srgrimes		case BPF_LD|BPF_IMM:
3671541Srgrimes			A = pc->k;
3681541Srgrimes			continue;
3691541Srgrimes
3701541Srgrimes		case BPF_LDX|BPF_IMM:
3711541Srgrimes			X = pc->k;
3721541Srgrimes			continue;
3731541Srgrimes
3741541Srgrimes		case BPF_LD|BPF_MEM:
3751541Srgrimes			A = mem[pc->k];
3761541Srgrimes			continue;
3778876Srgrimes
3781541Srgrimes		case BPF_LDX|BPF_MEM:
3791541Srgrimes			X = mem[pc->k];
3801541Srgrimes			continue;
3811541Srgrimes
3821541Srgrimes		case BPF_ST:
3831541Srgrimes			mem[pc->k] = A;
3841541Srgrimes			continue;
3851541Srgrimes
3861541Srgrimes		case BPF_STX:
3871541Srgrimes			mem[pc->k] = X;
3881541Srgrimes			continue;
3891541Srgrimes
3901541Srgrimes		case BPF_JMP|BPF_JA:
3911541Srgrimes			pc += pc->k;
3921541Srgrimes			continue;
3931541Srgrimes
3941541Srgrimes		case BPF_JMP|BPF_JGT|BPF_K:
3951541Srgrimes			pc += (A > pc->k) ? pc->jt : pc->jf;
3961541Srgrimes			continue;
3971541Srgrimes
3981541Srgrimes		case BPF_JMP|BPF_JGE|BPF_K:
3991541Srgrimes			pc += (A >= pc->k) ? pc->jt : pc->jf;
4001541Srgrimes			continue;
4011541Srgrimes
4021541Srgrimes		case BPF_JMP|BPF_JEQ|BPF_K:
4031541Srgrimes			pc += (A == pc->k) ? pc->jt : pc->jf;
4041541Srgrimes			continue;
4051541Srgrimes
4061541Srgrimes		case BPF_JMP|BPF_JSET|BPF_K:
4071541Srgrimes			pc += (A & pc->k) ? pc->jt : pc->jf;
4081541Srgrimes			continue;
4091541Srgrimes
4101541Srgrimes		case BPF_JMP|BPF_JGT|BPF_X:
4111541Srgrimes			pc += (A > X) ? pc->jt : pc->jf;
4121541Srgrimes			continue;
4131541Srgrimes
4141541Srgrimes		case BPF_JMP|BPF_JGE|BPF_X:
4151541Srgrimes			pc += (A >= X) ? pc->jt : pc->jf;
4161541Srgrimes			continue;
4171541Srgrimes
4181541Srgrimes		case BPF_JMP|BPF_JEQ|BPF_X:
4191541Srgrimes			pc += (A == X) ? pc->jt : pc->jf;
4201541Srgrimes			continue;
4211541Srgrimes
4221541Srgrimes		case BPF_JMP|BPF_JSET|BPF_X:
4231541Srgrimes			pc += (A & X) ? pc->jt : pc->jf;
4241541Srgrimes			continue;
4251541Srgrimes
4261541Srgrimes		case BPF_ALU|BPF_ADD|BPF_X:
4271541Srgrimes			A += X;
4281541Srgrimes			continue;
4298876Srgrimes
4301541Srgrimes		case BPF_ALU|BPF_SUB|BPF_X:
4311541Srgrimes			A -= X;
4321541Srgrimes			continue;
4338876Srgrimes
4341541Srgrimes		case BPF_ALU|BPF_MUL|BPF_X:
4351541Srgrimes			A *= X;
4361541Srgrimes			continue;
4378876Srgrimes
4381541Srgrimes		case BPF_ALU|BPF_DIV|BPF_X:
4391541Srgrimes			if (X == 0)
4401541Srgrimes				return 0;
4411541Srgrimes			A /= X;
4421541Srgrimes			continue;
4438876Srgrimes
4441541Srgrimes		case BPF_ALU|BPF_AND|BPF_X:
4451541Srgrimes			A &= X;
4461541Srgrimes			continue;
4478876Srgrimes
4481541Srgrimes		case BPF_ALU|BPF_OR|BPF_X:
4491541Srgrimes			A |= X;
4501541Srgrimes			continue;
4511541Srgrimes
4521541Srgrimes		case BPF_ALU|BPF_LSH|BPF_X:
4531541Srgrimes			A <<= X;
4541541Srgrimes			continue;
4551541Srgrimes
4561541Srgrimes		case BPF_ALU|BPF_RSH|BPF_X:
4571541Srgrimes			A >>= X;
4581541Srgrimes			continue;
4591541Srgrimes
4601541Srgrimes		case BPF_ALU|BPF_ADD|BPF_K:
4611541Srgrimes			A += pc->k;
4621541Srgrimes			continue;
4638876Srgrimes
4641541Srgrimes		case BPF_ALU|BPF_SUB|BPF_K:
4651541Srgrimes			A -= pc->k;
4661541Srgrimes			continue;
4678876Srgrimes
4681541Srgrimes		case BPF_ALU|BPF_MUL|BPF_K:
4691541Srgrimes			A *= pc->k;
4701541Srgrimes			continue;
4718876Srgrimes
4721541Srgrimes		case BPF_ALU|BPF_DIV|BPF_K:
4731541Srgrimes			A /= pc->k;
4741541Srgrimes			continue;
4758876Srgrimes
4761541Srgrimes		case BPF_ALU|BPF_AND|BPF_K:
4771541Srgrimes			A &= pc->k;
4781541Srgrimes			continue;
4798876Srgrimes
4801541Srgrimes		case BPF_ALU|BPF_OR|BPF_K:
4811541Srgrimes			A |= pc->k;
4821541Srgrimes			continue;
4831541Srgrimes
4841541Srgrimes		case BPF_ALU|BPF_LSH|BPF_K:
4851541Srgrimes			A <<= pc->k;
4861541Srgrimes			continue;
4871541Srgrimes
4881541Srgrimes		case BPF_ALU|BPF_RSH|BPF_K:
4891541Srgrimes			A >>= pc->k;
4901541Srgrimes			continue;
4911541Srgrimes
4921541Srgrimes		case BPF_ALU|BPF_NEG:
4931541Srgrimes			A = -A;
4941541Srgrimes			continue;
4951541Srgrimes
4961541Srgrimes		case BPF_MISC|BPF_TAX:
4971541Srgrimes			X = A;
4981541Srgrimes			continue;
4991541Srgrimes
5001541Srgrimes		case BPF_MISC|BPF_TXA:
5011541Srgrimes			A = X;
5021541Srgrimes			continue;
5031541Srgrimes		}
5041541Srgrimes	}
5051541Srgrimes}
5061541Srgrimes
50755205Speter#ifdef _KERNEL
5081541Srgrimes/*
5091541Srgrimes * Return true if the 'fcode' is a valid filter program.
5101541Srgrimes * The constraints are that each jump be forward and to a valid
5118876Srgrimes * code.  The code must terminate with either an accept or reject.
5121541Srgrimes *
5131541Srgrimes * The kernel needs to be able to verify an application's filter code.
5141541Srgrimes * Otherwise, a bogus program could easily crash the system.
5151541Srgrimes */
5161541Srgrimesint
5171541Srgrimesbpf_validate(f, len)
51854038Sarchie	const struct bpf_insn *f;
5191541Srgrimes	int len;
5201541Srgrimes{
5211541Srgrimes	register int i;
52254038Sarchie	register const struct bpf_insn *p;
5231541Srgrimes
524153996Sjkim	/* Do not accept negative length filter. */
525153996Sjkim	if (len < 0)
526153996Sjkim		return 0;
527153996Sjkim
528153996Sjkim	/* An empty filter means accept all. */
529153996Sjkim	if (len == 0)
530153995Sjkim		return 1;
531153221Sjkim
5321541Srgrimes	for (i = 0; i < len; ++i) {
5331541Srgrimes		/*
5348876Srgrimes		 * Check that that jumps are forward, and within
5351541Srgrimes		 * the code block.
5361541Srgrimes		 */
5371541Srgrimes		p = &f[i];
5381541Srgrimes		if (BPF_CLASS(p->code) == BPF_JMP) {
5391541Srgrimes			register int from = i + 1;
5401541Srgrimes
5411541Srgrimes			if (BPF_OP(p->code) == BPF_JA) {
54241588Seivind				if (from >= len || p->k >= len - from)
5431541Srgrimes					return 0;
5441541Srgrimes			}
54545574Seivind			else if (from >= len || p->jt >= len - from ||
54645574Seivind				 p->jf >= len - from)
5471541Srgrimes				return 0;
5481541Srgrimes		}
5491541Srgrimes		/*
5501541Srgrimes		 * Check that memory operations use valid addresses.
5511541Srgrimes		 */
5521541Srgrimes		if ((BPF_CLASS(p->code) == BPF_ST ||
5538876Srgrimes		     (BPF_CLASS(p->code) == BPF_LD &&
5541541Srgrimes		      (p->code & 0xe0) == BPF_MEM)) &&
55541588Seivind		    p->k >= BPF_MEMWORDS)
5561541Srgrimes			return 0;
5571541Srgrimes		/*
5581541Srgrimes		 * Check for constant division by 0.
5591541Srgrimes		 */
5601541Srgrimes		if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
5611541Srgrimes			return 0;
5621541Srgrimes	}
5631541Srgrimes	return BPF_CLASS(f[len - 1].code) == BPF_RET;
5641541Srgrimes}
5651541Srgrimes#endif
566