1478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*-
2478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
3478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	The Regents of the University of California.  All rights reserved.
4478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
5478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * This code is derived from the Stanford/CMU enet packet filter,
6478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * (net/enet.c) distributed as part of 4.3BSD, and code contributed
7478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
8478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Berkeley Laboratory.
9478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
10478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Redistribution and use in source and binary forms, with or without
11478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * modification, are permitted provided that the following conditions
12478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * are met:
13478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
14478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
15478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
16478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
17478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *    documentation and/or other materials provided with the distribution.
18478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * 3. All advertising materials mentioning features or use of this software
19478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *    must display the following acknowledgement:
20478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	This product includes software developed by the University of
21478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	California, Berkeley and its contributors.
22478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * 4. Neither the name of the University nor the names of its contributors
23478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *    may be used to endorse or promote products derived from this software
24478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *    without specific prior written permission.
25478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
26478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * SUCH DAMAGE.
37478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
38478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	@(#)bpf.c	7.5 (Berkeley) 7/15/91
39478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
40478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
41478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#if !(defined(lint) || defined(KERNEL) || defined(_KERNEL))
42478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic const char rcsid[] _U_ =
43478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project    "@(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf_filter.c,v 1.44 2003/11/15 23:24:07 guy Exp $ (LBL)";
44478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
45478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
46478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef HAVE_CONFIG_H
47478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include "config.h"
48478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
49478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
50478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef WIN32
51478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
52478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <pcap-stdinc.h>
53478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
54478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else /* WIN32 */
55478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
56478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <sys/param.h>
57478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <sys/types.h>
58478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <sys/time.h>
59478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
60478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define	SOLARIS	(defined(sun) && (defined(__SVR4) || defined(__svr4__)))
61478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#if defined(__hpux) || SOLARIS
62478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project# include <sys/sysmacros.h>
63478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project# include <sys/stream.h>
64478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project# define	mbuf	msgb
65478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project# define	m_next	b_cont
66478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project# define	MLEN(m)	((m)->b_wptr - (m)->b_rptr)
67478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project# define	mtod(m,t)	((t)(m)->b_rptr)
68478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
69478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project# define	MLEN(m)	((m)->m_len)
70478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
71478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
72478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif /* WIN32 */
73478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
74478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <pcap-bpf.h>
75478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
76478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#if !defined(KERNEL) && !defined(_KERNEL)
77478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <stdlib.h>
78478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
79478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
80478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define int32 bpf_int32
81478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define u_int32 bpf_u_int32
82478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
83478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef LBL_ALIGN
84478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
85478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * XXX - IA-64?  If not, this probably won't work on Win64 IA-64
86478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * systems, unless LBL_ALIGN is defined elsewhere for them.
87478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * XXX - SuperH?  If not, this probably won't work on WinCE SuperH
88478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * systems, unless LBL_ALIGN is defined elsewhere for them.
89478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
90478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#if defined(sparc) || defined(__sparc__) || defined(mips) || \
91478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project    defined(ibm032) || defined(__alpha) || defined(__hpux) || \
92478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project    defined(__arm__)
93478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define LBL_ALIGN
94478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
95478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
96478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
97478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef LBL_ALIGN
98478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef WIN32
99478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <netinet/in.h>
100478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
101478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
102478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define EXTRACT_SHORT(p)	((u_short)ntohs(*(u_short *)p))
103478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define EXTRACT_LONG(p)		(ntohl(*(u_int32 *)p))
104478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
105478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define EXTRACT_SHORT(p)\
106478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	((u_short)\
107478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		((u_short)*((u_char *)p+0)<<8|\
108478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 (u_short)*((u_char *)p+1)<<0))
109478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define EXTRACT_LONG(p)\
110478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		((u_int32)*((u_char *)p+0)<<24|\
111478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 (u_int32)*((u_char *)p+1)<<16|\
112478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 (u_int32)*((u_char *)p+2)<<8|\
113478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 (u_int32)*((u_char *)p+3)<<0)
114478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
115478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
116478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#if defined(KERNEL) || defined(_KERNEL)
117478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project# if !defined(__hpux) && !SOLARIS
118478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <sys/mbuf.h>
119478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project# endif
120478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define MINDEX(len, _m, _k) \
121478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{ \
122478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	len = MLEN(m); \
123478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	while ((_k) >= len) { \
124478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		(_k) -= len; \
125478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		(_m) = (_m)->m_next; \
126478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if ((_m) == 0) \
127478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return 0; \
128478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		len = MLEN(m); \
129478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	} \
130478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
131478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
132478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
133478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectm_xword(m, k, err)
134478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct mbuf *m;
135478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int k, *err;
136478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
137478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int len;
138478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register u_char *cp, *np;
139478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct mbuf *m0;
140478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
141478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	MINDEX(len, m, k);
142478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	cp = mtod(m, u_char *) + k;
143478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (len - k >= 4) {
144478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		*err = 0;
145478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return EXTRACT_LONG(cp);
146478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
147478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	m0 = m->m_next;
148478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (m0 == 0 || MLEN(m0) + len - k < 4)
149478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		goto bad;
150478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	*err = 0;
151478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	np = mtod(m0, u_char *);
152478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (len - k) {
153478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
154478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case 1:
155478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
156478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
157478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case 2:
158478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1];
159478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
160478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
161478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0];
162478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
163478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project    bad:
164478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	*err = 1;
165478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return 0;
166478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
167478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
168478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
169478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectm_xhalf(m, k, err)
170478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct mbuf *m;
171478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int k, *err;
172478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
173478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int len;
174478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register u_char *cp;
175478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct mbuf *m0;
176478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
177478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	MINDEX(len, m, k);
178478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	cp = mtod(m, u_char *) + k;
179478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (len - k >= 2) {
180478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		*err = 0;
181478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return EXTRACT_SHORT(cp);
182478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
183478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	m0 = m->m_next;
184478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (m0 == 0)
185478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		goto bad;
186478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	*err = 0;
187478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (cp[0] << 8) | mtod(m0, u_char *)[0];
188478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project bad:
189478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	*err = 1;
190478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return 0;
191478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
192478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
193478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
194478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
195478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Execute the filter program starting at pc on the packet p
196478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * wirelen is the length of the original packet
197478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * buflen is the amount of data present
198478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * For the kernel, p is assumed to be a pointer to an mbuf if buflen is 0,
199478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * in all other cases, p is a pointer to a buffer and buflen is its size.
200478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
201478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectu_int
202478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectbpf_filter(pc, p, wirelen, buflen)
203478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct bpf_insn *pc;
204478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register u_char *p;
205478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int wirelen;
206478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register u_int buflen;
207478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
208478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register u_int32 A, X;
209478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int k;
210478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int32 mem[BPF_MEMWORDS];
211478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#if defined(KERNEL) || defined(_KERNEL)
212478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct mbuf *m, *n;
213478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int merr, len;
214478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
215478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (buflen == 0) {
216478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		m = (struct mbuf *)p;
217478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		p = mtod(m, u_char *);
218478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		buflen = MLEN(m);
219478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	} else
220478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		m = NULL;
221478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
222478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
223478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (pc == 0)
224478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
225478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * No filter means accept all.
226478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
227478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return (u_int)-1;
228478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	A = 0;
229478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	X = 0;
230478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	--pc;
231478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	while (1) {
232478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		++pc;
233478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		switch (pc->code) {
234478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
235478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		default:
236478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#if defined(KERNEL) || defined(_KERNEL)
237478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return 0;
238478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
239478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			abort();
240478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
241478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_RET|BPF_K:
242478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return (u_int)pc->k;
243478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
244478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_RET|BPF_A:
245478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return (u_int)A;
246478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
247478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_LD|BPF_W|BPF_ABS:
248478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			k = pc->k;
249478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (k + sizeof(int32) > buflen) {
250478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#if defined(KERNEL) || defined(_KERNEL)
251478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (m == NULL)
252478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					return 0;
253478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				A = m_xword(m, k, &merr);
254478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (merr != 0)
255478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					return 0;
256478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				continue;
257478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
258478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				return 0;
259478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
260478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
261478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A = EXTRACT_LONG(&p[k]);
262478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
263478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
264478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_LD|BPF_H|BPF_ABS:
265478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			k = pc->k;
266478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (k + sizeof(short) > buflen) {
267478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#if defined(KERNEL) || defined(_KERNEL)
268478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (m == NULL)
269478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					return 0;
270478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				A = m_xhalf(m, k, &merr);
271478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (merr != 0)
272478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					return 0;
273478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				continue;
274478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
275478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				return 0;
276478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
277478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
278478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A = EXTRACT_SHORT(&p[k]);
279478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
280478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
281478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_LD|BPF_B|BPF_ABS:
282478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			k = pc->k;
283478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (k >= buflen) {
284478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#if defined(KERNEL) || defined(_KERNEL)
285478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (m == NULL)
286478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					return 0;
287478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				n = m;
288478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				MINDEX(len, n, k);
289478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				A = mtod(n, u_char *)[k];
290478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				continue;
291478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
292478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				return 0;
293478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
294478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
295478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A = p[k];
296478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
297478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
298478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_LD|BPF_W|BPF_LEN:
299478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A = wirelen;
300478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
301478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
302478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_LDX|BPF_W|BPF_LEN:
303478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			X = wirelen;
304478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
305478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
306478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_LD|BPF_W|BPF_IND:
307478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			k = X + pc->k;
308478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (k + sizeof(int32) > buflen) {
309478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#if defined(KERNEL) || defined(_KERNEL)
310478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (m == NULL)
311478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					return 0;
312478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				A = m_xword(m, k, &merr);
313478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (merr != 0)
314478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					return 0;
315478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				continue;
316478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
317478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				return 0;
318478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
319478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
320478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A = EXTRACT_LONG(&p[k]);
321478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
322478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
323478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_LD|BPF_H|BPF_IND:
324478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			k = X + pc->k;
325478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (k + sizeof(short) > buflen) {
326478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#if defined(KERNEL) || defined(_KERNEL)
327478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (m == NULL)
328478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					return 0;
329478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				A = m_xhalf(m, k, &merr);
330478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (merr != 0)
331478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					return 0;
332478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				continue;
333478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
334478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				return 0;
335478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
336478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
337478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A = EXTRACT_SHORT(&p[k]);
338478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
339478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
340478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_LD|BPF_B|BPF_IND:
341478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			k = X + pc->k;
342478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (k >= buflen) {
343478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#if defined(KERNEL) || defined(_KERNEL)
344478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (m == NULL)
345478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					return 0;
346478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				n = m;
347478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				MINDEX(len, n, k);
348478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				A = mtod(n, u_char *)[k];
349478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				continue;
350478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
351478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				return 0;
352478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
353478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
354478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A = p[k];
355478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
356478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
357478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_LDX|BPF_MSH|BPF_B:
358478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			k = pc->k;
359478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (k >= buflen) {
360478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#if defined(KERNEL) || defined(_KERNEL)
361478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (m == NULL)
362478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					return 0;
363478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				n = m;
364478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				MINDEX(len, n, k);
365478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				X = (mtod(n, char *)[k] & 0xf) << 2;
366478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				continue;
367478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
368478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				return 0;
369478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
370478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
371478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			X = (p[pc->k] & 0xf) << 2;
372478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
373478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
374478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_LD|BPF_IMM:
375478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A = pc->k;
376478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
377478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
378478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_LDX|BPF_IMM:
379478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			X = pc->k;
380478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
381478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
382478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_LD|BPF_MEM:
383478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A = mem[pc->k];
384478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
385478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
386478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_LDX|BPF_MEM:
387478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			X = mem[pc->k];
388478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
389478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
390478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ST:
391478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			mem[pc->k] = A;
392478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
393478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
394478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_STX:
395478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			mem[pc->k] = X;
396478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
397478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
398478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_JMP|BPF_JA:
399478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			pc += pc->k;
400478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
401478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
402478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_JMP|BPF_JGT|BPF_K:
403478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			pc += (A > pc->k) ? pc->jt : pc->jf;
404478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
405478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
406478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_JMP|BPF_JGE|BPF_K:
407478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			pc += (A >= pc->k) ? pc->jt : pc->jf;
408478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
409478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
410478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_JMP|BPF_JEQ|BPF_K:
411478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			pc += (A == pc->k) ? pc->jt : pc->jf;
412478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
413478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
414478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_JMP|BPF_JSET|BPF_K:
415478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			pc += (A & pc->k) ? pc->jt : pc->jf;
416478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
417478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
418478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_JMP|BPF_JGT|BPF_X:
419478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			pc += (A > X) ? pc->jt : pc->jf;
420478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
421478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
422478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_JMP|BPF_JGE|BPF_X:
423478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			pc += (A >= X) ? pc->jt : pc->jf;
424478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
425478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
426478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_JMP|BPF_JEQ|BPF_X:
427478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			pc += (A == X) ? pc->jt : pc->jf;
428478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
429478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
430478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_JMP|BPF_JSET|BPF_X:
431478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			pc += (A & X) ? pc->jt : pc->jf;
432478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
433478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
434478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_ADD|BPF_X:
435478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A += X;
436478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
437478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
438478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_SUB|BPF_X:
439478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A -= X;
440478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
441478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
442478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_MUL|BPF_X:
443478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A *= X;
444478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
445478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
446478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_DIV|BPF_X:
447478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (X == 0)
448478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				return 0;
449478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A /= X;
450478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
451478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
452478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_AND|BPF_X:
453478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A &= X;
454478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
455478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
456478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_OR|BPF_X:
457478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A |= X;
458478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
459478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
460478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_LSH|BPF_X:
461478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A <<= X;
462478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
463478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
464478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_RSH|BPF_X:
465478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A >>= X;
466478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
467478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
468478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_ADD|BPF_K:
469478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A += pc->k;
470478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
471478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
472478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_SUB|BPF_K:
473478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A -= pc->k;
474478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
475478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
476478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_MUL|BPF_K:
477478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A *= pc->k;
478478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
479478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
480478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_DIV|BPF_K:
481478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A /= pc->k;
482478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
483478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
484478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_AND|BPF_K:
485478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A &= pc->k;
486478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
487478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
488478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_OR|BPF_K:
489478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A |= pc->k;
490478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
491478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
492478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_LSH|BPF_K:
493478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A <<= pc->k;
494478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
495478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
496478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_RSH|BPF_K:
497478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A >>= pc->k;
498478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
499478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
500478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_ALU|BPF_NEG:
501478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A = -A;
502478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
503478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
504478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_MISC|BPF_TAX:
505478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			X = A;
506478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
507478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
508478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_MISC|BPF_TXA:
509478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			A = X;
510478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			continue;
511478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
512478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
513478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
514478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
515478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
516478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
517478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Return true if the 'fcode' is a valid filter program.
518478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * The constraints are that each jump be forward and to a valid
519478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * code.  The code must terminate with either an accept or reject.
520478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * 'valid' is an array for use by the routine (it must be at least
521478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * 'len' bytes long).
522478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
523478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * The kernel needs to be able to verify an application's filter code.
524478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Otherwise, a bogus program could easily crash the system.
525478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
526478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectint
527478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectbpf_validate(f, len)
528478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct bpf_insn *f;
529478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int len;
530478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
531478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int i;
532478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct bpf_insn *p;
533478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
534478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	for (i = 0; i < len; ++i) {
535478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
536478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Check that that jumps are forward, and within
537478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the code block.
538478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
539478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		p = &f[i];
540478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (BPF_CLASS(p->code) == BPF_JMP) {
541478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			register int from = i + 1;
542478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
543478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (BPF_OP(p->code) == BPF_JA) {
544478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (from + p->k >= (unsigned)len)
545478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					return 0;
546478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
547478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			else if (from + p->jt >= len || from + p->jf >= len)
548478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				return 0;
549478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
550478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
551478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Check that memory operations use valid addresses.
552478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
553478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if ((BPF_CLASS(p->code) == BPF_ST ||
554478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		     (BPF_CLASS(p->code) == BPF_LD &&
555478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		      (p->code & 0xe0) == BPF_MEM)) &&
556478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    (p->k >= BPF_MEMWORDS || p->k < 0))
557478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return 0;
558478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
559478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Check for constant division by 0.
560478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
561478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
562478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return 0;
563478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
564478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return BPF_CLASS(f[len - 1].code) == BPF_RET;
565478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
566