1478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*#define CHASE_CHAIN*/
2478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
3478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
4478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	The Regents of the University of California.  All rights reserved.
5478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
6478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Redistribution and use in source and binary forms, with or without
7478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * modification, are permitted provided that: (1) source code distributions
8478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * retain the above copyright notice and this paragraph in its entirety, (2)
9478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * distributions including binary code include the above copyright notice and
10478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * this paragraph in its entirety in the documentation or other materials
11478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * provided with the distribution, and (3) all advertising materials mentioning
12478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * features or use of this software display the following acknowledgement:
13478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * ``This product includes software developed by the University of California,
14478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
15478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * the University nor the names of its contributors may be used to endorse
16478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * or promote products derived from this software without specific prior
17478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * written permission.
18478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
22478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
23478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef HAVE_CONFIG_H
24478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include "config.h"
25478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
26478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
27478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef WIN32
28478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <pcap-stdinc.h>
29478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else /* WIN32 */
30511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if HAVE_INTTYPES_H
31511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <inttypes.h>
32511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#elif HAVE_STDINT_H
33511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <stdint.h>
34511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
35511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_SYS_BITYPES_H
36511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <sys/bitypes.h>
37511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
38478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <sys/types.h>
39478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <sys/socket.h>
40478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif /* WIN32 */
41478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
42478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
43478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * XXX - why was this included even on UNIX?
44478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
45478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef __MINGW32__
46511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "ip6_misc.h"
47478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
48478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
49478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef WIN32
50478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
51478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef __NetBSD__
52478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <sys/param.h>
53478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
54478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
55478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <netinet/in.h>
56511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <arpa/inet.h>
57478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
58478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif /* WIN32 */
59478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
60478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <stdlib.h>
61478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <string.h>
62478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <memory.h>
63478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <setjmp.h>
64478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <stdarg.h>
65478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
66478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef MSDOS
67478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include "pcap-dos.h"
68478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
69478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
70478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include "pcap-int.h"
71478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
72478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include "ethertype.h"
73478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include "nlpid.h"
74478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include "llc.h"
75478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include "gencode.h"
76511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "ieee80211.h"
77478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include "atmuni31.h"
78478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include "sunatmpos.h"
79478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include "ppp.h"
80511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "pcap/sll.h"
81511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "pcap/ipnet.h"
82478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include "arcnet.h"
83511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
84511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/types.h>
85511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/if_packet.h>
86511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/filter.h>
87511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
88478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef HAVE_NET_PFVAR_H
89478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <sys/socket.h>
90478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <net/if.h>
91478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <net/pfvar.h>
92478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <net/if_pflog.h>
93478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
94478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef offsetof
95478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define offsetof(s, e) ((size_t)&((s *)0)->e)
96478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
97478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef INET6
98478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef WIN32
99478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <netdb.h>	/* for "struct addrinfo" */
100478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif /* WIN32 */
101478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif /*INET6*/
102511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <pcap/namedb.h>
103478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
104478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define ETHERMTU	1500
105478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
106d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes#ifndef ETHERTYPE_TEB
107d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes#define ETHERTYPE_TEB 0x6558
108d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes#endif
109d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
110511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef IPPROTO_HOPOPTS
111511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define IPPROTO_HOPOPTS 0
112511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
113511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef IPPROTO_ROUTING
114511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define IPPROTO_ROUTING 43
115511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
116511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef IPPROTO_FRAGMENT
117511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define IPPROTO_FRAGMENT 44
118511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
119511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef IPPROTO_DSTOPTS
120511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define IPPROTO_DSTOPTS 60
121511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
122478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef IPPROTO_SCTP
123478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define IPPROTO_SCTP 132
124478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
125478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
126d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes#define GENEVE_PORT 6081
127d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
128478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef HAVE_OS_PROTO_H
129478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include "os-proto.h"
130478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
131478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
132478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define JMP(c) ((c)|BPF_JMP|BPF_K)
133478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
134478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/* Locals */
135478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic jmp_buf top_ctx;
136478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic pcap_t *bpf_pcap;
137478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
138d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes/* Hack for handling VLAN and MPLS stacks. */
139511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef WIN32
140d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic u_int	label_stack_depth = (u_int)-1, vlan_stack_depth = (u_int)-1;
141478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
142d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic u_int	label_stack_depth = -1U, vlan_stack_depth = -1U;
143478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
144478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
145478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/* XXX */
146478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int	pcap_fddipad;
147478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
148478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/* VARARGS */
149478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectvoid
150478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectbpf_error(const char *fmt, ...)
151478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
152478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	va_list ap;
153478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
154478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	va_start(ap, fmt);
155478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (bpf_pcap != NULL)
156478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		(void)vsnprintf(pcap_geterr(bpf_pcap), PCAP_ERRBUF_SIZE,
157478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    fmt, ap);
158478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	va_end(ap);
159478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	longjmp(top_ctx, 1);
160478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
161478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
162478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
163478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic void init_linktype(pcap_t *);
164478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
165511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void init_regs(void);
166478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int alloc_reg(void);
167478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic void free_reg(int);
168478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
169478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *root;
170478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
171478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
172d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * Absolute offsets, which are offsets from the beginning of the raw
173d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * packet data, are, in the general case, the sum of a variable value
174d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * and a constant value; the variable value may be absent, in which
175d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * case the offset is only the constant value, and the constant value
176d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * may be zero, in which case the offset is only the variable value.
177d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *
178d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * bpf_abs_offset is a structure containing all that information:
179d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *
180d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *   is_variable is 1 if there's a variable part.
181d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *
182d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *   constant_part is the constant part of the value, possibly zero;
183d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *
184d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *   if is_variable is 1, reg is the register number for a register
185d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *   containing the variable value if the register has been assigned,
186d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *   and -1 otherwise.
187d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes */
188d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughestypedef struct {
189d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	int	is_variable;
190d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	u_int	constant_part;
191d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	int	reg;
192d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes} bpf_abs_offset;
193d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
194d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes/*
195478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Value passed to gen_load_a() to indicate what the offset argument
196d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * is relative to the beginning of.
197478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
198478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectenum e_offrel {
199d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	OR_PACKET,		/* full packet data */
200d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	OR_LINKHDR,		/* link-layer header */
201d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	OR_PREVLINKHDR,		/* previous link-layer header */
202d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	OR_LLC,			/* 802.2 LLC header */
203d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	OR_PREVMPLSHDR,		/* previous MPLS header */
204d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	OR_LINKTYPE,		/* link-layer type */
205d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	OR_LINKPL,		/* link-layer payload */
206d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	OR_LINKPL_NOSNAP,	/* link-layer payload, with no SNAP header at the link layer */
207d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	OR_TRAN_IPV4,		/* transport-layer header, with IPv4 network layer */
208d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	OR_TRAN_IPV6		/* transport-layer header, with IPv6 network layer */
209478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project};
210478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
211511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef INET6
212511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
213511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * As errors are handled by a longjmp, anything allocated must be freed
214511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * in the longjmp handler, so it must be reachable from that handler.
215511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * One thing that's allocated is the result of pcap_nametoaddrinfo();
216511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * it must be freed with freeaddrinfo().  This variable points to any
217511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * addrinfo structure that would need to be freed.
218511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
219511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct addrinfo *ai;
220511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
221511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
222478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
223478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * We divy out chunks of memory rather than call malloc each time so
224478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * we don't have to worry about leaking memory.  It's probably
225478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * not a big deal if all this memory was wasted but if this ever
226478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * goes into a library that would probably not be a good idea.
227478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
228478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * XXX - this *is* in a library....
229478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
230478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define NCHUNKS 16
231478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define CHUNK0SIZE 1024
232478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct chunk {
233478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int n_left;
234478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	void *m;
235478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project};
236478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
237478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct chunk chunks[NCHUNKS];
238478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int cur_chunk;
239478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
240478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic void *newchunk(u_int);
241478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic void freechunks(void);
242478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic inline struct block *new_block(int);
243478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic inline struct slist *new_stmt(int);
244478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_retblk(int);
245478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic inline void syntax(void);
246478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
247478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic void backpatch(struct block *, struct block *);
248478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic void merge(struct block *, struct block *);
249478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_cmp(enum e_offrel, u_int, u_int, bpf_int32);
250478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_cmp_gt(enum e_offrel, u_int, u_int, bpf_int32);
251478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_cmp_ge(enum e_offrel, u_int, u_int, bpf_int32);
252478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_cmp_lt(enum e_offrel, u_int, u_int, bpf_int32);
253478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_cmp_le(enum e_offrel, u_int, u_int, bpf_int32);
254478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_mcmp(enum e_offrel, u_int, u_int, bpf_int32,
255478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project    bpf_u_int32);
256478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_bcmp(enum e_offrel, u_int, u_int, const u_char *);
257478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_ncmp(enum e_offrel, bpf_u_int32, bpf_u_int32,
258478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project    bpf_u_int32, bpf_u_int32, int, bpf_int32);
259d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic struct slist *gen_load_absoffsetrel(bpf_abs_offset *, u_int, u_int);
260478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct slist *gen_load_a(enum e_offrel, u_int, u_int);
261478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct slist *gen_loadx_iphdrlen(void);
262478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_uncond(int);
263478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic inline struct block *gen_true(void);
264478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic inline struct block *gen_false(void);
265478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_ether_linktype(int);
266511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct block *gen_ipnet_linktype(int);
267478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_linux_sll_linktype(int);
268511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct slist *gen_load_prism_llprefixlen(void);
269511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct slist *gen_load_avs_llprefixlen(void);
270511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct slist *gen_load_radiotap_llprefixlen(void);
271511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct slist *gen_load_ppi_llprefixlen(void);
272511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void insert_compute_vloffsets(struct block *);
273d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic struct slist *gen_abs_offset_varpart(bpf_abs_offset *);
274511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int ethertype_to_ppptype(int);
275478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_linktype(int);
276511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct block *gen_snap(bpf_u_int32, bpf_u_int32);
277478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_llc_linktype(int);
278478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int);
279478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef INET6
280478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int);
281478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
282478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_ahostop(const u_char *, int);
283478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_ehostop(const u_char *, int);
284478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_fhostop(const u_char *, int);
285478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_thostop(const u_char *, int);
286478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_wlanhostop(const u_char *, int);
287478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_ipfchostop(const u_char *, int);
288478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_dnhostop(bpf_u_int32, int);
289478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_mpls_linktype(int);
290478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int, int);
291478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef INET6
292478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int, int);
293478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
294478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef INET6
295478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);
296478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
297478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_ipfrag(void);
298478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_portatom(int, bpf_int32);
299478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_portrangeatom(int, bpf_int32, bpf_int32);
300478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_portatom6(int, bpf_int32);
301478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32);
302478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *gen_portop(int, int, int);
303478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_port(int, int, int);
304478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *gen_portrangeop(int, int, int, int);
305478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_portrange(int, int, int, int);
306478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *gen_portop6(int, int, int);
307478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_port6(int, int, int);
308478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *gen_portrangeop6(int, int, int, int);
309478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_portrange6(int, int, int, int);
310478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int lookup_proto(const char *, int);
311478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_protochain(int, int, int);
312478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_proto(int, int, int);
313478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct slist *xfer_to_x(struct arth *);
314478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct slist *xfer_to_a(struct arth *);
315478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_mac_multicast(int);
316478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_len(int, int);
317511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct block *gen_check_802_11_data_frame(void);
318d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic struct block *gen_geneve_ll_check(void);
319478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
320478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_ppi_dlt_check(void);
321478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *gen_msg_abbrev(int type);
322478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
323478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic void *
324478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectnewchunk(n)
325478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int n;
326478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
327478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct chunk *cp;
328478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int k;
329478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	size_t size;
330478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
331478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef __NetBSD__
332478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* XXX Round up to nearest long. */
333478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);
334478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
335478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* XXX Round up to structure boundary. */
336478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	n = ALIGN(n);
337478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
338478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
339478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	cp = &chunks[cur_chunk];
340478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (n > cp->n_left) {
341478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		++cp, k = ++cur_chunk;
342478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (k >= NCHUNKS)
343478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("out of memory");
344478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		size = CHUNK0SIZE << k;
345478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		cp->m = (void *)malloc(size);
346478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (cp->m == NULL)
347478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("out of memory");
348478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		memset((char *)cp->m, 0, size);
349478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		cp->n_left = size;
350478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (n > size)
351478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("out of memory");
352478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
353478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	cp->n_left -= n;
354478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (void *)((char *)cp->m + cp->n_left);
355478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
356478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
357478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic void
358478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectfreechunks()
359478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
360478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int i;
361478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
362478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	cur_chunk = 0;
363478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	for (i = 0; i < NCHUNKS; ++i)
364478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (chunks[i].m != NULL) {
365478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			free(chunks[i].m);
366478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			chunks[i].m = NULL;
367478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
368478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
369478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
370478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
371478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * A strdup whose allocations are freed after code generation is over.
372478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
373478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectchar *
374478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectsdup(s)
375478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register const char *s;
376478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
377478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int n = strlen(s) + 1;
378478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	char *cp = newchunk(n);
379478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
380478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	strlcpy(cp, s, n);
381478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (cp);
382478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
383478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
384478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic inline struct block *
385478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectnew_block(code)
386478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int code;
387478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
388478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *p;
389478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
390478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	p = (struct block *)newchunk(sizeof(*p));
391478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	p->s.code = code;
392478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	p->head = p;
393478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
394478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return p;
395478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
396478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
397478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic inline struct slist *
398478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectnew_stmt(code)
399478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int code;
400478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
401478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *p;
402478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
403478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	p = (struct slist *)newchunk(sizeof(*p));
404478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	p->s.code = code;
405478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
406478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return p;
407478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
408478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
409478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
410478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_retblk(v)
411478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int v;
412478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
413478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b = new_block(BPF_RET|BPF_K);
414478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
415478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b->s.k = v;
416478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b;
417478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
418478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
419478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic inline void
420478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectsyntax()
421478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
422478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_error("syntax error in filter expression");
423478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
424478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
425478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic bpf_u_int32 netmask;
426478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int snaplen;
427478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectint no_optimize;
428511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
429511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallint
430511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_compile(pcap_t *p, struct bpf_program *program,
431511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	     const char *buf, int optimize, bpf_u_int32 mask)
432511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
433478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	extern int n_errors;
434478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	const char * volatile xbuf = buf;
435511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_int len;
436d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	int  rc;
437d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
438d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/*
439d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * XXX - single-thread this code path with pthread calls on
440d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * UN*X, if the platform supports pthreads?  If that requires
441d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * a separate -lpthread, we might not want to do that.
442d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 */
443d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes#ifdef WIN32
444d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	extern int wsockinit (void);
445d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	static int done = 0;
446d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
447d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	if (!done)
448d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		wsockinit();
449d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	done = 1;
450d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	EnterCriticalSection(&g_PcapCompileCriticalSection);
451d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes#endif
452478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
453511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
454511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If this pcap_t hasn't been activated, it doesn't have a
455511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * link-layer type, so we can't use it.
456511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
457511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!p->activated) {
458511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
459511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "not-yet-activated pcap_t passed to pcap_compile");
460d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		rc = -1;
461d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		goto quit;
462511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
463478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	no_optimize = 0;
464478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	n_errors = 0;
465478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	root = NULL;
466478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_pcap = p;
467511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	init_regs();
468d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
469478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (setjmp(top_ctx)) {
470511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef INET6
471511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ai != NULL) {
472511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			freeaddrinfo(ai);
473511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ai = NULL;
474511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
475511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
476478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		lex_cleanup();
477478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		freechunks();
478d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		rc = -1;
479d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		goto quit;
480478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
481478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
482478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	netmask = mask;
483478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
484478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	snaplen = pcap_snapshot(p);
485478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (snaplen == 0) {
486478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
487478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 "snaplen of 0 rejects all packets");
488d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		rc = -1;
489d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		goto quit;
490478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
491478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
492478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	lex_init(xbuf ? xbuf : "");
493478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	init_linktype(p);
494478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	(void)pcap_parse();
495478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
496478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (n_errors)
497478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		syntax();
498478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
499478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (root == NULL)
500478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		root = gen_retblk(snaplen);
501478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
502478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (optimize && !no_optimize) {
503478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_optimize(&root);
504478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (root == NULL ||
505478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0))
506478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("expression rejects all packets");
507478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
508478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	program->bf_insns = icode_to_fcode(root, &len);
509478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	program->bf_len = len;
510478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
511478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	lex_cleanup();
512478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	freechunks();
513d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
514d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	rc = 0;  /* We're all okay */
515d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
516d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesquit:
517d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
518d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes#ifdef WIN32
519d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	LeaveCriticalSection(&g_PcapCompileCriticalSection);
520d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes#endif
521d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
522d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	return (rc);
523478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
524478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
525478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
526478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * entry point for using the compiler with no pcap open
527478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * pass in all the stuff that is needed explicitly instead.
528478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
529478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectint
530478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectpcap_compile_nopcap(int snaplen_arg, int linktype_arg,
531478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    struct bpf_program *program,
532478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	     const char *buf, int optimize, bpf_u_int32 mask)
533478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
534478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	pcap_t *p;
535478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int ret;
536478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
537478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	p = pcap_open_dead(linktype_arg, snaplen_arg);
538478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (p == NULL)
539478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return (-1);
540478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	ret = pcap_compile(p, program, buf, optimize, mask);
541478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	pcap_close(p);
542478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (ret);
543478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
544478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
545478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
546478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Clean up a "struct bpf_program" by freeing all the memory allocated
547478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * in it.
548478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
549478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectvoid
550478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectpcap_freecode(struct bpf_program *program)
551478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
552478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	program->bf_len = 0;
553478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (program->bf_insns != NULL) {
554478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		free((char *)program->bf_insns);
555478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		program->bf_insns = NULL;
556478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
557478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
558478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
559478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
560478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Backpatch the blocks in 'list' to 'target'.  The 'sense' field indicates
561478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * which of the jt and jf fields has been resolved and which is a pointer
562478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * back to another unresolved block (or nil).  At least one of the fields
563478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * in each block is already resolved.
564478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
565478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic void
566478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectbackpatch(list, target)
567478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *list, *target;
568478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
569478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *next;
570478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
571478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	while (list) {
572478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (!list->sense) {
573478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			next = JT(list);
574478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			JT(list) = target;
575478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		} else {
576478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			next = JF(list);
577478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			JF(list) = target;
578478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
579478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		list = next;
580478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
581478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
582478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
583478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
584478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Merge the lists in b0 and b1, using the 'sense' field to indicate
585478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * which of jt and jf is the link.
586478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
587478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic void
588478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectmerge(b0, b1)
589478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1;
590478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
591478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct block **p = &b0;
592478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
593478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* Find end of list. */
594478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	while (*p)
595478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		p = !((*p)->sense) ? &JT(*p) : &JF(*p);
596478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
597478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* Concatenate the lists. */
598478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	*p = b1;
599478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
600478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
601478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectvoid
602478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectfinish_parse(p)
603478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *p;
604478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
605478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *ppi_dlt_check;
606478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
607478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
608478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * Insert before the statements of the first (root) block any
609478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * statements needed to load the lengths of any variable-length
610478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * headers into registers.
611478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 *
612478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * XXX - a fancier strategy would be to insert those before the
613478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * statements of all blocks that use those lengths and that
614478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * have no predecessors that use them, so that we only compute
615478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * the lengths if we need them.  There might be even better
616511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * approaches than that.
617511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
618511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * However, those strategies would be more complicated, and
619511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * as we don't generate code to compute a length if the
620511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * program has no tests that use the length, and as most
621511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * tests will probably use those lengths, we would just
622511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * postpone computing the lengths so that it's not done
623511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * for tests that fail early, and it's not clear that's
624511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * worth the effort.
625511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
626511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	insert_compute_vloffsets(p->head);
627d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
628511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
629511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * For DLT_PPI captures, generate a check of the per-packet
630511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * DLT value to make sure it's DLT_IEEE802_11.
631478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
632511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ppi_dlt_check = gen_ppi_dlt_check();
633511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ppi_dlt_check != NULL)
634511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_and(ppi_dlt_check, p);
635478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
636511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	backpatch(p, gen_retblk(snaplen));
637511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	p->sense = !p->sense;
638511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	backpatch(p, gen_retblk(0));
639511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	root = p->head;
640478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
641478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
642478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectvoid
643478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_and(b0, b1)
644478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1;
645478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
646478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	backpatch(b0, b1->head);
647478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b0->sense = !b0->sense;
648478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b1->sense = !b1->sense;
649478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	merge(b1, b0);
650478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b1->sense = !b1->sense;
651478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b1->head = b0->head;
652478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
653478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
654478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectvoid
655478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_or(b0, b1)
656478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1;
657478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
658478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b0->sense = !b0->sense;
659478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	backpatch(b0, b1->head);
660478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b0->sense = !b0->sense;
661478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	merge(b1, b0);
662478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b1->head = b0->head;
663478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
664478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
665478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectvoid
666478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_not(b)
667478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b;
668478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
669478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b->sense = !b->sense;
670478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
671478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
672478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
673478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_cmp(offrel, offset, size, v)
674478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	enum e_offrel offrel;
675478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int offset, size;
676478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_int32 v;
677478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
678478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v);
679478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
680478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
681478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
682478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_cmp_gt(offrel, offset, size, v)
683478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	enum e_offrel offrel;
684478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int offset, size;
685478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_int32 v;
686478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
687478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 0, v);
688478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
689478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
690478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
691478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_cmp_ge(offrel, offset, size, v)
692478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	enum e_offrel offrel;
693478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int offset, size;
694478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_int32 v;
695478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
696478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 0, v);
697478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
698478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
699478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
700478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_cmp_lt(offrel, offset, size, v)
701478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	enum e_offrel offrel;
702478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int offset, size;
703478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_int32 v;
704478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
705478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 1, v);
706478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
707478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
708478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
709478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_cmp_le(offrel, offset, size, v)
710478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	enum e_offrel offrel;
711478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int offset, size;
712478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_int32 v;
713478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
714478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 1, v);
715478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
716478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
717478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
718478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_mcmp(offrel, offset, size, v, mask)
719478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	enum e_offrel offrel;
720478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int offset, size;
721478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_int32 v;
722478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 mask;
723478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
724478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return gen_ncmp(offrel, offset, size, mask, BPF_JEQ, 0, v);
725478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
726478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
727478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
728478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_bcmp(offrel, offset, size, v)
729478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	enum e_offrel offrel;
730478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register u_int offset, size;
731478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register const u_char *v;
732478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
733478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct block *b, *tmp;
734478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
735478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b = NULL;
736478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	while (size >= 4) {
737478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		register const u_char *p = &v[size - 4];
738478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_int32 w = ((bpf_int32)p[0] << 24) |
739478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    ((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3];
740478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
741478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_cmp(offrel, offset + size - 4, BPF_W, w);
742478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (b != NULL)
743478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_and(b, tmp);
744478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b = tmp;
745478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		size -= 4;
746478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
747478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	while (size >= 2) {
748478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		register const u_char *p = &v[size - 2];
749478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_int32 w = ((bpf_int32)p[0] << 8) | p[1];
750478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
751478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_cmp(offrel, offset + size - 2, BPF_H, w);
752478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (b != NULL)
753478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_and(b, tmp);
754478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b = tmp;
755478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		size -= 2;
756478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
757478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (size > 0) {
758478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_cmp(offrel, offset, BPF_B, (bpf_int32)v[0]);
759478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (b != NULL)
760478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_and(b, tmp);
761478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b = tmp;
762478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
763478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b;
764478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
765478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
766478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
767478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * AND the field of size "size" at offset "offset" relative to the header
768478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * specified by "offrel" with "mask", and compare it with the value "v"
769478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * with the test specified by "jtype"; if "reverse" is true, the test
770478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * should test the opposite of "jtype".
771478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
772478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
773478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_ncmp(offrel, offset, size, mask, jtype, reverse, v)
774478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	enum e_offrel offrel;
775478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_int32 v;
776478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 offset, size, mask, jtype;
777478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int reverse;
778478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
779478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s, *s2;
780478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b;
781478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
782478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s = gen_load_a(offrel, offset, size);
783478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
784478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (mask != 0xffffffff) {
785478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
786478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2->s.k = mask;
787478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s, s2);
788478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
789478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
790478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b = new_block(JMP(jtype));
791478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b->stmts = s;
792478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b->s.k = v;
793478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE))
794478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_not(b);
795478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b;
796478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
797478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
798478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
799d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * Various code constructs need to know the layout of the packet.
800d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * These variables give the necessary offsets from the beginning
801478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * of the packet data.
802478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
803478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
804478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
805d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * Absolute offset of the beginning of the link-layer header.
806478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
807d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic bpf_abs_offset off_linkhdr;
808478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
809478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
810d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * If we're checking a link-layer header for a packet encapsulated in
811d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * another protocol layer, this is the equivalent information for the
812d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * previous layers' link-layer header from the beginning of the raw
813d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * packet data.
814478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
815d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic bpf_abs_offset off_prevlinkhdr;
816478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
817478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
818d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * This is the equivalent information for the outermost layers' link-layer
819d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * header.
820511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
821d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic bpf_abs_offset off_outermostlinkhdr;
822511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
823511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
824d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * "Push" the current value of the link-layer header type and link-layer
825d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * header offset onto a "stack", and set a new value.  (It's not a
826d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * full-blown stack; we keep only the top two items.)
827511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
828d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes#define PUSH_LINKHDR(new_linktype, new_is_variable, new_constant_part, new_reg) \
829d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes{ \
830d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	prevlinktype = new_linktype; \
831d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_prevlinkhdr = off_linkhdr; \
832d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	linktype = new_linktype; \
833d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linkhdr.is_variable = new_is_variable; \
834d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linkhdr.constant_part = new_constant_part; \
835d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linkhdr.reg = new_reg; \
836d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	is_geneve = 0; \
837d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes}
838511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
839511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
840d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * Absolute offset of the beginning of the link-layer payload.
841511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
842d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic bpf_abs_offset off_linkpl;
843511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
844511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
845478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * "off_linktype" is the offset to information in the link-layer header
846d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * giving the packet type. This is an absolute offset from the beginning
847d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * of the packet.
848478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
849d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * For Ethernet, it's the offset of the Ethernet type field; this
850d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * means that it must have a value that skips VLAN tags.
851478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
852478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * For link-layer types that always use 802.2 headers, it's the
853d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * offset of the LLC header; this means that it must have a value
854d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * that skips VLAN tags.
855478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
856478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * For PPP, it's the offset of the PPP type field.
857478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
858478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * For Cisco HDLC, it's the offset of the CHDLC type field.
859478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
860478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * For BSD loopback, it's the offset of the AF_ value.
861478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
862478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * For Linux cooked sockets, it's the offset of the type field.
863478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
864d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * off_linktype.constant_part is set to -1 for no encapsulation,
865d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * in which case, IP is assumed.
866478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
867d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic bpf_abs_offset off_linktype;
868511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
869511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
870478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * TRUE if the link layer includes an ATM pseudo-header.
871478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
872478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int is_atm = 0;
873478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
874478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
875d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * TRUE if "geneve" appeared in the filter; it causes us to generate
876d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * code that checks for a Geneve header and assume that later filters
877d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * apply to the encapsulated payload.
878478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
879d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic int is_geneve = 0;
880478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
881478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
882478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * These are offsets for the ATM pseudo-header.
883478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
884478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic u_int off_vpi;
885478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic u_int off_vci;
886478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic u_int off_proto;
887478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
888478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
889478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * These are offsets for the MTP2 fields.
890478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
891478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic u_int off_li;
892511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic u_int off_li_hsl;
893478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
894478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
895478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * These are offsets for the MTP3 fields.
896478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
897478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic u_int off_sio;
898478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic u_int off_opc;
899478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic u_int off_dpc;
900478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic u_int off_sls;
901478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
902478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
903478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * This is the offset of the first byte after the ATM pseudo_header,
904478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * or -1 if there is no ATM pseudo-header.
905478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
906478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic u_int off_payload;
907478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
908478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
909478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * These are offsets to the beginning of the network-layer header.
910d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * They are relative to the beginning of the link-layer payload (i.e.,
911d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * they don't include off_linkhdr.constant_part or off_linkpl.constant_part).
912478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
913478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * If the link layer never uses 802.2 LLC:
914478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
915478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	"off_nl" and "off_nl_nosnap" are the same.
916478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
917478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * If the link layer always uses 802.2 LLC:
918478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
919478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	"off_nl" is the offset if there's a SNAP header following
920478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	the 802.2 header;
921478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
922478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	"off_nl_nosnap" is the offset if there's no SNAP header.
923478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
924478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * If the link layer is Ethernet:
925478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
926478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	"off_nl" is the offset if the packet is an Ethernet II packet
927478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	(we assume no 802.3+802.2+SNAP);
928478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
929478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	"off_nl_nosnap" is the offset if the packet is an 802.3 packet
930478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	with an 802.2 header following it.
931478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
932478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic u_int off_nl;
933478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic u_int off_nl_nosnap;
934478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
935478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int linktype;
936d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic int prevlinktype;
937d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic int outermostlinktype;
938478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
939478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic void
940478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectinit_linktype(p)
941478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	pcap_t *p;
942478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
943478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	pcap_fddipad = p->fddipad;
944478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
945478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
946d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * We start out with only one link-layer header.
947d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 */
948d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	outermostlinktype = pcap_datalink(p);
949d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_outermostlinkhdr.constant_part = 0;
950d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_outermostlinkhdr.is_variable = 0;
951d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_outermostlinkhdr.reg = -1;
952d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
953d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	prevlinktype = outermostlinktype;
954d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_prevlinkhdr.constant_part = 0;
955d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_prevlinkhdr.is_variable = 0;
956d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_prevlinkhdr.reg = -1;
957d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
958d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	linktype = outermostlinktype;
959d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linkhdr.constant_part = 0;
960d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linkhdr.is_variable = 0;
961d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linkhdr.reg = -1;
962d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
963d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/*
964d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * XXX
965d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 */
966d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linkpl.constant_part = 0;
967d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linkpl.is_variable = 0;
968d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linkpl.reg = -1;
969d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
970d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linktype.constant_part = 0;
971d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linktype.is_variable = 0;
972d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linktype.reg = -1;
973d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
974d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/*
975478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * Assume it's not raw ATM with a pseudo-header, for now.
976478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
977478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	is_atm = 0;
978478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	off_vpi = -1;
979478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	off_vci = -1;
980478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	off_proto = -1;
981478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	off_payload = -1;
982478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
983478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
984d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * And not Geneve.
985511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
986d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	is_geneve = 0;
987511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
988511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
989478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * And assume we're not doing SS7.
990478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
991478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	off_li = -1;
992511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	off_li_hsl = -1;
993478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	off_sio = -1;
994478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	off_opc = -1;
995478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	off_dpc = -1;
996478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	off_sls = -1;
997478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
998478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        label_stack_depth = 0;
999d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        vlan_stack_depth = 0;
1000478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1001478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (linktype) {
1002478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1003478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_ARCNET:
1004d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 2;
1005d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 6;
1006511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;		/* XXX in reality, variable! */
1007511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 0;	/* no 802.2 LLC */
1008d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1009478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1010478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_ARCNET_LINUX:
1011d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 4;
1012d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 8;
1013511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;		/* XXX in reality, variable! */
1014511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 0;	/* no 802.2 LLC */
1015d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1016478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1017478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_EN10MB:
1018d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 12;
1019d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 14;	/* Ethernet header length */
1020511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;		/* Ethernet II */
1021511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 3;	/* 802.3+802.2 */
1022d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1023478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1024478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_SLIP:
1025478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1026478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * SLIP doesn't have a link level type.  The 16 byte
1027478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * header is hacked into our SLIP driver.
1028478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1029d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = -1;
1030d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 16;
1031511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1032511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 0;	/* no 802.2 LLC */
1033d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1034478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1035478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_SLIP_BSDOS:
1036478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* XXX this may be the same as the DLT_PPP_BSDOS case */
1037d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = -1;
1038478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* XXX end */
1039d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 24;
1040511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1041511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 0;	/* no 802.2 LLC */
1042d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1043478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1044478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_NULL:
1045478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_LOOP:
1046d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 0;
1047d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 4;
1048511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1049511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 0;	/* no 802.2 LLC */
1050d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1051478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1052478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_ENC:
1053d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 0;
1054d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 12;
1055511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1056511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 0;	/* no 802.2 LLC */
1057d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1058478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1059478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_PPP:
1060478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_PPP_PPPD:
1061478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_C_HDLC:		/* BSD/OS Cisco HDLC */
1062478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_PPP_SERIAL:		/* NetBSD sync/async serial PPP */
1063d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 2;	/* skip HDLC-like framing */
1064d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 4;	/* skip HDLC-like framing and protocol field */
1065511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1066511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 0;	/* no 802.2 LLC */
1067d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1068478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1069478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_PPP_ETHER:
1070478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1071478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * This does no include the Ethernet header, and
1072478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * only covers session state.
1073478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1074d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 6;
1075d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 8;
1076511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1077511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 0;	/* no 802.2 LLC */
1078d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1079478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1080478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_PPP_BSDOS:
1081d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 5;
1082d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 24;
1083511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1084511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 0;	/* no 802.2 LLC */
1085d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1086478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1087478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_FDDI:
1088478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1089478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * FDDI doesn't really have a link-level type field.
1090478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * We set "off_linktype" to the offset of the LLC header.
1091478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1092478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * To check for Ethernet types, we assume that SSAP = SNAP
1093478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * is being used and pick out the encapsulated Ethernet type.
1094478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - should we generate code to check for SNAP?
1095478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1096d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 13;
1097d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part += pcap_fddipad;
1098d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 13;	/* FDDI MAC header length */
1099d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part += pcap_fddipad;
1100511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 8;		/* 802.2+SNAP */
1101511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 3;	/* 802.2 */
1102d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1103478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1104478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_IEEE802:
1105478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1106478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Token Ring doesn't really have a link-level type field.
1107478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * We set "off_linktype" to the offset of the LLC header.
1108478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1109478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * To check for Ethernet types, we assume that SSAP = SNAP
1110478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * is being used and pick out the encapsulated Ethernet type.
1111478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - should we generate code to check for SNAP?
1112478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1113478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - the header is actually variable-length.
1114478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Some various Linux patched versions gave 38
1115478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * as "off_linktype" and 40 as "off_nl"; however,
1116478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * if a token ring packet has *no* routing
1117478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * information, i.e. is not source-routed, the correct
1118478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * values are 20 and 22, as they are in the vanilla code.
1119478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1120478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * A packet is source-routed iff the uppermost bit
1121478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * of the first byte of the source address, at an
1122478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * offset of 8, has the uppermost bit set.  If the
1123478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * packet is source-routed, the total number of bytes
1124478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * of routing information is 2 plus bits 0x1F00 of
1125478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the 16-bit value at an offset of 14 (shifted right
1126478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * 8 - figure out which byte that is).
1127478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1128d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 14;
1129d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 14;	/* Token Ring MAC header length */
1130511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 8;		/* 802.2+SNAP */
1131511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 3;	/* 802.2 */
1132d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1133478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1134511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_PRISM_HEADER:
1135511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_11_RADIO_AVS:
1136511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_11_RADIO:
1137d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkhdr.is_variable = 1;
1138d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		/* Fall through, 802.11 doesn't have a variable link
1139d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * prefix but is otherwise the same. */
1140d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
1141d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_IEEE802_11:
1142478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1143478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * 802.11 doesn't really have a link-level type field.
1144d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * We set "off_linktype.constant_part" to the offset of
1145d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * the LLC header.
1146478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1147478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * To check for Ethernet types, we assume that SSAP = SNAP
1148478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * is being used and pick out the encapsulated Ethernet type.
1149478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - should we generate code to check for SNAP?
1150478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1151511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * We also handle variable-length radio headers here.
1152511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * The Prism header is in theory variable-length, but in
1153511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * practice it's always 144 bytes long.  However, some
1154511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * drivers on Linux use ARPHRD_IEEE80211_PRISM, but
1155511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * sometimes or always supply an AVS header, so we
1156511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * have to check whether the radio header is a Prism
1157511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * header or an AVS header, so, in practice, it's
1158511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * variable-length.
1159478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1160d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 24;
1161d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 0;	/* link-layer header is variable-length */
1162d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.is_variable = 1;
1163511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 8;		/* 802.2+SNAP */
1164511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 3;	/* 802.2 */
1165d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1166478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1167478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_PPI:
1168d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		/*
1169511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * At the moment we treat PPI the same way that we treat
1170511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * normal Radiotap encoded packets. The difference is in
1171511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the function that generates the code at the beginning
1172511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * to compute the header length.  Since this code generator
1173511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * of PPI supports bare 802.11 encapsulation only (i.e.
1174511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the encapsulated DLT should be DLT_IEEE802_11) we
1175511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * generate code to check for this too.
1176478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1177d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 24;
1178d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 0;	/* link-layer header is variable-length */
1179d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.is_variable = 1;
1180d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkhdr.is_variable = 1;
1181511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 8;		/* 802.2+SNAP */
1182511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 3;	/* 802.2 */
1183d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1184478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1185478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_ATM_RFC1483:
1186478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_ATM_CLIP:	/* Linux ATM defines this */
1187478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1188478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * assume routed, non-ISO PDUs
1189478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00)
1190478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1191478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - what about ISO PDUs, e.g. CLNP, ISIS, ESIS,
1192478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * or PPP with the PPP NLPID (e.g., PPPoA)?  The
1193478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * latter would presumably be treated the way PPPoE
1194478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * should be, so you can do "pppoe and udp port 2049"
1195478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * or "pppoa and tcp port 80" and have it check for
1196478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * PPPo{A,E} and a PPP protocol of IP and....
1197478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1198d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 0;
1199d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 0;	/* packet begins with LLC header */
1200478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl = 8;		/* 802.2+SNAP */
1201478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl_nosnap = 3;	/* 802.2 */
1202d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1203478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1204478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_SUNATM:
1205478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1206478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Full Frontal ATM; you get AALn PDUs with an ATM
1207478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * pseudo-header.
1208478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1209478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		is_atm = 1;
1210478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_vpi = SUNATM_VPI_POS;
1211478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_vci = SUNATM_VCI_POS;
1212478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_proto = PROTO_POS;
1213478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_payload = SUNATM_PKT_BEGIN_POS;
1214d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = off_payload;
1215d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = off_payload;	/* if LLC-encapsulated */
1216511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 8;		/* 802.2+SNAP */
1217511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 3;	/* 802.2 */
1218d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1219478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1220478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_RAW:
1221511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IPV4:
1222511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IPV6:
1223d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = -1;
1224d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 0;
1225478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl = 0;
1226478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl_nosnap = 0;	/* no 802.2 LLC */
1227d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1228478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1229478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_LINUX_SLL:	/* fake header for Linux cooked socket */
1230d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 14;
1231d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 16;
1232511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1233511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 0;	/* no 802.2 LLC */
1234d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1235478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1236478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_LTALK:
1237478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1238478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * LocalTalk does have a 1-byte type field in the LLAP header,
1239478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * but really it just indicates whether there is a "short" or
1240478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * "long" DDP packet following.
1241478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1242d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = -1;
1243d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 0;
1244478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl = 0;
1245478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl_nosnap = 0;	/* no 802.2 LLC */
1246d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1247478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1248478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_IP_OVER_FC:
1249478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1250478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * RFC 2625 IP-over-Fibre-Channel doesn't really have a
1251478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * link-level type field.  We set "off_linktype" to the
1252478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * offset of the LLC header.
1253478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1254478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * To check for Ethernet types, we assume that SSAP = SNAP
1255478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * is being used and pick out the encapsulated Ethernet type.
1256478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - should we generate code to check for SNAP? RFC
1257478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * 2625 says SNAP should be used.
1258478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1259d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 16;
1260d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 16;
1261511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 8;		/* 802.2+SNAP */
1262511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 3;	/* 802.2 */
1263d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1264478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1265478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_FRELAY:
1266478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1267478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - we should set this to handle SNAP-encapsulated
1268478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * frames (NLPID of 0x80).
1269478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1270d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = -1;
1271d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 0;
1272478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl = 0;
1273478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl_nosnap = 0;	/* no 802.2 LLC */
1274d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1275478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1276478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                /*
1277478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                 * the only BPF-interesting FRF.16 frames are non-control frames;
1278478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                 * Frame Relay has a variable length link-layer
1279478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                 * so lets start with offset 4 for now and increments later on (FIXME);
1280478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                 */
1281478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_MFR:
1282d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = -1;
1283d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 0;
1284478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl = 4;
1285478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl_nosnap = 0;	/* XXX - for now -> no 802.2 LLC */
1286d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1287478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1288478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_APPLE_IP_OVER_IEEE1394:
1289d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 16;
1290d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 18;
1291511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1292511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 0;	/* no 802.2 LLC */
1293d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1294478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1295478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_SYMANTEC_FIREWALL:
1296d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 6;
1297d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 44;
1298511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;		/* Ethernet II */
1299511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 0;	/* XXX - what does it do with 802.3 packets? */
1300d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1301478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1302478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef HAVE_NET_PFVAR_H
1303478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_PFLOG:
1304d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 0;
1305d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = PFLOG_HDRLEN;
1306511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1307511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 0;	/* no 802.2 LLC */
1308d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1309478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
1310478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1311478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_MFR:
1312478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_MLFR:
1313478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_MLPPP:
1314478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_PPP:
1315478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_CHDLC:
1316478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_FRELAY:
1317d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                off_linktype.constant_part = 4;
1318d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 4;
1319511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1320478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl_nosnap = -1;	/* no 802.2 LLC */
1321d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                break;
1322478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1323478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_ATM1:
1324d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 4;		/* in reality variable between 4-8 */
1325d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 4;	/* in reality variable between 4-8 */
1326511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1327511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 10;
1328d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1329478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1330478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_ATM2:
1331d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 8;		/* in reality variable between 8-12 */
1332d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 8;	/* in reality variable between 8-12 */
1333511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1334511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 10;
1335d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1336478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1337478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* frames captured on a Juniper PPPoE service PIC
1338478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * contain raw ethernet frames */
1339478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_PPPOE:
1340478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_ETHER:
1341d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        	off_linkpl.constant_part = 14;
1342d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 16;
1343478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl = 18;		/* Ethernet II */
1344478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl_nosnap = 21;	/* 802.3+802.2 */
1345d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1346478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1347478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_PPPOE_ATM:
1348d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 4;
1349d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 6;
1350511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1351511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = -1;	/* no 802.2 LLC */
1352d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1353478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1354478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_GGSN:
1355d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 6;
1356d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 12;
1357511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1358511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = -1;	/* no 802.2 LLC */
1359d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1360478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1361478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_ES:
1362d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 6;
1363d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = -1;	/* not really a network layer but raw IP addresses */
1364511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = -1;		/* not really a network layer but raw IP addresses */
1365478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl_nosnap = -1;	/* no 802.2 LLC */
1366d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1367478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1368478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_MONITOR:
1369d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 12;
1370d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 12;
1371511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;		/* raw IP/IP6 header */
1372478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl_nosnap = -1;	/* no 802.2 LLC */
1373d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1374478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1375511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_BACNET_MS_TP:
1376d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = -1;
1377d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = -1;
1378511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = -1;
1379511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = -1;
1380d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1381511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1382478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_SERVICES:
1383d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 12;
1384d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = -1;	/* L3 proto location dep. on cookie type */
1385478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl = -1;		/* L3 proto location dep. on cookie type */
1386478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl_nosnap = -1;	/* no 802.2 LLC */
1387d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1388478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1389478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_VP:
1390d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 18;
1391d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = -1;
1392511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = -1;
1393511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = -1;
1394d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1395511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1396511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_JUNIPER_ST:
1397d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 18;
1398d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = -1;
1399511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = -1;
1400511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = -1;
1401d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1402511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1403511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_JUNIPER_ISM:
1404d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 8;
1405d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = -1;
1406511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = -1;
1407511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = -1;
1408d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1409511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1410511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_JUNIPER_VS:
1411511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_JUNIPER_SRX_E2E:
1412511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_JUNIPER_FIBRECHANNEL:
1413511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_JUNIPER_ATM_CEMIC:
1414d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 8;
1415d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = -1;
1416478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl = -1;
1417478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl_nosnap = -1;
1418d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1419478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1420478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_MTP2:
1421478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_li = 2;
1422511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_li_hsl = 4;
1423478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_sio = 3;
1424478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_opc = 4;
1425478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_dpc = 4;
1426478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_sls = 7;
1427d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = -1;
1428d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = -1;
1429478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl = -1;
1430478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl_nosnap = -1;
1431d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1432478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1433478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_MTP2_WITH_PHDR:
1434478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_li = 6;
1435511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_li_hsl = 8;
1436478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_sio = 7;
1437478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_opc = 8;
1438478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_dpc = 8;
1439478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_sls = 11;
1440d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = -1;
1441d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = -1;
1442478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl = -1;
1443478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl_nosnap = -1;
1444d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1445478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1446511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_ERF:
1447511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_li = 22;
1448511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_li_hsl = 24;
1449511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_sio = 23;
1450511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_opc = 24;
1451511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_dpc = 24;
1452511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_sls = 27;
1453d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = -1;
1454d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = -1;
1455511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = -1;
1456511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = -1;
1457d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1458478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1459511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_PFSYNC:
1460d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = -1;
1461d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 4;
1462511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1463511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 0;
1464d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1465478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1466511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_AX25_KISS:
1467478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1468478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Currently, only raw "link[N:M]" filtering is supported.
1469478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1470d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = -1;	/* variable, min 15, max 71 steps of 7 */
1471d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = -1;
1472511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = -1;		/* variable, min 16, max 71 steps of 7 */
1473511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = -1;	/* no 802.2 LLC */
1474d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1475511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1476511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IPNET:
1477d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = 1;
1478d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = 24;	/* ipnet header length */
1479511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;
1480478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		off_nl_nosnap = -1;
1481d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1482478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1483511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_NETANALYZER:
1484d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkhdr.constant_part = 4;	/* Ethernet header is past 4-byte pseudo-header */
1485d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = off_linkhdr.constant_part + 12;
1486d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = off_linkhdr.constant_part + 14;	/* pseudo-header+Ethernet header length */
1487511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;		/* Ethernet II */
1488511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 3;	/* 802.3+802.2 */
1489d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1490511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1491511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_NETANALYZER_TRANSPARENT:
1492d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkhdr.constant_part = 12;	/* MAC header is past 4-byte pseudo-header, preamble, and SFD */
1493d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = off_linkhdr.constant_part + 12;
1494d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = off_linkhdr.constant_part + 14;	/* pseudo-header+preamble+SFD+Ethernet header length */
1495511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;		/* Ethernet II */
1496511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 3;	/* 802.3+802.2 */
1497d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1498511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1499511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	default:
1500478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1501511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * For values in the range in which we've assigned new
1502511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * DLT_ values, only raw "link[N:M]" filtering is supported.
1503478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1504511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (linktype >= DLT_MATCHING_MIN &&
1505511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    linktype <= DLT_MATCHING_MAX) {
1506d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			off_linktype.constant_part = -1;
1507d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			off_linkpl.constant_part = -1;
1508511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			off_nl = -1;
1509511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			off_nl_nosnap = -1;
1510d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		} else {
1511d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			bpf_error("unknown data link type %d", linktype);
1512511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1513d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1514478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
1515478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1516d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_outermostlinkhdr = off_prevlinkhdr = off_linkhdr;
1517478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
1518478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1519511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
1520d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * Load a value relative to the specified absolute offset.
1521511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
1522511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct slist *
1523d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_load_absoffsetrel(bpf_abs_offset *abs_offset, u_int offset, u_int size)
1524511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
1525511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct slist *s, *s2;
1526511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1527d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s = gen_abs_offset_varpart(abs_offset);
1528511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1529511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
1530d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * If "s" is non-null, it has code to arrange that the X register
1531d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * contains the variable part of the absolute offset, so we
1532d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * generate a load relative to that, with an offset of
1533d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * abs_offset->constant_part + offset.
1534511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
1535d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * Otherwise, we can do an absolute load with an offset of
1536d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * abs_offset->constant_part + offset.
1537511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
1538511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (s != NULL) {
1539511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
1540d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * "s" points to a list of statements that puts the
1541d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * variable part of the absolute offset into the X register.
1542d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * Do an indirect load, to use the X register as an offset.
1543511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
1544511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2 = new_stmt(BPF_LD|BPF_IND|size);
1545d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s2->s.k = abs_offset->constant_part + offset;
1546511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s, s2);
1547511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else {
1548511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
1549d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * There is no variable part of the absolute offset, so
1550d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * just do an absolute load.
1551511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
1552511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s = new_stmt(BPF_LD|BPF_ABS|size);
1553d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s->s.k = abs_offset->constant_part + offset;
1554511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1555511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return s;
1556511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
1557478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1558478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
1559478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Load a value relative to the beginning of the specified header.
1560478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
1561478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct slist *
1562478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_load_a(offrel, offset, size)
1563478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	enum e_offrel offrel;
1564478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int offset, size;
1565478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
1566478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s, *s2;
1567478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1568478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (offrel) {
1569478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1570478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case OR_PACKET:
1571478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                s = new_stmt(BPF_LD|BPF_ABS|size);
1572478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                s->s.k = offset;
1573478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
1574478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1575d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case OR_LINKHDR:
1576d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_absoffsetrel(&off_linkhdr, offset, size);
1577478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
1578478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1579d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case OR_PREVLINKHDR:
1580d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_absoffsetrel(&off_prevlinkhdr, offset, size);
1581511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
1582511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1583d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case OR_LLC:
1584d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_absoffsetrel(&off_linkpl, offset, size);
1585478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
1586478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1587d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case OR_PREVMPLSHDR:
1588d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_absoffsetrel(&off_linkpl, off_nl - 4 + offset, size);
1589d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1590d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
1591d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case OR_LINKPL:
1592d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_absoffsetrel(&off_linkpl, off_nl + offset, size);
1593d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1594d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
1595d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case OR_LINKPL_NOSNAP:
1596d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_absoffsetrel(&off_linkpl, off_nl_nosnap + offset, size);
1597d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
1598d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
1599d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case OR_LINKTYPE:
1600d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_absoffsetrel(&off_linktype, offset, size);
1601478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
1602478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1603478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case OR_TRAN_IPV4:
1604478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1605478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Load the X register with the length of the IPv4 header
1606478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * (plus the offset of the link-layer header, if it's
1607478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * preceded by a variable-length header such as a radio
1608478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * header), in bytes.
1609478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1610478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s = gen_loadx_iphdrlen();
1611478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1612478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1613d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * Load the item at {offset of the link-layer payload} +
1614d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * {offset, relative to the start of the link-layer
1615511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * paylod, of the IPv4 header} + {length of the IPv4 header} +
1616478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * {specified offset}.
1617478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1618d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * If the offset of the link-layer payload is variable,
1619d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * the variable part of that offset is included in the
1620d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * value in the X register, and we include the constant
1621d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * part in the offset of the load.
1622478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1623478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_LD|BPF_IND|size);
1624d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s2->s.k = off_linkpl.constant_part + off_nl + offset;
1625478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s, s2);
1626478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
1627478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1628478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case OR_TRAN_IPV6:
1629d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_absoffsetrel(&off_linkpl, off_nl + 40 + offset, size);
1630478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
1631478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1632478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
1633478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
1634478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return NULL;
1635478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
1636478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return s;
1637478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
1638478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1639478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
1640478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Generate code to load into the X register the sum of the length of
1641d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * the IPv4 header and the variable part of the offset of the link-layer
1642d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * payload.
1643478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
1644478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct slist *
1645478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_loadx_iphdrlen()
1646478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
1647478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s, *s2;
1648478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1649d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s = gen_abs_offset_varpart(&off_linkpl);
1650478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (s != NULL) {
1651478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1652d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * The offset of the link-layer payload has a variable
1653d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * part.  "s" points to a list of statements that put
1654d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * the variable part of that offset into the X register.
1655511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
1656478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * The 4*([k]&0xf) addressing mode can't be used, as we
1657478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * don't have a constant offset, so we have to load the
1658478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * value in question into the A register and add to it
1659478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the value from the X register.
1660478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1661478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
1662d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s2->s.k = off_linkpl.constant_part + off_nl;
1663478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s, s2);
1664478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
1665478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2->s.k = 0xf;
1666478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s, s2);
1667478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
1668478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2->s.k = 2;
1669478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s, s2);
1670478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1671478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1672d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * The A register now contains the length of the IP header.
1673d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * We need to add to it the variable part of the offset of
1674d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * the link-layer payload, which is still in the X
1675511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * register, and move the result into the X register.
1676478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1677478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
1678478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s, new_stmt(BPF_MISC|BPF_TAX));
1679478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	} else {
1680478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1681d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * The offset of the link-layer payload is a constant,
1682d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * so no code was generated to load the (non-existent)
1683d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * variable part of that offset.
1684d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 *
1685d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * This means we can use the 4*([k]&0xf) addressing
1686d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * mode.  Load the length of the IPv4 header, which
1687d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * is at an offset of off_nl from the beginning of
1688d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * the link-layer payload, and thus at an offset of
1689d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * off_linkpl.constant_part + off_nl from the beginning
1690d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * of the raw packet data, using that addressing mode.
1691478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1692478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
1693d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s->s.k = off_linkpl.constant_part + off_nl;
1694478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
1695478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return s;
1696478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
1697478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1698478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
1699478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_uncond(rsense)
1700478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int rsense;
1701478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
1702478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b;
1703478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s;
1704478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1705478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s = new_stmt(BPF_LD|BPF_IMM);
1706478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s->s.k = !rsense;
1707478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b = new_block(JMP(BPF_JEQ));
1708478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b->stmts = s;
1709478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1710478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b;
1711478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
1712478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1713478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic inline struct block *
1714478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_true()
1715478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
1716478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return gen_uncond(1);
1717478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
1718478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1719478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic inline struct block *
1720478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_false()
1721478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
1722478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return gen_uncond(0);
1723478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
1724478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1725478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
1726478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Byte-swap a 32-bit number.
1727478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * ("htonl()" or "ntohl()" won't work - we want to byte-swap even on
1728478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * big-endian platforms.)
1729478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
1730478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define	SWAPLONG(y) \
1731478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
1732478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1733478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
1734478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Generate code to match a particular packet type.
1735478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
1736478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
1737478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * value, if <= ETHERMTU.  We use that to determine whether to
1738478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * match the type/length field or to check the type/length field for
1739478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * a value <= ETHERMTU to see whether it's a type field and then do
1740478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * the appropriate test.
1741478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
1742478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
1743478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_ether_linktype(proto)
1744478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int proto;
1745478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
1746478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1;
1747478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1748478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (proto) {
1749478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1750478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case LLCSAP_ISONS:
1751478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case LLCSAP_IP:
1752478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case LLCSAP_NETBEUI:
1753478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1754478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * OSI protocols and NetBEUI always use 802.2 encapsulation,
1755478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * so we check the DSAP and SSAP.
1756478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1757478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * LLCSAP_IP checks for IP-over-802.2, rather
1758478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * than IP-over-Ethernet or IP-over-SNAP.
1759478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1760478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - should we check both the DSAP and the
1761478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * SSAP, like this, or should we check just the
1762478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * DSAP, as we do for other types <= ETHERMTU
1763478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * (i.e., other SAP values)?
1764478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1765d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
1766478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_not(b0);
1767d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32)
1768478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			     ((proto << 8) | proto));
1769478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
1770478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
1771478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1772478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case LLCSAP_IPX:
1773478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1774478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Check for;
1775478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1776478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	Ethernet_II frames, which are Ethernet
1777478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	frames with a frame type of ETHERTYPE_IPX;
1778478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1779478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	Ethernet_802.3 frames, which are 802.3
1780478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	frames (i.e., the type/length field is
1781478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	a length field, <= ETHERMTU, rather than
1782478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	a type field) with the first two bytes
1783478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	after the Ethernet/802.3 header being
1784478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	0xFFFF;
1785478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1786478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	Ethernet_802.2 frames, which are 802.3
1787478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	frames with an 802.2 LLC header and
1788478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	with the IPX LSAP as the DSAP in the LLC
1789478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	header;
1790478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1791478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	Ethernet_SNAP frames, which are 802.3
1792478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	frames with an LLC header and a SNAP
1793478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	header and with an OUI of 0x000000
1794478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	(encapsulated Ethernet) and a protocol
1795478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	ID of ETHERTYPE_IPX in the SNAP header.
1796478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1797478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - should we generate the same code both
1798478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * for tests for LLCSAP_IPX and for ETHERTYPE_IPX?
1799478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1800478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1801478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1802478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * This generates code to check both for the
1803478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3.
1804478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1805d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp(OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
1806d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
1807478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
1808478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1809478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1810478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now we add code to check for SNAP frames with
1811478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * ETHERTYPE_IPX, i.e. Ethernet_SNAP.
1812478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1813511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b0 = gen_snap(0x000000, ETHERTYPE_IPX);
1814478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
1815478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1816478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1817478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now we generate code to check for 802.3
1818478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * frames in general.
1819478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1820d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
1821478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_not(b0);
1822478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1823478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1824478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now add the check for 802.3 frames before the
1825478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * check for Ethernet_802.2 and Ethernet_802.3,
1826478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * as those checks should only be done on 802.3
1827478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * frames, not on Ethernet frames.
1828478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1829478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
1830478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1831478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1832478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now add the check for Ethernet_II frames, and
1833478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * do that before checking for the other frame
1834478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * types.
1835478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1836d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
1837478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
1838478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
1839478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1840478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case ETHERTYPE_ATALK:
1841478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case ETHERTYPE_AARP:
1842478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1843478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * EtherTalk (AppleTalk protocols on Ethernet link
1844478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * layer) may use 802.2 encapsulation.
1845478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1846478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1847478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1848478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Check for 802.2 encapsulation (EtherTalk phase 2?);
1849478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * we check for an Ethernet type field less than
1850478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * 1500, which means it's an 802.3 length field.
1851478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1852d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
1853478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_not(b0);
1854478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1855478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1856478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * 802.2-encapsulated ETHERTYPE_ATALK packets are
1857478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * SNAP packets with an organization code of
1858478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * 0x080007 (Apple, for Appletalk) and a protocol
1859478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * type of ETHERTYPE_ATALK (Appletalk).
1860478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1861478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * 802.2-encapsulated ETHERTYPE_AARP packets are
1862478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * SNAP packets with an organization code of
1863478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * 0x000000 (encapsulated Ethernet) and a protocol
1864478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * type of ETHERTYPE_AARP (Appletalk ARP).
1865478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1866478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto == ETHERTYPE_ATALK)
1867511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
1868478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else	/* proto == ETHERTYPE_AARP */
1869511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b1 = gen_snap(0x000000, ETHERTYPE_AARP);
1870478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
1871478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1872478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1873478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Check for Ethernet encapsulation (Ethertalk
1874478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * phase 1?); we just check for the Ethernet
1875478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * protocol type.
1876478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1877d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
1878478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1879478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
1880478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
1881478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1882478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
1883478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto <= ETHERMTU) {
1884478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
1885478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * This is an LLC SAP value, so the frames
1886478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * that match would be 802.2 frames.
1887478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * Check that the frame is an 802.2 frame
1888478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * (i.e., that the length/type field is
1889478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * a length field, <= ETHERMTU) and
1890478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * then check the DSAP.
1891478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
1892d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
1893478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_not(b0);
1894d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b1 = gen_cmp(OR_LINKTYPE, 2, BPF_B, (bpf_int32)proto);
1895478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_and(b0, b1);
1896478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return b1;
1897478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		} else {
1898478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
1899478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * This is an Ethernet type, so compare
1900478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * the length/type field with it (if
1901478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * the frame is an 802.2 frame, the length
1902478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * field will be <= ETHERMTU, and, as
1903478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * "proto" is > ETHERMTU, this test
1904478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * will fail and the frame won't match,
1905478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * which is what we want).
1906478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
1907d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return gen_cmp(OR_LINKTYPE, 0, BPF_H,
1908478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			    (bpf_int32)proto);
1909478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
1910478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
1911478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
1912478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1913478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
1914511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * "proto" is an Ethernet type value and for IPNET, if it is not IPv4
1915511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * or IPv6 then we have an error.
1916511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
1917511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct block *
1918511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallgen_ipnet_linktype(proto)
1919511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	register int proto;
1920511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
1921511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	switch (proto) {
1922511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1923511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ETHERTYPE_IP:
1924d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_cmp(OR_LINKTYPE, 0, BPF_B, (bpf_int32)IPH_AF_INET);
1925511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* NOTREACHED */
1926511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1927511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ETHERTYPE_IPV6:
1928d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_cmp(OR_LINKTYPE, 0, BPF_B,
1929511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    (bpf_int32)IPH_AF_INET6);
1930511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* NOTREACHED */
1931511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1932511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	default:
1933511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
1934511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1935511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1936511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return gen_false();
1937511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
1938511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1939511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
1940478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Generate code to match a particular packet type.
1941478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
1942478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
1943478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * value, if <= ETHERMTU.  We use that to determine whether to
1944478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * match the type field or to check the type field for the special
1945478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * LINUX_SLL_P_802_2 value and then do the appropriate test.
1946478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
1947478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
1948478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_linux_sll_linktype(proto)
1949478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int proto;
1950478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
1951478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1;
1952478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1953478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (proto) {
1954478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1955478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case LLCSAP_ISONS:
1956478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case LLCSAP_IP:
1957478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case LLCSAP_NETBEUI:
1958478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1959478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * OSI protocols and NetBEUI always use 802.2 encapsulation,
1960478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * so we check the DSAP and SSAP.
1961478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1962478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * LLCSAP_IP checks for IP-over-802.2, rather
1963478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * than IP-over-Ethernet or IP-over-SNAP.
1964478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1965478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - should we check both the DSAP and the
1966478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * SSAP, like this, or should we check just the
1967478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * DSAP, as we do for other types <= ETHERMTU
1968478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * (i.e., other SAP values)?
1969478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1970d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
1971d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32)
1972478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			     ((proto << 8) | proto));
1973478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
1974478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
1975478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1976478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case LLCSAP_IPX:
1977478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1978478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	Ethernet_II frames, which are Ethernet
1979478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	frames with a frame type of ETHERTYPE_IPX;
1980478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1981478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	Ethernet_802.3 frames, which have a frame
1982478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	type of LINUX_SLL_P_802_3;
1983478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1984478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	Ethernet_802.2 frames, which are 802.3
1985478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	frames with an 802.2 LLC header (i.e, have
1986478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	a frame type of LINUX_SLL_P_802_2) and
1987478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	with the IPX LSAP as the DSAP in the LLC
1988478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	header;
1989478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1990478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	Ethernet_SNAP frames, which are 802.3
1991478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	frames with an LLC header and a SNAP
1992478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	header and with an OUI of 0x000000
1993478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	(encapsulated Ethernet) and a protocol
1994478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	ID of ETHERTYPE_IPX in the SNAP header.
1995478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1996478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * First, do the checks on LINUX_SLL_P_802_2
1997478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * frames; generate the check for either
1998478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Ethernet_802.2 or Ethernet_SNAP frames, and
1999478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * then put a check for LINUX_SLL_P_802_2 frames
2000478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * before it.
2001478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2002d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp(OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
2003511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b1 = gen_snap(0x000000, ETHERTYPE_IPX);
2004478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
2005d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
2006478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
2007478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2008478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2009478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now check for 802.3 frames and OR that with
2010478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the previous test.
2011478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2012d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_3);
2013478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
2014478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2015478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2016478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now add the check for Ethernet_II frames, and
2017478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * do that before checking for the other frame
2018478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * types.
2019478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2020d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
2021478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
2022478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
2023478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2024478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case ETHERTYPE_ATALK:
2025478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case ETHERTYPE_AARP:
2026478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2027478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * EtherTalk (AppleTalk protocols on Ethernet link
2028478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * layer) may use 802.2 encapsulation.
2029478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2030478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2031478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2032478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Check for 802.2 encapsulation (EtherTalk phase 2?);
2033478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * we check for the 802.2 protocol type in the
2034478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * "Ethernet type" field.
2035478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2036d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
2037478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2038478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2039478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * 802.2-encapsulated ETHERTYPE_ATALK packets are
2040478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * SNAP packets with an organization code of
2041478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * 0x080007 (Apple, for Appletalk) and a protocol
2042478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * type of ETHERTYPE_ATALK (Appletalk).
2043478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
2044478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * 802.2-encapsulated ETHERTYPE_AARP packets are
2045478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * SNAP packets with an organization code of
2046478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * 0x000000 (encapsulated Ethernet) and a protocol
2047478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * type of ETHERTYPE_AARP (Appletalk ARP).
2048478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2049478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto == ETHERTYPE_ATALK)
2050511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
2051478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else	/* proto == ETHERTYPE_AARP */
2052511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b1 = gen_snap(0x000000, ETHERTYPE_AARP);
2053478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
2054478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2055478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2056478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Check for Ethernet encapsulation (Ethertalk
2057478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * phase 1?); we just check for the Ethernet
2058478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * protocol type.
2059478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2060d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
2061478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2062478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
2063478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
2064478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2065478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
2066478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto <= ETHERMTU) {
2067478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
2068478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * This is an LLC SAP value, so the frames
2069478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * that match would be 802.2 frames.
2070478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * Check for the 802.2 protocol type
2071478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * in the "Ethernet type" field, and
2072478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * then check the DSAP.
2073478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
2074d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
2075d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b1 = gen_cmp(OR_LINKHDR, off_linkpl.constant_part, BPF_B,
2076478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			     (bpf_int32)proto);
2077478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_and(b0, b1);
2078478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return b1;
2079478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		} else {
2080478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
2081478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * This is an Ethernet type, so compare
2082478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * the length/type field with it (if
2083478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * the frame is an 802.2 frame, the length
2084478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * field will be <= ETHERMTU, and, as
2085478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * "proto" is > ETHERMTU, this test
2086478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * will fail and the frame won't match,
2087478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * which is what we want).
2088478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
2089d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
2090478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
2091478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
2092478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
2093478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2094511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct slist *
2095511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallgen_load_prism_llprefixlen()
2096511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
2097511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct slist *s1, *s2;
2098511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct slist *sjeq_avs_cookie;
2099511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct slist *sjcommon;
2100511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2101511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2102511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * This code is not compatible with the optimizer, as
2103511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * we are generating jmp instructions within a normal
2104511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * slist of instructions
2105511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2106511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	no_optimize = 1;
2107511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2108511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2109511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Generate code to load the length of the radio header into
2110511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the register assigned to hold that length, if one has been
2111511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * assigned.  (If one hasn't been assigned, no code we've
2112511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * generated uses that prefix, so we don't need to generate any
2113511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * code to load it.)
2114511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
2115511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Some Linux drivers use ARPHRD_IEEE80211_PRISM but sometimes
2116511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * or always use the AVS header rather than the Prism header.
2117511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We load a 4-byte big-endian value at the beginning of the
2118511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * raw packet data, and see whether, when masked with 0xFFFFF000,
2119511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * it's equal to 0x80211000.  If so, that indicates that it's
2120511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * an AVS header (the masked-out bits are the version number).
2121511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Otherwise, it's a Prism header.
2122511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
2123511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX - the Prism header is also, in theory, variable-length,
2124511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * but no known software generates headers that aren't 144
2125511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * bytes long.
2126511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2127d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	if (off_linkhdr.reg != -1) {
2128511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2129511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Load the cookie.
2130511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2131511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
2132511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s1->s.k = 0;
2133511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2134511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2135511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * AND it with 0xFFFFF000.
2136511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2137511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
2138511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2->s.k = 0xFFFFF000;
2139511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s1, s2);
2140511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2141511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2142511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Compare with 0x80211000.
2143511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2144511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjeq_avs_cookie = new_stmt(JMP(BPF_JEQ));
2145511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjeq_avs_cookie->s.k = 0x80211000;
2146511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s1, sjeq_avs_cookie);
2147511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2148511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2149511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If it's AVS:
2150511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2151511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * The 4 bytes at an offset of 4 from the beginning of
2152511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the AVS header are the length of the AVS header.
2153511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * That field is big-endian.
2154511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2155511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
2156511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2->s.k = 4;
2157511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s1, s2);
2158511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjeq_avs_cookie->s.jt = s2;
2159511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2160511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2161511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Now jump to the code to allocate a register
2162511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * into which to save the header length and
2163511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * store the length there.  (The "jump always"
2164511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * instruction needs to have the k field set;
2165511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * it's added to the PC, so, as we're jumping
2166511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * over a single instruction, it should be 1.)
2167511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2168511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjcommon = new_stmt(JMP(BPF_JA));
2169511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjcommon->s.k = 1;
2170511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s1, sjcommon);
2171511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2172511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2173511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Now for the code that handles the Prism header.
2174511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Just load the length of the Prism header (144)
2175511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * into the A register.  Have the test for an AVS
2176511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * header branch here if we don't have an AVS header.
2177511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2178511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2 = new_stmt(BPF_LD|BPF_W|BPF_IMM);
2179511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2->s.k = 144;
2180511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s1, s2);
2181511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjeq_avs_cookie->s.jf = s2;
2182511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2183511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2184511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Now allocate a register to hold that value and store
2185511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * it.  The code for the AVS header will jump here after
2186511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * loading the length of the AVS header.
2187511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2188511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2 = new_stmt(BPF_ST);
2189d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s2->s.k = off_linkhdr.reg;
2190511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s1, s2);
2191511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjcommon->s.jf = s2;
2192511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2193511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2194511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Now move it into the X register.
2195511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2196511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2 = new_stmt(BPF_MISC|BPF_TAX);
2197511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s1, s2);
2198511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2199511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (s1);
2200511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else
2201511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (NULL);
2202511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
2203511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2204511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct slist *
2205511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallgen_load_avs_llprefixlen()
2206478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
2207478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s1, *s2;
2208478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2209478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
2210511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Generate code to load the length of the AVS header into
2211511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the register assigned to hold that length, if one has been
2212511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * assigned.  (If one hasn't been assigned, no code we've
2213511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * generated uses that prefix, so we don't need to generate any
2214511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * code to load it.)
2215478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
2216d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	if (off_linkhdr.reg != -1) {
2217511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2218511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * The 4 bytes at an offset of 4 from the beginning of
2219511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the AVS header are the length of the AVS header.
2220511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * That field is big-endian.
2221511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2222511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
2223511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s1->s.k = 4;
2224511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2225511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2226511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Now allocate a register to hold that value and store
2227511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * it.
2228511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2229511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2 = new_stmt(BPF_ST);
2230d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s2->s.k = off_linkhdr.reg;
2231511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s1, s2);
2232511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2233511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2234511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Now move it into the X register.
2235511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2236511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2 = new_stmt(BPF_MISC|BPF_TAX);
2237511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s1, s2);
2238511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2239511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (s1);
2240511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else
2241511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (NULL);
2242511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
2243511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2244511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct slist *
2245511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallgen_load_radiotap_llprefixlen()
2246511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
2247511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct slist *s1, *s2;
2248511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2249511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2250511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Generate code to load the length of the radiotap header into
2251511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the register assigned to hold that length, if one has been
2252511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * assigned.  (If one hasn't been assigned, no code we've
2253511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * generated uses that prefix, so we don't need to generate any
2254511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * code to load it.)
2255511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2256d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	if (off_linkhdr.reg != -1) {
2257478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2258478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * The 2 bytes at offsets of 2 and 3 from the beginning
2259478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * of the radiotap header are the length of the radiotap
2260478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * header; unfortunately, it's little-endian, so we have
2261478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * to load it a byte at a time and construct the value.
2262478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2263478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2264478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2265478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Load the high-order byte, at an offset of 3, shift it
2266478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * left a byte, and put the result in the X register.
2267478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2268478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
2269478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s1->s.k = 3;
2270478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
2271478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s1, s2);
2272478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2->s.k = 8;
2273478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_MISC|BPF_TAX);
2274478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s1, s2);
2275478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2276478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2277478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Load the next byte, at an offset of 2, and OR the
2278478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * value from the X register into it.
2279478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2280478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
2281478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s1, s2);
2282478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2->s.k = 2;
2283478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X);
2284478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s1, s2);
2285478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2286478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2287478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now allocate a register to hold that value and store
2288478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * it.
2289478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2290478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_ST);
2291d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s2->s.k = off_linkhdr.reg;
2292478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s1, s2);
2293478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2294478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2295478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now move it into the X register.
2296478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2297478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_MISC|BPF_TAX);
2298478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s1, s2);
2299478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2300511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (s1);
2301511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else
2302511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (NULL);
2303478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
2304478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2305d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes/*
2306478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * At the moment we treat PPI as normal Radiotap encoded
2307478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * packets. The difference is in the function that generates
2308478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * the code at the beginning to compute the header length.
2309478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Since this code generator of PPI supports bare 802.11
2310478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * encapsulation only (i.e. the encapsulated DLT should be
2311511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * DLT_IEEE802_11) we generate code to check for this too;
2312511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * that's done in finish_parse().
2313478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
2314511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct slist *
2315511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallgen_load_ppi_llprefixlen()
2316478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
2317478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s1, *s2;
2318d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
2319478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
2320511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Generate code to load the length of the radiotap header
2321511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * into the register assigned to hold that length, if one has
2322511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * been assigned.
2323478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
2324d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	if (off_linkhdr.reg != -1) {
2325511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2326478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * The 2 bytes at offsets of 2 and 3 from the beginning
2327478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * of the radiotap header are the length of the radiotap
2328478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * header; unfortunately, it's little-endian, so we have
2329478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * to load it a byte at a time and construct the value.
2330478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2331478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2332478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2333478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Load the high-order byte, at an offset of 3, shift it
2334478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * left a byte, and put the result in the X register.
2335478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2336478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
2337478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s1->s.k = 3;
2338478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
2339478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s1, s2);
2340478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2->s.k = 8;
2341478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_MISC|BPF_TAX);
2342478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s1, s2);
2343478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2344478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2345478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Load the next byte, at an offset of 2, and OR the
2346478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * value from the X register into it.
2347478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2348478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
2349478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s1, s2);
2350478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2->s.k = 2;
2351478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X);
2352478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s1, s2);
2353478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2354478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2355478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now allocate a register to hold that value and store
2356478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * it.
2357478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2358478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_ST);
2359d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s2->s.k = off_linkhdr.reg;
2360478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s1, s2);
2361478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2362478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2363478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now move it into the X register.
2364478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2365478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_MISC|BPF_TAX);
2366478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s1, s2);
2367478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2368511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (s1);
2369511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else
2370511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (NULL);
2371511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
2372511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2373511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
2374511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Load a value relative to the beginning of the link-layer header after the 802.11
2375511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * header, i.e. LLC_SNAP.
2376511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * The link-layer header doesn't necessarily begin at the beginning
2377511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * of the packet data; there might be a variable-length prefix containing
2378511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * radio information.
2379511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
2380511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct slist *
2381511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallgen_load_802_11_header_len(struct slist *s, struct slist *snext)
2382511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
2383511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct slist *s2;
2384511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct slist *sjset_data_frame_1;
2385511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct slist *sjset_data_frame_2;
2386511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct slist *sjset_qos;
2387511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct slist *sjset_radiotap_flags;
2388511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct slist *sjset_radiotap_tsft;
2389511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct slist *sjset_tsft_datapad, *sjset_notsft_datapad;
2390511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct slist *s_roundup;
2391511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2392d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	if (off_linkpl.reg == -1) {
2393511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2394511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * No register has been assigned to the offset of
2395d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * the link-layer payload, which means nobody needs
2396511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * it; don't bother computing it - just return
2397511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * what we already have.
2398511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2399511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (s);
2400511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2401511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2402511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2403511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * This code is not compatible with the optimizer, as
2404511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * we are generating jmp instructions within a normal
2405511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * slist of instructions
2406511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2407511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	no_optimize = 1;
2408d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
2409511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2410511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If "s" is non-null, it has code to arrange that the X register
2411511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * contains the length of the prefix preceding the link-layer
2412511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * header.
2413511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
2414511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Otherwise, the length of the prefix preceding the link-layer
2415d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * header is "off_outermostlinkhdr.constant_part".
2416511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2417511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (s == NULL) {
2418511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2419511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * There is no variable-length header preceding the
2420511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * link-layer header.
2421511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2422511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Load the length of the fixed-length prefix preceding
2423511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the link-layer header (if any) into the X register,
2424d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * and store it in the off_linkpl.reg register.
2425d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * That length is off_outermostlinkhdr.constant_part.
2426511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2427511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s = new_stmt(BPF_LDX|BPF_IMM);
2428d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s->s.k = off_outermostlinkhdr.constant_part;
2429511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2430511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2431511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2432511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * The X register contains the offset of the beginning of the
2433511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * link-layer header; add 24, which is the minimum length
2434511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * of the MAC header for a data frame, to that, and store it
2435d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * in off_linkpl.reg, and then load the Frame Control field,
2436511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * which is at the offset in the X register, with an indexed load.
2437511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2438511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	s2 = new_stmt(BPF_MISC|BPF_TXA);
2439511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sappend(s, s2);
2440511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
2441511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	s2->s.k = 24;
2442511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sappend(s, s2);
2443511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	s2 = new_stmt(BPF_ST);
2444d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s2->s.k = off_linkpl.reg;
2445511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sappend(s, s2);
2446511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2447511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
2448511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	s2->s.k = 0;
2449511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sappend(s, s2);
2450511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2451511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2452511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Check the Frame Control field to see if this is a data frame;
2453511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * a data frame has the 0x08 bit (b3) in that field set and the
2454511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * 0x04 bit (b2) clear.
2455511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2456511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sjset_data_frame_1 = new_stmt(JMP(BPF_JSET));
2457511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sjset_data_frame_1->s.k = 0x08;
2458511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sappend(s, sjset_data_frame_1);
2459d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
2460511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2461511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If b3 is set, test b2, otherwise go to the first statement of
2462511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the rest of the program.
2463511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2464511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sjset_data_frame_1->s.jt = sjset_data_frame_2 = new_stmt(JMP(BPF_JSET));
2465511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sjset_data_frame_2->s.k = 0x04;
2466511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sappend(s, sjset_data_frame_2);
2467511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sjset_data_frame_1->s.jf = snext;
2468511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2469511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2470511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If b2 is not set, this is a data frame; test the QoS bit.
2471511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Otherwise, go to the first statement of the rest of the
2472511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * program.
2473511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2474511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sjset_data_frame_2->s.jt = snext;
2475511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sjset_data_frame_2->s.jf = sjset_qos = new_stmt(JMP(BPF_JSET));
2476511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sjset_qos->s.k = 0x80;	/* QoS bit */
2477511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sappend(s, sjset_qos);
2478d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
2479511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2480d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * If it's set, add 2 to off_linkpl.reg, to skip the QoS
2481511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * field.
2482511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Otherwise, go to the first statement of the rest of the
2483511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * program.
2484511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2485511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sjset_qos->s.jt = s2 = new_stmt(BPF_LD|BPF_MEM);
2486d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s2->s.k = off_linkpl.reg;
2487511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sappend(s, s2);
2488511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
2489511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	s2->s.k = 2;
2490511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sappend(s, s2);
2491511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	s2 = new_stmt(BPF_ST);
2492d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s2->s.k = off_linkpl.reg;
2493511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sappend(s, s2);
2494511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2495511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2496511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If we have a radiotap header, look at it to see whether
2497511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * there's Atheros padding between the MAC-layer header
2498511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * and the payload.
2499511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
2500511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Note: all of the fields in the radiotap header are
2501511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * little-endian, so we byte-swap all of the values
2502511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * we test against, as they will be loaded as big-endian
2503511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * values.
2504511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2505511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (linktype == DLT_IEEE802_11_RADIO) {
2506511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2507511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Is the IEEE80211_RADIOTAP_FLAGS bit (0x0000002) set
2508511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * in the presence flag?
2509511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2510511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_qos->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_W);
2511511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2->s.k = 4;
2512511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s, s2);
2513511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2514511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_radiotap_flags = new_stmt(JMP(BPF_JSET));
2515511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_radiotap_flags->s.k = SWAPLONG(0x00000002);
2516511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s, sjset_radiotap_flags);
2517511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2518511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2519511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If not, skip all of this.
2520511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2521511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_radiotap_flags->s.jf = snext;
2522511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2523511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2524511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Otherwise, is the IEEE80211_RADIOTAP_TSFT bit set?
2525511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2526511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_radiotap_tsft = sjset_radiotap_flags->s.jt =
2527511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    new_stmt(JMP(BPF_JSET));
2528511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_radiotap_tsft->s.k = SWAPLONG(0x00000001);
2529511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s, sjset_radiotap_tsft);
2530511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2531511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2532511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If IEEE80211_RADIOTAP_TSFT is set, the flags field is
2533511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * at an offset of 16 from the beginning of the raw packet
2534511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * data (8 bytes for the radiotap header and 8 bytes for
2535511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the TSFT field).
2536511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2537511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
2538511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * is set.
2539511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2540511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_radiotap_tsft->s.jt = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
2541511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2->s.k = 16;
2542511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s, s2);
2543511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2544511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_tsft_datapad = new_stmt(JMP(BPF_JSET));
2545511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_tsft_datapad->s.k = 0x20;
2546511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s, sjset_tsft_datapad);
2547511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2548511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2549511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If IEEE80211_RADIOTAP_TSFT is not set, the flags field is
2550511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * at an offset of 8 from the beginning of the raw packet
2551511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * data (8 bytes for the radiotap header).
2552511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2553511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
2554511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * is set.
2555511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2556511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_radiotap_tsft->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
2557511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2->s.k = 8;
2558511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s, s2);
2559511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2560511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_notsft_datapad = new_stmt(JMP(BPF_JSET));
2561511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_notsft_datapad->s.k = 0x20;
2562511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s, sjset_notsft_datapad);
2563511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2564478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2565511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * In either case, if IEEE80211_RADIOTAP_F_DATAPAD is
2566511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * set, round the length of the 802.11 header to
2567511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * a multiple of 4.  Do that by adding 3 and then
2568511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * dividing by and multiplying by 4, which we do by
2569511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * ANDing with ~3.
2570478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2571511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s_roundup = new_stmt(BPF_LD|BPF_MEM);
2572d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s_roundup->s.k = off_linkpl.reg;
2573511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s, s_roundup);
2574511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
2575511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2->s.k = 3;
2576511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s, s2);
2577511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2 = new_stmt(BPF_ALU|BPF_AND|BPF_IMM);
2578511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2->s.k = ~3;
2579511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s, s2);
2580511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s2 = new_stmt(BPF_ST);
2581d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s2->s.k = off_linkpl.reg;
2582511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s, s2);
2583511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2584511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_tsft_datapad->s.jt = s_roundup;
2585511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_tsft_datapad->s.jf = snext;
2586511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_notsft_datapad->s.jt = s_roundup;
2587511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_notsft_datapad->s.jf = snext;
2588511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else
2589511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sjset_qos->s.jf = snext;
2590511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2591511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return s;
2592511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
2593511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2594511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void
2595511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallinsert_compute_vloffsets(b)
2596511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct block *b;
2597511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
2598511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct slist *s;
2599511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2600d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* There is an implicit dependency between the link
2601d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * payload and link header since the payload computation
2602d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * includes the variable part of the header. Therefore,
2603d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * if nobody else has allocated a register for the link
2604d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * header and we need it, do it now. */
2605d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	if (off_linkpl.reg != -1 && off_linkhdr.is_variable &&
2606d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	    off_linkhdr.reg == -1)
2607d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkhdr.reg = alloc_reg();
2608d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
2609511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2610511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * For link-layer types that have a variable-length header
2611511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * preceding the link-layer header, generate code to load
2612511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the offset of the link-layer header into the register
2613511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * assigned to that offset, if any.
2614d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 *
2615d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * XXX - this, and the next switch statement, won't handle
2616d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * encapsulation of 802.11 or 802.11+radio information in
2617d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * some other protocol stack.  That's significantly more
2618d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * complicated.
2619511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2620d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	switch (outermostlinktype) {
2621511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2622511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_PRISM_HEADER:
2623511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s = gen_load_prism_llprefixlen();
2624511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2625511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2626511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_11_RADIO_AVS:
2627511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s = gen_load_avs_llprefixlen();
2628511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2629511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2630511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_11_RADIO:
2631511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s = gen_load_radiotap_llprefixlen();
2632511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2633511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2634511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_PPI:
2635511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s = gen_load_ppi_llprefixlen();
2636511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2637478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2638511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	default:
2639511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s = NULL;
2640511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2641511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2642511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2643511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2644511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * For link-layer types that have a variable-length link-layer
2645d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * header, generate code to load the offset of the link-layer
2646511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * payload into the register assigned to that offset, if any.
2647511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2648d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	switch (outermostlinktype) {
2649511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2650511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_11:
2651511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_PRISM_HEADER:
2652511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_11_RADIO_AVS:
2653511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_11_RADIO:
2654511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_PPI:
2655511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s = gen_load_802_11_header_len(s, b->stmts);
2656511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2657511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2658511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2659511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2660511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If we have any offset-loading code, append all the
2661511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * existing statements in the block to those statements,
2662511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * and make the resulting list the list of statements
2663511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * for the block.
2664511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2665511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (s != NULL) {
2666511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		sappend(s, b->stmts);
2667511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b->stmts = s;
2668478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
2669478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
2670511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2671478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
2672478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_ppi_dlt_check(void)
2673478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
2674478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s_load_dlt;
2675478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b;
2676478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2677478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (linktype == DLT_PPI)
2678478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	{
2679478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* Create the statements that check for the DLT
2680478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2681478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s_load_dlt = new_stmt(BPF_LD|BPF_W|BPF_ABS);
2682478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s_load_dlt->s.k = 4;
2683478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2684478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b = new_block(JMP(BPF_JEQ));
2685478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2686478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b->stmts = s_load_dlt;
2687478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b->s.k = SWAPLONG(DLT_IEEE802_11);
2688478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
2689478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	else
2690478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	{
2691478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b = NULL;
2692478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
2693478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2694478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b;
2695478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
2696478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2697478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
2698d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * Take an absolute offset, and:
2699d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *
2700d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *    if it has no variable part, return NULL;
2701d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *
2702d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *    if it has a variable part, generate code to load the register
2703d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *    containing that variable part into the X register, returning
2704d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *    a pointer to that code - if no register for that offset has
2705d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *    been allocated, allocate it first.
2706d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *
2707d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * (The code to set that register will be generated later, but will
2708d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * be placed earlier in the code sequence.)
2709511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
2710511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct slist *
2711d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_abs_offset_varpart(bpf_abs_offset *off)
2712511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
2713511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct slist *s;
2714511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2715d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	if (off->is_variable) {
2716d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		if (off->reg == -1) {
2717511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
2718d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			 * We haven't yet assigned a register for the
2719d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			 * variable part of the offset of the link-layer
2720d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			 * header; allocate one.
2721511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
2722d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			off->reg = alloc_reg();
2723511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2724511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2725511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2726d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * Load the register containing the variable part of the
2727d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * offset of the link-layer header into the X register.
2728511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2729511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s = new_stmt(BPF_LDX|BPF_MEM);
2730d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s->s.k = off->reg;
2731511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return s;
2732511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else {
2733511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2734d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * That offset isn't variable, there's no variable part,
2735d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * so we don't need to generate any code.
2736511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2737511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return NULL;
2738511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2739511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
2740511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2741511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
2742511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Map an Ethernet type to the equivalent PPP type.
2743511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
2744511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
2745511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallethertype_to_ppptype(proto)
2746511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int proto;
2747511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
2748511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	switch (proto) {
2749511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2750511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ETHERTYPE_IP:
2751511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		proto = PPP_IP;
2752511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2753511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2754511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ETHERTYPE_IPV6:
2755511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		proto = PPP_IPV6;
2756511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2757511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2758511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ETHERTYPE_DN:
2759511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		proto = PPP_DECNET;
2760511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2761511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2762511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ETHERTYPE_ATALK:
2763511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		proto = PPP_APPLE;
2764511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2765511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2766511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ETHERTYPE_NS:
2767511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		proto = PPP_NS;
2768511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2769511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2770511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case LLCSAP_ISONS:
2771511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		proto = PPP_OSI;
2772511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2773511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2774511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case LLCSAP_8021D:
2775511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2776511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * I'm assuming the "Bridging PDU"s that go
2777511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * over PPP are Spanning Tree Protocol
2778511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Bridging PDUs.
2779511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2780511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		proto = PPP_BRPDU;
2781511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2782511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2783511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case LLCSAP_IPX:
2784511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		proto = PPP_IPX;
2785511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2786511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2787511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return (proto);
2788511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
2789511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2790511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
2791d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * Generate any tests that, for encapsulation of a link-layer packet
2792d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * inside another protocol stack, need to be done to check for those
2793d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * link-layer packets (and that haven't already been done by a check
2794d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * for that encapsulation).
2795d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes */
2796d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic struct block *
2797d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_prevlinkhdr_check(void)
2798d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes{
2799d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct block *b0;
2800d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
2801d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	if (is_geneve)
2802d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_geneve_ll_check();
2803d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
2804d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	switch (prevlinktype) {
2805d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
2806d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_SUNATM:
2807d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		/*
2808d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * This is LANE-encapsulated Ethernet; check that the LANE
2809d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * packet doesn't begin with an LE Control marker, i.e.
2810d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * that it's data, not a control message.
2811d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 *
2812d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * (We've already generated a test for LANE.)
2813d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 */
2814d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp(OR_PREVLINKHDR, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
2815d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		gen_not(b0);
2816d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return b0;
2817d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
2818d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	default:
2819d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		/*
2820d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * No such tests are necessary.
2821d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 */
2822d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return NULL;
2823d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	}
2824d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/*NOTREACHED*/
2825d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes}
2826d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
2827d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes/*
2828478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Generate code to match a particular packet type by matching the
2829478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * link-layer type field or fields in the 802.2 LLC header.
2830478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
2831478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
2832478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * value, if <= ETHERMTU.
2833478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
2834478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
2835478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_linktype(proto)
2836478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int proto;
2837478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
2838478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1, *b2;
2839d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	const char *description;
2840478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2841478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* are we checking MPLS-encapsulated packets? */
2842478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (label_stack_depth > 0) {
2843478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		switch (proto) {
2844478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case ETHERTYPE_IP:
2845478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case PPP_IP:
2846511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* FIXME add other L3 proto IDs */
2847d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return gen_mpls_linktype(Q_IP);
2848478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2849478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case ETHERTYPE_IPV6:
2850478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case PPP_IPV6:
2851511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* FIXME add other L3 proto IDs */
2852d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return gen_mpls_linktype(Q_IPV6);
2853478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2854478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		default:
2855478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("unsupported protocol over mpls");
2856478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/* NOTREACHED */
2857478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
2858478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
2859478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2860478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (linktype) {
2861478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2862478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_EN10MB:
2863511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_NETANALYZER:
2864511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_NETANALYZER_TRANSPARENT:
2865d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		/* Geneve has an EtherType regardless of whether there is an
2866d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * L2 header. */
2867d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		if (!is_geneve)
2868d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_prevlinkhdr_check();
2869d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		else
2870d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = NULL;
2871d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
2872d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_ether_linktype(proto);
2873d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		if (b0 != NULL)
2874d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			gen_and(b0, b1);
2875d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return b1;
2876478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*NOTREACHED*/
2877478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
2878478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2879478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_C_HDLC:
2880478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		switch (proto) {
2881478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2882478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case LLCSAP_ISONS:
2883478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			proto = (proto << 8 | LLCSAP_ISONS);
2884478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/* fall through */
2885478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2886478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		default:
2887d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
2888478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*NOTREACHED*/
2889478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			break;
2890478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
2891478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
2892478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2893478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_IEEE802_11:
2894511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_PRISM_HEADER:
2895478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_IEEE802_11_RADIO_AVS:
2896478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_IEEE802_11_RADIO:
2897511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_PPI:
2898511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2899511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Check that we have a data frame.
2900511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2901511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b0 = gen_check_802_11_data_frame();
2902511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2903511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2904511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Now check for the specified link-layer type.
2905511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2906511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b1 = gen_llc_linktype(proto);
2907511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_and(b0, b1);
2908511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return b1;
2909511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*NOTREACHED*/
2910511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2911511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2912511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_FDDI:
2913511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2914d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * XXX - check for LLC frames.
2915511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2916511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return gen_llc_linktype(proto);
2917511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*NOTREACHED*/
2918511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2919511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2920511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802:
2921511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2922511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * XXX - check for LLC PDUs, as per IEEE 802.5.
2923511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2924511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return gen_llc_linktype(proto);
2925511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*NOTREACHED*/
2926511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2927511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2928478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_ATM_RFC1483:
2929478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_ATM_CLIP:
2930478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_IP_OVER_FC:
2931478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return gen_llc_linktype(proto);
2932478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*NOTREACHED*/
2933478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
2934478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2935478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_SUNATM:
2936478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2937d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * Check for an LLC-encapsulated version of this protocol;
2938d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * if we were checking for LANE, linktype would no longer
2939d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * be DLT_SUNATM.
2940478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
2941d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * Check for LLC encapsulation and then check the protocol.
2942478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2943d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
2944d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_llc_linktype(proto);
2945d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		gen_and(b0, b1);
2946d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return b1;
2947478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*NOTREACHED*/
2948478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
2949478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2950478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_LINUX_SLL:
2951478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return gen_linux_sll_linktype(proto);
2952478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*NOTREACHED*/
2953478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
2954478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2955478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_SLIP:
2956478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_SLIP_BSDOS:
2957478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_RAW:
2958478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
2959478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * These types don't provide any type field; packets
2960478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * are always IPv4 or IPv6.
2961478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
2962478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - for IPv4, check for a version number of 4, and,
2963478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * for IPv6, check for a version number of 6?
2964478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
2965478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		switch (proto) {
2966478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2967478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case ETHERTYPE_IP:
2968478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/* Check for a version number of 4. */
2969d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return gen_mcmp(OR_LINKHDR, 0, BPF_B, 0x40, 0xF0);
2970511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2971478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case ETHERTYPE_IPV6:
2972478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/* Check for a version number of 6. */
2973d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return gen_mcmp(OR_LINKHDR, 0, BPF_B, 0x60, 0xF0);
2974478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2975478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		default:
2976478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return gen_false();		/* always false */
2977478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
2978478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*NOTREACHED*/
2979478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
2980478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
2981511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IPV4:
2982511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2983511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Raw IPv4, so no type field.
2984511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2985511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (proto == ETHERTYPE_IP)
2986511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return gen_true();		/* always true */
2987511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2988511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Checking for something other than IPv4; always false */
2989511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return gen_false();
2990511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*NOTREACHED*/
2991511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2992511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2993511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IPV6:
2994511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2995511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Raw IPv6, so no type field.
2996511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2997511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (proto == ETHERTYPE_IPV6)
2998511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return gen_true();		/* always true */
2999511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3000511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Checking for something other than IPv6; always false */
3001511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return gen_false();
3002511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*NOTREACHED*/
3003511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3004511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3005478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_PPP:
3006478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_PPP_PPPD:
3007478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_PPP_SERIAL:
3008478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_PPP_ETHER:
3009478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3010478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * We use Ethernet protocol types inside libpcap;
3011478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * map them to the corresponding PPP protocol types.
3012478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3013511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		proto = ethertype_to_ppptype(proto);
3014d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
3015511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*NOTREACHED*/
3016478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
3017478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3018478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_PPP_BSDOS:
3019478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3020478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * We use Ethernet protocol types inside libpcap;
3021478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * map them to the corresponding PPP protocol types.
3022478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3023478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		switch (proto) {
3024478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3025478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case ETHERTYPE_IP:
3026511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
3027511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Also check for Van Jacobson-compressed IP.
3028511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * XXX - do this for other forms of PPP?
3029511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
3030d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, PPP_IP);
3031d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b1 = gen_cmp(OR_LINKTYPE, 0, BPF_H, PPP_VJC);
3032478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_or(b0, b1);
3033d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, PPP_VJNC);
3034478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_or(b1, b0);
3035478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return b0;
3036478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3037511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		default:
3038511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			proto = ethertype_to_ppptype(proto);
3039d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return gen_cmp(OR_LINKTYPE, 0, BPF_H,
3040511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				(bpf_int32)proto);
3041478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
3042511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*NOTREACHED*/
3043478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
3044478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3045478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_NULL:
3046478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_LOOP:
3047478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_ENC:
3048478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3049478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * For DLT_NULL, the link-layer header is a 32-bit
3050478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * word containing an AF_ value in *host* byte order,
3051478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * and for DLT_ENC, the link-layer header begins
3052478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * with a 32-bit work containing an AF_ value in
3053478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * host byte order.
3054478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
3055478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * In addition, if we're reading a saved capture file,
3056478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the host byte order in the capture may not be the
3057478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * same as the host byte order on this machine.
3058478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
3059478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * For DLT_LOOP, the link-layer header is a 32-bit
3060478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * word containing an AF_ value in *network* byte order.
3061478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
3062478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - AF_ values may, unfortunately, be platform-
3063478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * dependent; for example, FreeBSD's AF_INET6 is 24
3064478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * whilst NetBSD's and OpenBSD's is 26.
3065478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
3066478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * This means that, when reading a capture file, just
3067478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * checking for our AF_INET6 value won't work if the
3068478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * capture file came from another OS.
3069478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3070478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		switch (proto) {
3071478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3072478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case ETHERTYPE_IP:
3073478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			proto = AF_INET;
3074478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			break;
3075478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3076478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef INET6
3077478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case ETHERTYPE_IPV6:
3078478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			proto = AF_INET6;
3079478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			break;
3080478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
3081478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3082478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		default:
3083478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
3084478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * Not a type on which we support filtering.
3085478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * XXX - support those that have AF_ values
3086478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * #defined on this platform, at least?
3087478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
3088478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return gen_false();
3089478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
3090478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3091478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (linktype == DLT_NULL || linktype == DLT_ENC) {
3092478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
3093478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * The AF_ value is in host byte order, but
3094478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * the BPF interpreter will convert it to
3095478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * network byte order.
3096478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 *
3097478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * If this is a save file, and it's from a
3098478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * machine with the opposite byte order to
3099478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * ours, we byte-swap the AF_ value.
3100478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 *
3101478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * Then we run it through "htonl()", and
3102478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * generate code to compare against the result.
3103478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
3104511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (bpf_pcap->rfile != NULL && bpf_pcap->swapped)
3105478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				proto = SWAPLONG(proto);
3106478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			proto = htonl(proto);
3107478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
3108d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return (gen_cmp(OR_LINKHDR, 0, BPF_W, (bpf_int32)proto));
3109478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3110478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef HAVE_NET_PFVAR_H
3111478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_PFLOG:
3112478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3113478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * af field is host byte order in contrast to the rest of
3114478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the packet.
3115478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3116478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto == ETHERTYPE_IP)
3117d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return (gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, af),
3118478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			    BPF_B, (bpf_int32)AF_INET));
3119478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else if (proto == ETHERTYPE_IPV6)
3120d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return (gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, af),
3121478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			    BPF_B, (bpf_int32)AF_INET6));
3122478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else
3123478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return gen_false();
3124478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*NOTREACHED*/
3125478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
3126478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif /* HAVE_NET_PFVAR_H */
3127478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3128478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_ARCNET:
3129478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_ARCNET_LINUX:
3130478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3131478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX should we check for first fragment if the protocol
3132478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * uses PHDS?
3133478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3134478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		switch (proto) {
3135478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3136478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		default:
3137478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return gen_false();
3138478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3139478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case ETHERTYPE_IPV6:
3140d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return (gen_cmp(OR_LINKTYPE, 0, BPF_B,
3141478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				(bpf_int32)ARCTYPE_INET6));
3142478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3143478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case ETHERTYPE_IP:
3144d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_cmp(OR_LINKTYPE, 0, BPF_B,
3145478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				     (bpf_int32)ARCTYPE_IP);
3146d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b1 = gen_cmp(OR_LINKTYPE, 0, BPF_B,
3147478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				     (bpf_int32)ARCTYPE_IP_OLD);
3148478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_or(b0, b1);
3149478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return (b1);
3150478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3151478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case ETHERTYPE_ARP:
3152d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_cmp(OR_LINKTYPE, 0, BPF_B,
3153478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				     (bpf_int32)ARCTYPE_ARP);
3154d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b1 = gen_cmp(OR_LINKTYPE, 0, BPF_B,
3155478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				     (bpf_int32)ARCTYPE_ARP_OLD);
3156478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_or(b0, b1);
3157478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return (b1);
3158478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3159478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case ETHERTYPE_REVARP:
3160d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return (gen_cmp(OR_LINKTYPE, 0, BPF_B,
3161478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					(bpf_int32)ARCTYPE_REVARP));
3162478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3163478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case ETHERTYPE_ATALK:
3164d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return (gen_cmp(OR_LINKTYPE, 0, BPF_B,
3165478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					(bpf_int32)ARCTYPE_ATALK));
3166478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
3167478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*NOTREACHED*/
3168478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
3169478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3170478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_LTALK:
3171478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		switch (proto) {
3172478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case ETHERTYPE_ATALK:
3173478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return gen_true();
3174478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		default:
3175478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return gen_false();
3176478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
3177478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*NOTREACHED*/
3178478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
3179478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3180478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_FRELAY:
3181478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3182478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - assumes a 2-byte Frame Relay header with
3183478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * DLCI and flags.  What if the address is longer?
3184478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3185478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		switch (proto) {
3186478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3187478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case ETHERTYPE_IP:
3188478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
3189478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * Check for the special NLPID for IP.
3190478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
3191d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0xcc);
3192478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3193478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case ETHERTYPE_IPV6:
3194478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
3195478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * Check for the special NLPID for IPv6.
3196478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
3197d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0x8e);
3198478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3199478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case LLCSAP_ISONS:
3200478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
3201478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * Check for several OSI protocols.
3202478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 *
3203478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * Frame Relay packets typically have an OSI
3204478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * NLPID at the beginning; we check for each
3205478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * of them.
3206478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 *
3207478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * What we check for is the NLPID and a frame
3208478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * control field of UI, i.e. 0x03 followed
3209478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * by the NLPID.
3210478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
3211d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO8473_CLNP);
3212d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b1 = gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO9542_ESIS);
3213d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b2 = gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO10589_ISIS);
3214478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_or(b1, b2);
3215478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_or(b0, b2);
3216478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return b2;
3217478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3218478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		default:
3219478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return gen_false();
3220478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
3221478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*NOTREACHED*/
3222478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
3223478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3224511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_MFR:
3225511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("Multi-link Frame Relay link-layer type filtering not implemented");
3226511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3227478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_MFR:
3228478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_MLFR:
3229478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_MLPPP:
3230478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_ATM1:
3231478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_ATM2:
3232478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_PPPOE:
3233478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_PPPOE_ATM:
3234478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_GGSN:
3235478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_ES:
3236478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_MONITOR:
3237478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_SERVICES:
3238478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_ETHER:
3239478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_PPP:
3240478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_FRELAY:
3241478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_CHDLC:
3242478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_VP:
3243511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall        case DLT_JUNIPER_ST:
3244511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall        case DLT_JUNIPER_ISM:
3245511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall        case DLT_JUNIPER_VS:
3246511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall        case DLT_JUNIPER_SRX_E2E:
3247511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall        case DLT_JUNIPER_FIBRECHANNEL:
3248511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_JUNIPER_ATM_CEMIC:
3249511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3250478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* just lets verify the magic number for now -
3251478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * on ATM we may have up to 6 different encapsulations on the wire
3252478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * and need a lot of heuristics to figure out that the payload
3253478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * might be;
3254478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
3255478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * FIXME encapsulation specific BPF_ filters
3256478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3257d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_mcmp(OR_LINKHDR, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
3258478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3259511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_BACNET_MS_TP:
3260d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_mcmp(OR_LINKHDR, 0, BPF_W, 0x55FF0000, 0xffff0000);
3261511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3262511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IPNET:
3263511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return gen_ipnet_linktype(proto);
3264511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3265478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_LINUX_IRDA:
3266478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("IrDA link-layer type filtering not implemented");
3267478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3268478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_DOCSIS:
3269478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("DOCSIS link-layer type filtering not implemented");
3270478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3271511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_MTP2:
3272511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_MTP2_WITH_PHDR:
3273511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("MTP2 link-layer type filtering not implemented");
3274511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3275511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_ERF:
3276511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("ERF link-layer type filtering not implemented");
3277511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3278511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_PFSYNC:
3279511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("PFSYNC link-layer type filtering not implemented");
3280511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3281478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_LINUX_LAPD:
3282478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("LAPD link-layer type filtering not implemented");
3283511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3284511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_USB:
3285511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_USB_LINUX:
3286511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_USB_LINUX_MMAPPED:
3287511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("USB link-layer type filtering not implemented");
3288511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3289511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_BLUETOOTH_HCI_H4:
3290511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_BLUETOOTH_HCI_H4_WITH_PHDR:
3291511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("Bluetooth link-layer type filtering not implemented");
3292511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3293511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_CAN20B:
3294511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_CAN_SOCKETCAN:
3295511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("CAN link-layer type filtering not implemented");
3296511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3297511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_15_4:
3298511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_15_4_LINUX:
3299511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_15_4_NONASK_PHY:
3300511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_15_4_NOFCS:
3301511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("IEEE 802.15.4 link-layer type filtering not implemented");
3302511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3303511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_16_MAC_CPS_RADIO:
3304511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("IEEE 802.16 link-layer type filtering not implemented");
3305511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3306511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_SITA:
3307511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("SITA link-layer type filtering not implemented");
3308511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3309511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_RAIF1:
3310511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("RAIF1 link-layer type filtering not implemented");
3311511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3312511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IPMB:
3313511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("IPMB link-layer type filtering not implemented");
3314511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3315d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_AX25_KISS:
3316d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		bpf_error("AX.25 link-layer type filtering not implemented");
3317d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3318d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_NFLOG:
3319d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		/* Using the fixed-size NFLOG header it is possible to tell only
3320d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * the address family of the packet, other meaningful data is
3321d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * either missing or behind TLVs.
3322d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 */
3323d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		bpf_error("NFLOG link-layer type filtering not implemented");
3324d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3325d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	default:
3326d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		/*
3327d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * Does this link-layer header type have a field
3328d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * indicating the type of the next protocol?  If
3329d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * so, off_linktype.constant_part will be the offset of that
3330d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * field in the packet; if not, it will be -1.
3331d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 */
3332d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		if (off_linktype.constant_part != (u_int)-1) {
3333d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			/*
3334d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			 * Yes; assume it's an Ethernet type.  (If
3335d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			 * it's not, it needs to be handled specially
3336d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			 * above.)
3337d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			 */
3338d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
3339d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		} else {
3340d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			/*
3341d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			 * No; report an error.
3342d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			 */
3343d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			description = pcap_datalink_val_to_description(linktype);
3344d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			if (description != NULL) {
3345d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes				bpf_error("%s link-layer type filtering not implemented",
3346d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes				    description);
3347d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			} else {
3348d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes				bpf_error("DLT %u link-layer type filtering not implemented",
3349d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes				    linktype);
3350d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			}
3351d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		}
3352d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		break;
3353d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	}
3354d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes}
3355d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3356d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes/*
3357d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * Check for an LLC SNAP packet with a given organization code and
3358d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * protocol type; we check the entire contents of the 802.2 LLC and
3359d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * snap headers, checking for DSAP and SSAP of SNAP and a control
3360d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * field of 0x03 in the LLC header, and for the specified organization
3361d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * code and protocol type in the SNAP header.
3362d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes */
3363d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic struct block *
3364d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_snap(orgcode, ptype)
3365d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	bpf_u_int32 orgcode;
3366d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	bpf_u_int32 ptype;
3367d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes{
3368d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	u_char snapblock[8];
3369d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3370d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	snapblock[0] = LLCSAP_SNAP;	/* DSAP = SNAP */
3371d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	snapblock[1] = LLCSAP_SNAP;	/* SSAP = SNAP */
3372d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	snapblock[2] = 0x03;		/* control = UI */
3373d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	snapblock[3] = (orgcode >> 16);	/* upper 8 bits of organization code */
3374d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	snapblock[4] = (orgcode >> 8);	/* middle 8 bits of organization code */
3375d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	snapblock[5] = (orgcode >> 0);	/* lower 8 bits of organization code */
3376d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	snapblock[6] = (ptype >> 8);	/* upper 8 bits of protocol type */
3377d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	snapblock[7] = (ptype >> 0);	/* lower 8 bits of protocol type */
3378d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	return gen_bcmp(OR_LLC, 0, 8, snapblock);
3379d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes}
3380d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3381d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes/*
3382d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * Generate code to match frames with an LLC header.
3383d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes */
3384d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstruct block *
3385d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_llc(void)
3386d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes{
3387d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct block *b0, *b1;
3388d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3389d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	switch (linktype) {
3390d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3391d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_EN10MB:
3392d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		/*
3393d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * We check for an Ethernet type field less than
3394d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * 1500, which means it's an 802.3 length field.
3395d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 */
3396d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
3397d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		gen_not(b0);
3398d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3399d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		/*
3400d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * Now check for the purported DSAP and SSAP not being
3401d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * 0xFF, to rule out NetWare-over-802.3.
3402d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 */
3403d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
3404d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		gen_not(b1);
3405d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		gen_and(b0, b1);
3406d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return b1;
3407d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3408d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_SUNATM:
3409d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		/*
3410d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * We check for LLC traffic.
3411d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 */
3412d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_atmtype_abbrev(A_LLC);
3413d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return b0;
3414d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3415d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_IEEE802:	/* Token Ring */
3416d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		/*
3417d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * XXX - check for LLC frames.
3418d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 */
3419d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_true();
3420d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3421d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_FDDI:
3422d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		/*
3423d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * XXX - check for LLC frames.
3424d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 */
3425d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_true();
3426d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3427d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_ATM_RFC1483:
3428d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		/*
3429d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * For LLC encapsulation, these are defined to have an
3430d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * 802.2 LLC header.
3431d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 *
3432d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * For VC encapsulation, they don't, but there's no
3433d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * way to check for that; the protocol used on the VC
3434d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * is negotiated out of band.
3435d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 */
3436d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_true();
3437d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3438d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_IEEE802_11:
3439d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_PRISM_HEADER:
3440d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_IEEE802_11_RADIO:
3441d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_IEEE802_11_RADIO_AVS:
3442d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_PPI:
3443d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		/*
3444d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * Check that we have a data frame.
3445d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 */
3446d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_check_802_11_data_frame();
3447d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return b0;
3448d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3449d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	default:
3450d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		bpf_error("'llc' not supported for linktype %d", linktype);
3451d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		/* NOTREACHED */
3452d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	}
3453d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes}
3454d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3455d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstruct block *
3456d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_llc_i(void)
3457d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes{
3458d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct block *b0, *b1;
3459d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct slist *s;
3460d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3461d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/*
3462d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * Check whether this is an LLC frame.
3463d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 */
3464d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_llc();
3465d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3466d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/*
3467d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * Load the control byte and test the low-order bit; it must
3468d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * be clear for I frames.
3469d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 */
3470d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s = gen_load_a(OR_LLC, 2, BPF_B);
3471d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1 = new_block(JMP(BPF_JSET));
3472d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1->s.k = 0x01;
3473d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1->stmts = s;
3474d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	gen_not(b1);
3475d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	gen_and(b0, b1);
3476d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	return b1;
3477d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes}
3478d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3479d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstruct block *
3480d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_llc_s(void)
3481d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes{
3482d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct block *b0, *b1;
3483d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3484d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/*
3485d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * Check whether this is an LLC frame.
3486d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 */
3487d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_llc();
3488d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3489d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/*
3490d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * Now compare the low-order 2 bit of the control byte against
3491d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * the appropriate value for S frames.
3492d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 */
3493d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1 = gen_mcmp(OR_LLC, 2, BPF_B, LLC_S_FMT, 0x03);
3494d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	gen_and(b0, b1);
3495d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	return b1;
3496d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes}
3497d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3498d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstruct block *
3499d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_llc_u(void)
3500d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes{
3501d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct block *b0, *b1;
3502d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3503d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/*
3504d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * Check whether this is an LLC frame.
3505d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 */
3506d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_llc();
3507d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3508d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/*
3509d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * Now compare the low-order 2 bit of the control byte against
3510d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * the appropriate value for U frames.
3511d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 */
3512d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1 = gen_mcmp(OR_LLC, 2, BPF_B, LLC_U_FMT, 0x03);
3513d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	gen_and(b0, b1);
3514d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	return b1;
3515d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes}
3516d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3517d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstruct block *
3518d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_llc_s_subtype(bpf_u_int32 subtype)
3519d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes{
3520d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct block *b0, *b1;
3521478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3522478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
3523d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * Check whether this is an LLC frame.
3524478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
3525d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_llc();
3526478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3527478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
3528d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * Now check for an S frame with the appropriate type.
3529478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
3530d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1 = gen_mcmp(OR_LLC, 2, BPF_B, subtype, LLC_S_CMD_MASK);
3531d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	gen_and(b0, b1);
3532d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	return b1;
3533478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
3534478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3535d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstruct block *
3536d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_llc_u_subtype(bpf_u_int32 subtype)
3537478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
3538d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct block *b0, *b1;
3539478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3540d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/*
3541d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * Check whether this is an LLC frame.
3542d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 */
3543d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_llc();
3544d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
3545d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/*
3546d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * Now check for a U frame with the appropriate type.
3547d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 */
3548d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1 = gen_mcmp(OR_LLC, 2, BPF_B, subtype, LLC_U_CMD_MASK);
3549d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	gen_and(b0, b1);
3550d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	return b1;
3551478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
3552478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3553478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
3554478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Generate code to match a particular packet type, for link-layer types
3555478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * using 802.2 LLC headers.
3556478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
3557478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used
3558478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues.
3559478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
3560478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
3561478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * value, if <= ETHERMTU.  We use that to determine whether to
3562478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * match the DSAP or both DSAP and LSAP or to check the OUI and
3563478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * protocol ID in a SNAP header.
3564478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
3565478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
3566478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_llc_linktype(proto)
3567478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int proto;
3568478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
3569478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
3570478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * XXX - handle token-ring variable-length header.
3571478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
3572478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (proto) {
3573478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3574478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case LLCSAP_IP:
3575478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case LLCSAP_ISONS:
3576478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case LLCSAP_NETBEUI:
3577478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3578478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - should we check both the DSAP and the
3579478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * SSAP, like this, or should we check just the
3580d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * DSAP, as we do for other SAP values?
3581478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3582d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_cmp(OR_LLC, 0, BPF_H, (bpf_u_int32)
3583478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			     ((proto << 8) | proto));
3584478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3585478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case LLCSAP_IPX:
3586478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3587478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - are there ever SNAP frames for IPX on
3588478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * non-Ethernet 802.x networks?
3589478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3590d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_cmp(OR_LLC, 0, BPF_B,
3591478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    (bpf_int32)LLCSAP_IPX);
3592478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3593478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case ETHERTYPE_ATALK:
3594478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3595478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * 802.2-encapsulated ETHERTYPE_ATALK packets are
3596478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * SNAP packets with an organization code of
3597478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * 0x080007 (Apple, for Appletalk) and a protocol
3598478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * type of ETHERTYPE_ATALK (Appletalk).
3599478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
3600478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - check for an organization code of
3601478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * encapsulated Ethernet as well?
3602478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3603511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return gen_snap(0x080007, ETHERTYPE_ATALK);
3604478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3605478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
3606478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3607478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - we don't have to check for IPX 802.3
3608478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * here, but should we check for the IPX Ethertype?
3609478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3610478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto <= ETHERMTU) {
3611478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
3612478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * This is an LLC SAP value, so check
3613478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * the DSAP.
3614478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
3615d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return gen_cmp(OR_LLC, 0, BPF_B, (bpf_int32)proto);
3616478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		} else {
3617478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
3618478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * This is an Ethernet type; we assume that it's
3619478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * unlikely that it'll appear in the right place
3620478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * at random, and therefore check only the
3621478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * location that would hold the Ethernet type
3622478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * in a SNAP frame with an organization code of
3623478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * 0x000000 (encapsulated Ethernet).
3624478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 *
3625478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * XXX - if we were to check for the SNAP DSAP and
3626478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * LSAP, as per XXX, and were also to check for an
3627478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * organization code of 0x000000 (encapsulated
3628478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * Ethernet), we'd do
3629478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 *
3630511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *	return gen_snap(0x000000, proto);
3631478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 *
3632478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * here; for now, we don't, as per the above.
3633478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * I don't know whether it's worth the extra CPU
3634478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * time to do the right check or not.
3635478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
3636d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return gen_cmp(OR_LLC, 6, BPF_H, (bpf_int32)proto);
3637478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
3638478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
3639478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
3640478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3641478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
3642478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_hostop(addr, mask, dir, proto, src_off, dst_off)
3643478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 addr;
3644478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 mask;
3645478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir, proto;
3646478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int src_off, dst_off;
3647478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
3648478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1;
3649478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int offset;
3650478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3651478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (dir) {
3652478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3653478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SRC:
3654478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		offset = src_off;
3655478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
3656478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3657478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DST:
3658478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		offset = dst_off;
3659478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
3660478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3661478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AND:
3662478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
3663478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
3664478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
3665478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
3666478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3667478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_OR:
3668478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
3669478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
3670478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
3671478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
3672478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
3673478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3674478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
3675478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
3676478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
3677478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b0 = gen_linktype(proto);
3678d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1 = gen_mcmp(OR_LINKPL, offset, BPF_W, (bpf_int32)addr, mask);
3679478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(b0, b1);
3680478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b1;
3681478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
3682478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3683478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef INET6
3684478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
3685478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_hostop6(addr, mask, dir, proto, src_off, dst_off)
3686478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct in6_addr *addr;
3687478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct in6_addr *mask;
3688478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir, proto;
3689478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int src_off, dst_off;
3690478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
3691478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1;
3692478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int offset;
3693478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int32_t *a, *m;
3694478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3695478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (dir) {
3696478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3697478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SRC:
3698478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		offset = src_off;
3699478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
3700478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3701478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DST:
3702478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		offset = dst_off;
3703478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
3704478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3705478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AND:
3706478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
3707478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
3708478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
3709478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
3710478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3711478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_OR:
3712478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
3713478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
3714478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
3715478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
3716478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
3717478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3718478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
3719478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
3720478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
3721478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* this order is important */
3722478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	a = (u_int32_t *)addr;
3723478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	m = (u_int32_t *)mask;
3724d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1 = gen_mcmp(OR_LINKPL, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
3725d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_mcmp(OR_LINKPL, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
3726478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(b0, b1);
3727d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_mcmp(OR_LINKPL, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
3728478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(b0, b1);
3729d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_mcmp(OR_LINKPL, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
3730478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(b0, b1);
3731478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b0 = gen_linktype(proto);
3732478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(b0, b1);
3733478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b1;
3734478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
3735511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
3736478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3737478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
3738478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_ehostop(eaddr, dir)
3739478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register const u_char *eaddr;
3740478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int dir;
3741478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
3742478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct block *b0, *b1;
3743478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3744478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (dir) {
3745478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SRC:
3746d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_bcmp(OR_LINKHDR, 6, 6, eaddr);
3747478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3748478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DST:
3749d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_bcmp(OR_LINKHDR, 0, 6, eaddr);
3750478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3751478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AND:
3752478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_ehostop(eaddr, Q_SRC);
3753478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_ehostop(eaddr, Q_DST);
3754478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
3755478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
3756478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3757478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
3758478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_OR:
3759478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_ehostop(eaddr, Q_SRC);
3760478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_ehostop(eaddr, Q_DST);
3761478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
3762478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
3763511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3764511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR1:
3765511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr1' is only supported on 802.11 with 802.11 headers");
3766511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3767511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3768511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR2:
3769511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr2' is only supported on 802.11 with 802.11 headers");
3770511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3771511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3772511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR3:
3773511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr3' is only supported on 802.11 with 802.11 headers");
3774511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3775511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3776511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR4:
3777511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr4' is only supported on 802.11 with 802.11 headers");
3778511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3779511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3780511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_RA:
3781511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'ra' is only supported on 802.11 with 802.11 headers");
3782511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3783511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3784511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_TA:
3785511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'ta' is only supported on 802.11 with 802.11 headers");
3786511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3787478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
3788478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	abort();
3789478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
3790478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
3791478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3792478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
3793478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Like gen_ehostop, but for DLT_FDDI
3794478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
3795478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
3796478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_fhostop(eaddr, dir)
3797478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register const u_char *eaddr;
3798478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int dir;
3799478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
3800478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1;
3801478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3802478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (dir) {
3803478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SRC:
3804d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_bcmp(OR_LINKHDR, 6 + 1 + pcap_fddipad, 6, eaddr);
3805478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3806478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DST:
3807d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_bcmp(OR_LINKHDR, 0 + 1 + pcap_fddipad, 6, eaddr);
3808478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3809478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AND:
3810478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_fhostop(eaddr, Q_SRC);
3811478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_fhostop(eaddr, Q_DST);
3812478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
3813478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
3814478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3815478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
3816478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_OR:
3817478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_fhostop(eaddr, Q_SRC);
3818478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_fhostop(eaddr, Q_DST);
3819478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
3820478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
3821511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3822511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR1:
3823511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr1' is only supported on 802.11");
3824511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3825511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3826511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR2:
3827511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr2' is only supported on 802.11");
3828511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3829511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3830511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR3:
3831511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr3' is only supported on 802.11");
3832511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3833511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3834511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR4:
3835511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr4' is only supported on 802.11");
3836511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3837511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3838511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_RA:
3839511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'ra' is only supported on 802.11");
3840511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3841511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3842511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_TA:
3843511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'ta' is only supported on 802.11");
3844511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3845478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
3846478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	abort();
3847478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
3848478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
3849478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3850478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
3851478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Like gen_ehostop, but for DLT_IEEE802 (Token Ring)
3852478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
3853478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
3854478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_thostop(eaddr, dir)
3855478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register const u_char *eaddr;
3856478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int dir;
3857478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
3858478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct block *b0, *b1;
3859478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3860478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (dir) {
3861478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SRC:
3862d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_bcmp(OR_LINKHDR, 8, 6, eaddr);
3863478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3864478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DST:
3865d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_bcmp(OR_LINKHDR, 2, 6, eaddr);
3866478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3867478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AND:
3868478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_thostop(eaddr, Q_SRC);
3869478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_thostop(eaddr, Q_DST);
3870478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
3871478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
3872478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3873478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
3874478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_OR:
3875478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_thostop(eaddr, Q_SRC);
3876478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_thostop(eaddr, Q_DST);
3877478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
3878478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
3879511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3880511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR1:
3881511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr1' is only supported on 802.11");
3882511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3883511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3884511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR2:
3885511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr2' is only supported on 802.11");
3886511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3887511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3888511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR3:
3889511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr3' is only supported on 802.11");
3890511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3891511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3892511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR4:
3893511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr4' is only supported on 802.11");
3894511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3895511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3896511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_RA:
3897511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'ra' is only supported on 802.11");
3898511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3899511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3900511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_TA:
3901511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'ta' is only supported on 802.11");
3902511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3903478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
3904478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	abort();
3905478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
3906478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
3907478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3908478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
3909511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Like gen_ehostop, but for DLT_IEEE802_11 (802.11 wireless LAN) and
3910511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * various 802.11 + radio headers.
3911478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
3912478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
3913478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_wlanhostop(eaddr, dir)
3914478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register const u_char *eaddr;
3915478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int dir;
3916478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
3917478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct block *b0, *b1, *b2;
3918478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct slist *s;
3919478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3920511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef ENABLE_WLAN_FILTERING_PATCH
3921511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
3922511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * TODO GV 20070613
3923511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We need to disable the optimizer because the optimizer is buggy
3924511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * and wipes out some LD instructions generated by the below
3925511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * code to validate the Frame Control bits
3926511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
3927511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	no_optimize = 1;
3928511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* ENABLE_WLAN_FILTERING_PATCH */
3929511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3930478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (dir) {
3931478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SRC:
3932478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3933478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Oh, yuk.
3934478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
3935478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	For control frames, there is no SA.
3936478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
3937478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	For management frames, SA is at an
3938478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	offset of 10 from the beginning of
3939478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	the packet.
3940478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
3941478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	For data frames, SA is at an offset
3942478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	of 10 from the beginning of the packet
3943478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	if From DS is clear, at an offset of
3944478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	16 from the beginning of the packet
3945478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	if From DS is set and To DS is clear,
3946478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	and an offset of 24 from the beginning
3947478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	of the packet if From DS is set and To DS
3948478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	is set.
3949478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3950478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3951478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3952478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Generate the tests to be done for data frames
3953478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * with From DS set.
3954478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
3955478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * First, check for To DS set, i.e. check "link[1] & 0x01".
3956478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3957d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_a(OR_LINKHDR, 1, BPF_B);
3958478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = new_block(JMP(BPF_JSET));
3959478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1->s.k = 0x01;	/* To DS */
3960478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1->stmts = s;
3961478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3962478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3963478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * If To DS is set, the SA is at 24.
3964478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3965d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_bcmp(OR_LINKHDR, 24, 6, eaddr);
3966478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b1, b0);
3967478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3968478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3969478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now, check for To DS not set, i.e. check
3970478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * "!(link[1] & 0x01)".
3971478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3972d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_a(OR_LINKHDR, 1, BPF_B);
3973478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b2 = new_block(JMP(BPF_JSET));
3974478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b2->s.k = 0x01;	/* To DS */
3975478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b2->stmts = s;
3976478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_not(b2);
3977478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3978478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3979478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * If To DS is not set, the SA is at 16.
3980478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3981d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_bcmp(OR_LINKHDR, 16, 6, eaddr);
3982478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b2, b1);
3983478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3984478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3985478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now OR together the last two checks.  That gives
3986478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the complete set of checks for data frames with
3987478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * From DS set.
3988478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3989478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b1, b0);
3990478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
3991478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
3992478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now check for From DS being set, and AND that with
3993478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the ORed-together checks.
3994478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
3995d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_a(OR_LINKHDR, 1, BPF_B);
3996478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = new_block(JMP(BPF_JSET));
3997478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1->s.k = 0x02;	/* From DS */
3998478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1->stmts = s;
3999478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b1, b0);
4000478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4001478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4002478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now check for data frames with From DS not set.
4003478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4004d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_a(OR_LINKHDR, 1, BPF_B);
4005478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b2 = new_block(JMP(BPF_JSET));
4006478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b2->s.k = 0x02;	/* From DS */
4007478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b2->stmts = s;
4008478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_not(b2);
4009478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4010478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4011478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * If From DS isn't set, the SA is at 10.
4012478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4013d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_bcmp(OR_LINKHDR, 10, 6, eaddr);
4014478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b2, b1);
4015478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4016478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4017478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now OR together the checks for data frames with
4018478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * From DS not set and for data frames with From DS
4019478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * set; that gives the checks done for data frames.
4020478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4021478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b1, b0);
4022478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4023478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4024478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now check for a data frame.
4025478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * I.e, check "link[0] & 0x08".
4026478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4027d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_a(OR_LINKHDR, 0, BPF_B);
4028478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = new_block(JMP(BPF_JSET));
4029478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1->s.k = 0x08;
4030478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1->stmts = s;
4031478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4032478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4033478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * AND that with the checks done for data frames.
4034478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4035478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b1, b0);
4036478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4037478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4038478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * If the high-order bit of the type value is 0, this
4039478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * is a management frame.
4040478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * I.e, check "!(link[0] & 0x08)".
4041478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4042d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_a(OR_LINKHDR, 0, BPF_B);
4043478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b2 = new_block(JMP(BPF_JSET));
4044478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b2->s.k = 0x08;
4045478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b2->stmts = s;
4046478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_not(b2);
4047478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4048478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4049478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * For management frames, the SA is at 10.
4050478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4051d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_bcmp(OR_LINKHDR, 10, 6, eaddr);
4052478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b2, b1);
4053478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4054478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4055478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * OR that with the checks done for data frames.
4056478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * That gives the checks done for management and
4057478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * data frames.
4058478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4059478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b1, b0);
4060478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4061478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4062478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * If the low-order bit of the type value is 1,
4063478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * this is either a control frame or a frame
4064478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * with a reserved type, and thus not a
4065478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * frame with an SA.
4066478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
4067478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * I.e., check "!(link[0] & 0x04)".
4068478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4069d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_a(OR_LINKHDR, 0, BPF_B);
4070478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = new_block(JMP(BPF_JSET));
4071478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1->s.k = 0x04;
4072478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1->stmts = s;
4073478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_not(b1);
4074478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4075478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4076478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * AND that with the checks for data and management
4077478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * frames.
4078478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4079478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b1, b0);
4080478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b0;
4081478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4082478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DST:
4083478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4084478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Oh, yuk.
4085478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
4086478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	For control frames, there is no DA.
4087478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
4088478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	For management frames, DA is at an
4089478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	offset of 4 from the beginning of
4090478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	the packet.
4091478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
4092478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	For data frames, DA is at an offset
4093478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	of 4 from the beginning of the packet
4094478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	if To DS is clear and at an offset of
4095478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	16 from the beginning of the packet
4096478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *	if To DS is set.
4097478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4098478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4099478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4100478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Generate the tests to be done for data frames.
4101478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
4102478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * First, check for To DS set, i.e. "link[1] & 0x01".
4103478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4104d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_a(OR_LINKHDR, 1, BPF_B);
4105478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = new_block(JMP(BPF_JSET));
4106478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1->s.k = 0x01;	/* To DS */
4107478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1->stmts = s;
4108478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4109478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4110478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * If To DS is set, the DA is at 16.
4111478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4112d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_bcmp(OR_LINKHDR, 16, 6, eaddr);
4113478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b1, b0);
4114478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4115478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4116478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now, check for To DS not set, i.e. check
4117478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * "!(link[1] & 0x01)".
4118478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4119d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_a(OR_LINKHDR, 1, BPF_B);
4120478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b2 = new_block(JMP(BPF_JSET));
4121478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b2->s.k = 0x01;	/* To DS */
4122478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b2->stmts = s;
4123478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_not(b2);
4124478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4125478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4126478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * If To DS is not set, the DA is at 4.
4127478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4128d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_bcmp(OR_LINKHDR, 4, 6, eaddr);
4129478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b2, b1);
4130478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4131478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4132478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now OR together the last two checks.  That gives
4133478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the complete set of checks for data frames.
4134478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4135478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b1, b0);
4136478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4137478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4138478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Now check for a data frame.
4139478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * I.e, check "link[0] & 0x08".
4140478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4141d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_a(OR_LINKHDR, 0, BPF_B);
4142478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = new_block(JMP(BPF_JSET));
4143478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1->s.k = 0x08;
4144478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1->stmts = s;
4145478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4146478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4147478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * AND that with the checks done for data frames.
4148478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4149478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b1, b0);
4150478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4151478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4152478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * If the high-order bit of the type value is 0, this
4153478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * is a management frame.
4154478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * I.e, check "!(link[0] & 0x08)".
4155478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4156d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_a(OR_LINKHDR, 0, BPF_B);
4157478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b2 = new_block(JMP(BPF_JSET));
4158478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b2->s.k = 0x08;
4159478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b2->stmts = s;
4160478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_not(b2);
4161478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4162478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4163478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * For management frames, the DA is at 4.
4164478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4165d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_bcmp(OR_LINKHDR, 4, 6, eaddr);
4166478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b2, b1);
4167478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4168478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4169478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * OR that with the checks done for data frames.
4170478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * That gives the checks done for management and
4171478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * data frames.
4172478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4173478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b1, b0);
4174478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4175478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4176478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * If the low-order bit of the type value is 1,
4177478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * this is either a control frame or a frame
4178478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * with a reserved type, and thus not a
4179478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * frame with an SA.
4180478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
4181478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * I.e., check "!(link[0] & 0x04)".
4182478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4183d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_a(OR_LINKHDR, 0, BPF_B);
4184478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = new_block(JMP(BPF_JSET));
4185478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1->s.k = 0x04;
4186478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1->stmts = s;
4187478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_not(b1);
4188478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4189478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4190478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * AND that with the checks for data and management
4191478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * frames.
4192478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4193478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b1, b0);
4194478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b0;
4195478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4196511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_RA:
4197511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4198511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Not present in management frames; addr1 in other
4199511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * frames.
4200511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4201511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4202511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4203511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If the high-order bit of the type value is 0, this
4204511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * is a management frame.
4205511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * I.e, check "(link[0] & 0x08)".
4206511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4207d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_a(OR_LINKHDR, 0, BPF_B);
4208511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b1 = new_block(JMP(BPF_JSET));
4209511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b1->s.k = 0x08;
4210511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b1->stmts = s;
4211511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4212511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4213511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Check addr1.
4214511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4215d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_bcmp(OR_LINKHDR, 4, 6, eaddr);
4216511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4217511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4218511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * AND that with the check of addr1.
4219511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4220511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_and(b1, b0);
4221511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (b0);
4222511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4223511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_TA:
4224511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4225511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Not present in management frames; addr2, if present,
4226511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * in other frames.
4227511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4228511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4229511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4230511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Not present in CTS or ACK control frames.
4231511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4232d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
4233511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			IEEE80211_FC0_TYPE_MASK);
4234511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_not(b0);
4235d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
4236511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			IEEE80211_FC0_SUBTYPE_MASK);
4237511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_not(b1);
4238d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b2 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
4239511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			IEEE80211_FC0_SUBTYPE_MASK);
4240511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_not(b2);
4241511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_and(b1, b2);
4242511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_or(b0, b2);
4243511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4244511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4245511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If the high-order bit of the type value is 0, this
4246511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * is a management frame.
4247511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * I.e, check "(link[0] & 0x08)".
4248511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4249d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_load_a(OR_LINKHDR, 0, BPF_B);
4250511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b1 = new_block(JMP(BPF_JSET));
4251511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b1->s.k = 0x08;
4252511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b1->stmts = s;
4253511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4254511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4255511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * AND that with the check for frames other than
4256511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * CTS and ACK frames.
4257511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4258511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_and(b1, b2);
4259511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4260511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4261511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Check addr2.
4262511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4263d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_bcmp(OR_LINKHDR, 10, 6, eaddr);
4264511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_and(b2, b1);
4265511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return b1;
4266511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4267511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
4268511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX - add BSSID keyword?
4269511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
4270511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR1:
4271d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return (gen_bcmp(OR_LINKHDR, 4, 6, eaddr));
4272511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4273511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR2:
4274511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4275511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Not present in CTS or ACK control frames.
4276511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4277d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
4278511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			IEEE80211_FC0_TYPE_MASK);
4279511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_not(b0);
4280d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
4281511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			IEEE80211_FC0_SUBTYPE_MASK);
4282511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_not(b1);
4283d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b2 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
4284511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			IEEE80211_FC0_SUBTYPE_MASK);
4285511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_not(b2);
4286511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_and(b1, b2);
4287511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_or(b0, b2);
4288d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_bcmp(OR_LINKHDR, 10, 6, eaddr);
4289511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_and(b2, b1);
4290511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return b1;
4291511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4292511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR3:
4293511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4294511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Not present in control frames.
4295511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4296d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
4297511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			IEEE80211_FC0_TYPE_MASK);
4298511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_not(b0);
4299d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_bcmp(OR_LINKHDR, 16, 6, eaddr);
4300511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_and(b0, b1);
4301511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return b1;
4302511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4303511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR4:
4304511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4305511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Present only if the direction mask has both "From DS"
4306511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * and "To DS" set.  Neither control frames nor management
4307511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * frames should have both of those set, so we don't
4308511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * check the frame type.
4309511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4310d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_mcmp(OR_LINKHDR, 1, BPF_B,
4311511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
4312d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_bcmp(OR_LINKHDR, 24, 6, eaddr);
4313511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_and(b0, b1);
4314511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return b1;
4315511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4316478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AND:
4317478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_wlanhostop(eaddr, Q_SRC);
4318478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_wlanhostop(eaddr, Q_DST);
4319478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
4320478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
4321478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4322478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
4323478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_OR:
4324478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_wlanhostop(eaddr, Q_SRC);
4325478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_wlanhostop(eaddr, Q_DST);
4326478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
4327478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
4328478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
4329478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	abort();
4330478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
4331478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
4332478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4333478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
4334478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Like gen_ehostop, but for RFC 2625 IP-over-Fibre-Channel.
4335478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * (We assume that the addresses are IEEE 48-bit MAC addresses,
4336478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * as the RFC states.)
4337478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
4338478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
4339478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_ipfchostop(eaddr, dir)
4340478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register const u_char *eaddr;
4341478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int dir;
4342478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
4343478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct block *b0, *b1;
4344478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4345478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (dir) {
4346478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SRC:
4347d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_bcmp(OR_LINKHDR, 10, 6, eaddr);
4348478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4349478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DST:
4350d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_bcmp(OR_LINKHDR, 2, 6, eaddr);
4351478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4352478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AND:
4353478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_ipfchostop(eaddr, Q_SRC);
4354478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_ipfchostop(eaddr, Q_DST);
4355478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
4356478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
4357478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4358478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
4359478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_OR:
4360478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_ipfchostop(eaddr, Q_SRC);
4361478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_ipfchostop(eaddr, Q_DST);
4362478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
4363478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
4364511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4365511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR1:
4366511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr1' is only supported on 802.11");
4367511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
4368511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4369511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR2:
4370511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr2' is only supported on 802.11");
4371511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
4372511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4373511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR3:
4374511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr3' is only supported on 802.11");
4375511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
4376511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4377511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR4:
4378511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr4' is only supported on 802.11");
4379511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
4380511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4381511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_RA:
4382511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'ra' is only supported on 802.11");
4383511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
4384511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4385511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_TA:
4386511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'ta' is only supported on 802.11");
4387511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
4388478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
4389478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	abort();
4390478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
4391478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
4392478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4393478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
4394478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * This is quite tricky because there may be pad bytes in front of the
4395478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * DECNET header, and then there are two possible data packet formats that
4396478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * carry both src and dst addresses, plus 5 packet types in a format that
4397478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * carries only the src node, plus 2 types that use a different format and
4398478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * also carry just the src node.
4399478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
4400478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Yuck.
4401478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
4402478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Instead of doing those all right, we just look for data packets with
4403478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * 0 or 1 bytes of padding.  If you want to look at other packets, that
4404478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * will require a lot more hacking.
4405478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
4406478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * To add support for filtering on DECNET "areas" (network numbers)
4407478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * one would want to add a "mask" argument to this routine.  That would
4408478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * make the filter even more inefficient, although one could be clever
4409478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * and not generate masking instructions if the mask is 0xFFFF.
4410478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
4411478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
4412478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_dnhostop(addr, dir)
4413478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 addr;
4414478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir;
4415478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
4416478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1, *b2, *tmp;
4417478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int offset_lh;	/* offset if long header is received */
4418478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int offset_sh;	/* offset if short header is received */
4419478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4420478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (dir) {
4421478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4422478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DST:
4423478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		offset_sh = 1;	/* follows flags */
4424478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		offset_lh = 7;	/* flgs,darea,dsubarea,HIORD */
4425478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4426478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4427478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SRC:
4428478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		offset_sh = 3;	/* follows flags, dstnode */
4429478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		offset_lh = 15;	/* flgs,darea,dsubarea,did,sarea,ssub,HIORD */
4430478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4431478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4432478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AND:
4433478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* Inefficient because we do our Calvinball dance twice */
4434478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_dnhostop(addr, Q_SRC);
4435478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_dnhostop(addr, Q_DST);
4436478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
4437478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
4438478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4439478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_OR:
4440478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
4441478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* Inefficient because we do our Calvinball dance twice */
4442478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_dnhostop(addr, Q_SRC);
4443478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_dnhostop(addr, Q_DST);
4444478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
4445478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
4446478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4447478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISO:
4448478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("ISO host filtering not implemented");
4449478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4450478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
4451478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
4452478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
4453478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b0 = gen_linktype(ETHERTYPE_DN);
4454478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* Check for pad = 1, long header case */
4455d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	tmp = gen_mcmp(OR_LINKPL, 2, BPF_H,
4456478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	    (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF));
4457d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1 = gen_cmp(OR_LINKPL, 2 + 1 + offset_lh,
4458478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	    BPF_H, (bpf_int32)ntohs((u_short)addr));
4459478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(tmp, b1);
4460478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* Check for pad = 0, long header case */
4461d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	tmp = gen_mcmp(OR_LINKPL, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
4462d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b2 = gen_cmp(OR_LINKPL, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr));
4463478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(tmp, b2);
4464478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_or(b2, b1);
4465478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* Check for pad = 1, short header case */
4466d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	tmp = gen_mcmp(OR_LINKPL, 2, BPF_H,
4467478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	    (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF));
4468d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b2 = gen_cmp(OR_LINKPL, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
4469478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(tmp, b2);
4470478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_or(b2, b1);
4471478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* Check for pad = 0, short header case */
4472d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	tmp = gen_mcmp(OR_LINKPL, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
4473d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b2 = gen_cmp(OR_LINKPL, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
4474478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(tmp, b2);
4475478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_or(b2, b1);
4476478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4477478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* Combine with test for linktype */
4478478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(b0, b1);
4479478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b1;
4480478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
4481478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4482478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
4483478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Generate a check for IPv4 or IPv6 for MPLS-encapsulated packets;
4484478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * test the bottom-of-stack bit, and then check the version number
4485478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * field in the IP header.
4486478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
4487478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
4488478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_mpls_linktype(proto)
4489478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int proto;
4490478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
4491478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1;
4492478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4493478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        switch (proto) {
4494478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4495478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case Q_IP:
4496478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                /* match the bottom-of-stack bit */
4497d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                b0 = gen_mcmp(OR_LINKPL, -2, BPF_B, 0x01, 0x01);
4498478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                /* match the IPv4 version number */
4499d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                b1 = gen_mcmp(OR_LINKPL, 0, BPF_B, 0x40, 0xf0);
4500478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                gen_and(b0, b1);
4501478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                return b1;
4502d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
4503478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project       case Q_IPV6:
4504478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                /* match the bottom-of-stack bit */
4505d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                b0 = gen_mcmp(OR_LINKPL, -2, BPF_B, 0x01, 0x01);
4506478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                /* match the IPv4 version number */
4507d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                b1 = gen_mcmp(OR_LINKPL, 0, BPF_B, 0x60, 0xf0);
4508478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                gen_and(b0, b1);
4509478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                return b1;
4510d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
4511478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project       default:
4512478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                abort();
4513478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        }
4514478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
4515478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4516478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
4517478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_host(addr, mask, proto, dir, type)
4518478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 addr;
4519478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 mask;
4520478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int proto;
4521478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir;
4522478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int type;
4523478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
4524478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1;
4525478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	const char *typestr;
4526478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4527478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (type == Q_NET)
4528478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		typestr = "net";
4529478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	else
4530478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		typestr = "host";
4531478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4532478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (proto) {
4533478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4534478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
4535478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_host(addr, mask, Q_IP, dir, type);
4536478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4537478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Only check for non-IPv4 addresses if we're not
4538478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * checking MPLS-encapsulated packets.
4539478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4540478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (label_stack_depth == 0) {
4541478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			b1 = gen_host(addr, mask, Q_ARP, dir, type);
4542478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_or(b0, b1);
4543478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			b0 = gen_host(addr, mask, Q_RARP, dir, type);
4544478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_or(b1, b0);
4545478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
4546478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b0;
4547478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4548478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IP:
4549478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return gen_hostop(addr, mask, dir, ETHERTYPE_IP, 12, 16);
4550478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4551478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_RARP:
4552478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, 14, 24);
4553478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4554478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ARP:
4555478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, 14, 24);
4556478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4557478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_TCP:
4558478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'tcp' modifier applied to %s", typestr);
4559478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4560478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SCTP:
4561478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'sctp' modifier applied to %s", typestr);
4562478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4563478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_UDP:
4564478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'udp' modifier applied to %s", typestr);
4565478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4566478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ICMP:
4567478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'icmp' modifier applied to %s", typestr);
4568478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4569478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IGMP:
4570478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'igmp' modifier applied to %s", typestr);
4571478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4572478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IGRP:
4573478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'igrp' modifier applied to %s", typestr);
4574478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4575478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_PIM:
4576478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'pim' modifier applied to %s", typestr);
4577478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4578478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_VRRP:
4579478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'vrrp' modifier applied to %s", typestr);
4580478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4581511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_CARP:
4582511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'carp' modifier applied to %s", typestr);
4583511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4584478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ATALK:
4585478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("ATALK host filtering not implemented");
4586478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4587478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AARP:
4588478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("AARP host filtering not implemented");
4589478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4590478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DECNET:
4591478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return gen_dnhostop(addr, dir);
4592478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4593478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SCA:
4594478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("SCA host filtering not implemented");
4595478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4596478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_LAT:
4597478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("LAT host filtering not implemented");
4598478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4599478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_MOPDL:
4600478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("MOPDL host filtering not implemented");
4601478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4602478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_MOPRC:
4603478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("MOPRC host filtering not implemented");
4604478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4605478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IPV6:
4606478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'ip6' modifier applied to ip host");
4607478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4608478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ICMPV6:
4609478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'icmp6' modifier applied to %s", typestr);
4610478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4611478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AH:
4612478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'ah' modifier applied to %s", typestr);
4613478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4614478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ESP:
4615478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'esp' modifier applied to %s", typestr);
4616478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4617478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISO:
4618478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("ISO host filtering not implemented");
4619478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4620478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ESIS:
4621478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'esis' modifier applied to %s", typestr);
4622478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4623478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISIS:
4624478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'isis' modifier applied to %s", typestr);
4625478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4626478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_CLNP:
4627478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'clnp' modifier applied to %s", typestr);
4628478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4629478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_STP:
4630478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'stp' modifier applied to %s", typestr);
4631478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4632478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IPX:
4633478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("IPX host filtering not implemented");
4634478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4635478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_NETBEUI:
4636478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'netbeui' modifier applied to %s", typestr);
4637478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4638478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_RADIO:
4639478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'radio' modifier applied to %s", typestr);
4640478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4641478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
4642478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
4643478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
4644478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
4645478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
4646478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4647478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef INET6
4648478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
4649478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_host6(addr, mask, proto, dir, type)
4650478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct in6_addr *addr;
4651478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct in6_addr *mask;
4652478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int proto;
4653478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir;
4654478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int type;
4655478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
4656478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	const char *typestr;
4657478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4658478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (type == Q_NET)
4659478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		typestr = "net";
4660478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	else
4661478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		typestr = "host";
4662478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4663478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (proto) {
4664478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4665478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
4666478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return gen_host6(addr, mask, Q_IPV6, dir, type);
4667478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4668511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_LINK:
4669511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("link-layer modifier applied to ip6 %s", typestr);
4670511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4671478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IP:
4672478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'ip' modifier applied to ip6 %s", typestr);
4673478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4674478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_RARP:
4675478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'rarp' modifier applied to ip6 %s", typestr);
4676478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4677478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ARP:
4678478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'arp' modifier applied to ip6 %s", typestr);
4679478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4680478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SCTP:
4681478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'sctp' modifier applied to %s", typestr);
4682478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4683478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_TCP:
4684478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'tcp' modifier applied to %s", typestr);
4685478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4686478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_UDP:
4687478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'udp' modifier applied to %s", typestr);
4688478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4689478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ICMP:
4690478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'icmp' modifier applied to %s", typestr);
4691478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4692478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IGMP:
4693478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'igmp' modifier applied to %s", typestr);
4694478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4695478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IGRP:
4696478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'igrp' modifier applied to %s", typestr);
4697478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4698478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_PIM:
4699478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'pim' modifier applied to %s", typestr);
4700478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4701478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_VRRP:
4702478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'vrrp' modifier applied to %s", typestr);
4703478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4704511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_CARP:
4705511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'carp' modifier applied to %s", typestr);
4706511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4707478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ATALK:
4708478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("ATALK host filtering not implemented");
4709478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4710478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AARP:
4711478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("AARP host filtering not implemented");
4712478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4713478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DECNET:
4714478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'decnet' modifier applied to ip6 %s", typestr);
4715478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4716478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SCA:
4717478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("SCA host filtering not implemented");
4718478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4719478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_LAT:
4720478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("LAT host filtering not implemented");
4721478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4722478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_MOPDL:
4723478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("MOPDL host filtering not implemented");
4724478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4725478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_MOPRC:
4726478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("MOPRC host filtering not implemented");
4727478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4728478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IPV6:
4729478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6, 8, 24);
4730478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4731478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ICMPV6:
4732478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'icmp6' modifier applied to %s", typestr);
4733478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4734478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AH:
4735478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'ah' modifier applied to %s", typestr);
4736478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4737478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ESP:
4738478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'esp' modifier applied to %s", typestr);
4739478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4740478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISO:
4741478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("ISO host filtering not implemented");
4742478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4743478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ESIS:
4744478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'esis' modifier applied to %s", typestr);
4745478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4746478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISIS:
4747478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'isis' modifier applied to %s", typestr);
4748478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4749478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_CLNP:
4750478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'clnp' modifier applied to %s", typestr);
4751478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4752478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_STP:
4753478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'stp' modifier applied to %s", typestr);
4754478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4755478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IPX:
4756478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("IPX host filtering not implemented");
4757478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4758478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_NETBEUI:
4759478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'netbeui' modifier applied to %s", typestr);
4760478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4761478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_RADIO:
4762478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'radio' modifier applied to %s", typestr);
4763478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4764478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
4765478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
4766478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
4767478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
4768478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
4769511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
4770478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4771478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef INET6
4772478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
4773478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_gateway(eaddr, alist, proto, dir)
4774478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	const u_char *eaddr;
4775478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 **alist;
4776478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int proto;
4777478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir;
4778478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
4779478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1, *tmp;
4780478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4781478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (dir != 0)
4782478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("direction applied to 'gateway'");
4783478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4784478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (proto) {
4785478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
4786478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IP:
4787478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ARP:
4788478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_RARP:
4789511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		switch (linktype) {
4790511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_EN10MB:
4791511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_NETANALYZER:
4792511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_NETANALYZER_TRANSPARENT:
4793d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b1 = gen_prevlinkhdr_check();
4794511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b0 = gen_ehostop(eaddr, Q_OR);
4795d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			if (b1 != NULL)
4796d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes				gen_and(b1, b0);
4797511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
4798511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_FDDI:
4799511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b0 = gen_fhostop(eaddr, Q_OR);
4800511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
4801478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case DLT_IEEE802:
4802511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b0 = gen_thostop(eaddr, Q_OR);
4803511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
4804478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case DLT_IEEE802_11:
4805511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_PRISM_HEADER:
4806478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case DLT_IEEE802_11_RADIO_AVS:
4807478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case DLT_IEEE802_11_RADIO:
4808511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_PPI:
4809511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b0 = gen_wlanhostop(eaddr, Q_OR);
4810511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
4811511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_SUNATM:
4812478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
4813d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			 * This is LLC-multiplexed traffic; if it were
4814d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			 * LANE, linktype would have been set to
4815d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			 * DLT_EN10MB.
4816478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
4817d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			bpf_error(
4818d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			    "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
4819511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
4820478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case DLT_IP_OVER_FC:
4821511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b0 = gen_ipfchostop(eaddr, Q_OR);
4822511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
4823511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		default:
4824511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error(
4825511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
4826511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4827478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST);
4828478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		while (*alist) {
4829478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR,
4830478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			    Q_HOST);
4831478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_or(b1, tmp);
4832478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			b1 = tmp;
4833478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
4834478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_not(b1);
4835478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
4836478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
4837478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
4838478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_error("illegal modifier of 'gateway'");
4839478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
4840478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
4841478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
4842478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4843478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
4844478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_proto_abbrev(proto)
4845478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int proto;
4846478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
4847478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0;
4848478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b1;
4849478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4850478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (proto) {
4851478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4852478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SCTP:
4853478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(IPPROTO_SCTP, Q_IP, Q_DEFAULT);
4854478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(IPPROTO_SCTP, Q_IPV6, Q_DEFAULT);
4855478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
4856478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4857478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4858478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_TCP:
4859478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT);
4860478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
4861478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
4862478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4863478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4864478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_UDP:
4865478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT);
4866478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
4867478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
4868478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4869478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4870478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ICMP:
4871478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(IPPROTO_ICMP, Q_IP, Q_DEFAULT);
4872478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4873478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4874478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef	IPPROTO_IGMP
4875478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define	IPPROTO_IGMP	2
4876478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
4877478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4878478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IGMP:
4879478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(IPPROTO_IGMP, Q_IP, Q_DEFAULT);
4880478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4881478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4882478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef	IPPROTO_IGRP
4883478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define	IPPROTO_IGRP	9
4884478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
4885478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IGRP:
4886478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(IPPROTO_IGRP, Q_IP, Q_DEFAULT);
4887478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4888478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4889478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef IPPROTO_PIM
4890478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define IPPROTO_PIM	103
4891478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
4892478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4893478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_PIM:
4894478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT);
4895478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
4896478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
4897478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4898478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4899478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef IPPROTO_VRRP
4900478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define IPPROTO_VRRP	112
4901478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
4902478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4903478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_VRRP:
4904478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(IPPROTO_VRRP, Q_IP, Q_DEFAULT);
4905478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4906478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4907511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef IPPROTO_CARP
4908511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define IPPROTO_CARP	112
4909511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
4910511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4911511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_CARP:
4912511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b1 = gen_proto(IPPROTO_CARP, Q_IP, Q_DEFAULT);
4913511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
4914511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4915478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IP:
4916478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 =  gen_linktype(ETHERTYPE_IP);
4917478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4918478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4919478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ARP:
4920478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 =  gen_linktype(ETHERTYPE_ARP);
4921478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4922478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4923478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_RARP:
4924478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 =  gen_linktype(ETHERTYPE_REVARP);
4925478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4926478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4927478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_LINK:
4928478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("link layer applied in wrong context");
4929478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4930478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ATALK:
4931478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 =  gen_linktype(ETHERTYPE_ATALK);
4932478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4933478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4934478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AARP:
4935478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 =  gen_linktype(ETHERTYPE_AARP);
4936478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4937478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4938478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DECNET:
4939478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 =  gen_linktype(ETHERTYPE_DN);
4940478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4941478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4942478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SCA:
4943478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 =  gen_linktype(ETHERTYPE_SCA);
4944478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4945478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4946478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_LAT:
4947478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 =  gen_linktype(ETHERTYPE_LAT);
4948478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4949478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4950478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_MOPDL:
4951478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 =  gen_linktype(ETHERTYPE_MOPDL);
4952478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4953478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4954478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_MOPRC:
4955478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 =  gen_linktype(ETHERTYPE_MOPRC);
4956478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4957478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4958478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IPV6:
4959478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_linktype(ETHERTYPE_IPV6);
4960478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4961478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4962478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef IPPROTO_ICMPV6
4963478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define IPPROTO_ICMPV6	58
4964478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
4965478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ICMPV6:
4966478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT);
4967478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4968478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4969478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef IPPROTO_AH
4970478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define IPPROTO_AH	51
4971478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
4972478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AH:
4973478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT);
4974478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT);
4975478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
4976478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4977478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4978478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef IPPROTO_ESP
4979478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define IPPROTO_ESP	50
4980478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
4981478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ESP:
4982478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT);
4983478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
4984478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
4985478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4986478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4987478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISO:
4988478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_linktype(LLCSAP_ISONS);
4989478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4990478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4991478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ESIS:
4992478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT);
4993478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4994478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4995478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISIS:
4996478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
4997478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
4998478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4999478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISIS_L1: /* all IS-IS Level1 PDU-Types */
5000478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
5001478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
5002478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5003478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
5004478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5005478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
5006478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5007478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
5008478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5009478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5010478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5011478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISIS_L2: /* all IS-IS Level2 PDU-Types */
5012478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
5013478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
5014478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5015478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
5016478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5017478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
5018478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5019478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
5020478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5021478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5022478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5023478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISIS_IIH: /* all IS-IS Hello PDU-Types */
5024478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
5025478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
5026478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5027478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);
5028478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5029478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5030478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5031478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISIS_LSP:
5032478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
5033478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
5034478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5035478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5036478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5037478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISIS_SNP:
5038478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
5039478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
5040478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5041478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
5042478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5043478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
5044478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5045478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5046478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5047478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISIS_CSNP:
5048478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
5049478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
5050478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5051478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5052478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5053478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISIS_PSNP:
5054478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
5055478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
5056478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5057478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5058478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5059478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_CLNP:
5060478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT);
5061478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5062478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5063478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_STP:
5064478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_linktype(LLCSAP_8021D);
5065478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5066478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5067478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IPX:
5068478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_linktype(LLCSAP_IPX);
5069478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5070478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5071478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_NETBEUI:
5072478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_linktype(LLCSAP_NETBEUI);
5073478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5074478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5075478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_RADIO:
5076478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'radio' is not a valid protocol type");
5077478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5078478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
5079478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
5080478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5081478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b1;
5082478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5083478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5084478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
5085478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_ipfrag()
5086478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5087478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s;
5088478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b;
5089478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5090511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* not IPv4 frag other than the first frag */
5091d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s = gen_load_a(OR_LINKPL, 6, BPF_H);
5092478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b = new_block(JMP(BPF_JSET));
5093478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b->s.k = 0x1fff;
5094478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b->stmts = s;
5095478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_not(b);
5096478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5097478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b;
5098478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5099478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5100478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
5101478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Generate a comparison to a port value in the transport-layer header
5102478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * at the specified offset from the beginning of that header.
5103478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
5104478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * XXX - this handles a variable-length prefix preceding the link-layer
5105478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * header, such as the radiotap or AVS radio prefix, but doesn't handle
5106478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * variable-length link-layer headers (such as Token Ring or 802.11
5107478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * headers).
5108478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
5109478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
5110478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_portatom(off, v)
5111478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int off;
5112478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_int32 v;
5113478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5114478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return gen_cmp(OR_TRAN_IPV4, off, BPF_H, v);
5115478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5116478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5117478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
5118478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_portatom6(off, v)
5119478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int off;
5120478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_int32 v;
5121478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5122478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return gen_cmp(OR_TRAN_IPV6, off, BPF_H, v);
5123478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5124478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5125478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
5126478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_portop(port, proto, dir)
5127478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int port, proto, dir;
5128478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5129478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1, *tmp;
5130478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5131511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* ip proto 'proto' and not a fragment other than the first fragment */
5132d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	tmp = gen_cmp(OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
5133478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b0 = gen_ipfrag();
5134478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(tmp, b0);
5135478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5136478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (dir) {
5137478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SRC:
5138478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portatom(0, (bpf_int32)port);
5139478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5140478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5141478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DST:
5142478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portatom(2, (bpf_int32)port);
5143478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5144478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5145478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_OR:
5146478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
5147478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_portatom(0, (bpf_int32)port);
5148478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portatom(2, (bpf_int32)port);
5149478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(tmp, b1);
5150478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5151478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5152478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AND:
5153478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_portatom(0, (bpf_int32)port);
5154478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portatom(2, (bpf_int32)port);
5155478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(tmp, b1);
5156478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5157478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5158478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
5159478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
5160478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5161478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(b0, b1);
5162478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5163478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b1;
5164478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5165478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5166478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
5167478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_port(port, ip_proto, dir)
5168478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int port;
5169478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int ip_proto;
5170478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir;
5171478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5172478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1, *tmp;
5173478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5174478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
5175478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * ether proto ip
5176478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 *
5177478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * For FDDI, RFC 1188 says that SNAP encapsulation is used,
5178478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * not LLC encapsulation with LLCSAP_IP.
5179478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 *
5180478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * For IEEE 802 networks - which includes 802.5 token ring
5181478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042
5182478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * says that SNAP encapsulation is used, not LLC encapsulation
5183478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * with LLCSAP_IP.
5184478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 *
5185478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and
5186478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * RFC 2225 say that SNAP encapsulation is used, not LLC
5187478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * encapsulation with LLCSAP_IP.
5188478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 *
5189478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * So we always check for ETHERTYPE_IP.
5190478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
5191478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b0 =  gen_linktype(ETHERTYPE_IP);
5192478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5193478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (ip_proto) {
5194478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case IPPROTO_UDP:
5195478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case IPPROTO_TCP:
5196478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case IPPROTO_SCTP:
5197478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portop(port, ip_proto, dir);
5198478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5199478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5200478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case PROTO_UNDEF:
5201478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_portop(port, IPPROTO_TCP, dir);
5202478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portop(port, IPPROTO_UDP, dir);
5203478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(tmp, b1);
5204478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_portop(port, IPPROTO_SCTP, dir);
5205478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(tmp, b1);
5206478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5207478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5208478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
5209478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
5210478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5211478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(b0, b1);
5212478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b1;
5213478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5214478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5215478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
5216478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_portop6(port, proto, dir)
5217478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int port, proto, dir;
5218478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5219478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1, *tmp;
5220478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5221478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* ip6 proto 'proto' */
5222511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* XXX - catch the first fragment of a fragmented packet? */
5223d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_cmp(OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
5224478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5225478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (dir) {
5226478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SRC:
5227478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portatom6(0, (bpf_int32)port);
5228478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5229478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5230478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DST:
5231478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portatom6(2, (bpf_int32)port);
5232478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5233478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5234478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_OR:
5235478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
5236478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_portatom6(0, (bpf_int32)port);
5237478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portatom6(2, (bpf_int32)port);
5238478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(tmp, b1);
5239478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5240478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5241478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AND:
5242478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_portatom6(0, (bpf_int32)port);
5243478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portatom6(2, (bpf_int32)port);
5244478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(tmp, b1);
5245478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5246478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5247478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
5248478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
5249478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5250478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(b0, b1);
5251478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5252478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b1;
5253478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5254478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5255478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
5256478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_port6(port, ip_proto, dir)
5257478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int port;
5258478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int ip_proto;
5259478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir;
5260478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5261478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1, *tmp;
5262478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5263478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* link proto ip6 */
5264478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b0 =  gen_linktype(ETHERTYPE_IPV6);
5265478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5266478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (ip_proto) {
5267478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case IPPROTO_UDP:
5268478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case IPPROTO_TCP:
5269478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case IPPROTO_SCTP:
5270478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portop6(port, ip_proto, dir);
5271478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5272478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5273478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case PROTO_UNDEF:
5274478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_portop6(port, IPPROTO_TCP, dir);
5275478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portop6(port, IPPROTO_UDP, dir);
5276478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(tmp, b1);
5277478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_portop6(port, IPPROTO_SCTP, dir);
5278478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(tmp, b1);
5279478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5280478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5281478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
5282478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
5283478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5284478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(b0, b1);
5285478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b1;
5286478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5287478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5288478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/* gen_portrange code */
5289478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
5290478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_portrangeatom(off, v1, v2)
5291478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int off;
5292478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_int32 v1, v2;
5293478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5294478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b1, *b2;
5295478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5296478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (v1 > v2) {
5297478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
5298478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Reverse the order of the ports, so v1 is the lower one.
5299478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
5300478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_int32 vtemp;
5301478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5302478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		vtemp = v1;
5303478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		v1 = v2;
5304478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		v2 = vtemp;
5305478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5306478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5307478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b1 = gen_cmp_ge(OR_TRAN_IPV4, off, BPF_H, v1);
5308478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b2 = gen_cmp_le(OR_TRAN_IPV4, off, BPF_H, v2);
5309478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5310d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	gen_and(b1, b2);
5311478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5312478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b2;
5313478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5314478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5315478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
5316478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_portrangeop(port1, port2, proto, dir)
5317478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int port1, port2;
5318478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int proto;
5319478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir;
5320478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5321478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1, *tmp;
5322478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5323511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* ip proto 'proto' and not a fragment other than the first fragment */
5324d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	tmp = gen_cmp(OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
5325478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b0 = gen_ipfrag();
5326478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(tmp, b0);
5327478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5328478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (dir) {
5329478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SRC:
5330478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
5331478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5332478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5333478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DST:
5334478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
5335478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5336478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5337478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_OR:
5338478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
5339478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
5340478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
5341478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(tmp, b1);
5342478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5343478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5344478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AND:
5345478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
5346478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
5347478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(tmp, b1);
5348478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5349478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5350478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
5351478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
5352478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5353478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(b0, b1);
5354478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5355478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b1;
5356478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5357478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5358478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
5359478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_portrange(port1, port2, ip_proto, dir)
5360478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int port1, port2;
5361478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int ip_proto;
5362478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir;
5363478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5364478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1, *tmp;
5365478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5366478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* link proto ip */
5367478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b0 =  gen_linktype(ETHERTYPE_IP);
5368478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5369478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (ip_proto) {
5370478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case IPPROTO_UDP:
5371478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case IPPROTO_TCP:
5372478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case IPPROTO_SCTP:
5373478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portrangeop(port1, port2, ip_proto, dir);
5374478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5375478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5376478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case PROTO_UNDEF:
5377478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_portrangeop(port1, port2, IPPROTO_TCP, dir);
5378478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portrangeop(port1, port2, IPPROTO_UDP, dir);
5379478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(tmp, b1);
5380478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_portrangeop(port1, port2, IPPROTO_SCTP, dir);
5381478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(tmp, b1);
5382478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5383478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5384478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
5385478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
5386478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5387478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(b0, b1);
5388478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b1;
5389478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5390478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5391478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
5392478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_portrangeatom6(off, v1, v2)
5393478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int off;
5394478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_int32 v1, v2;
5395478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5396478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b1, *b2;
5397478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5398478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (v1 > v2) {
5399478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
5400478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Reverse the order of the ports, so v1 is the lower one.
5401478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
5402478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_int32 vtemp;
5403478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5404478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		vtemp = v1;
5405478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		v1 = v2;
5406478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		v2 = vtemp;
5407478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5408478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5409478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b1 = gen_cmp_ge(OR_TRAN_IPV6, off, BPF_H, v1);
5410478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b2 = gen_cmp_le(OR_TRAN_IPV6, off, BPF_H, v2);
5411478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5412d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	gen_and(b1, b2);
5413478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5414478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b2;
5415478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5416478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5417478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
5418478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_portrangeop6(port1, port2, proto, dir)
5419478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int port1, port2;
5420478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int proto;
5421478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir;
5422478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5423478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1, *tmp;
5424478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5425478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* ip6 proto 'proto' */
5426511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* XXX - catch the first fragment of a fragmented packet? */
5427d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_cmp(OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
5428478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5429478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (dir) {
5430478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SRC:
5431478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
5432478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5433478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5434478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DST:
5435478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
5436478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5437478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5438478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_OR:
5439478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
5440478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
5441478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
5442478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(tmp, b1);
5443478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5444478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5445478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AND:
5446478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
5447478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
5448478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(tmp, b1);
5449478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5450478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5451478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
5452478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
5453478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5454478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(b0, b1);
5455478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5456478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b1;
5457478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5458478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5459478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
5460478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_portrange6(port1, port2, ip_proto, dir)
5461478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int port1, port2;
5462478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int ip_proto;
5463478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir;
5464478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5465478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1, *tmp;
5466478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5467478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* link proto ip6 */
5468478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b0 =  gen_linktype(ETHERTYPE_IPV6);
5469478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5470478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (ip_proto) {
5471478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case IPPROTO_UDP:
5472478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case IPPROTO_TCP:
5473478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case IPPROTO_SCTP:
5474478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portrangeop6(port1, port2, ip_proto, dir);
5475478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5476478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5477478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case PROTO_UNDEF:
5478478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_portrangeop6(port1, port2, IPPROTO_TCP, dir);
5479478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_portrangeop6(port1, port2, IPPROTO_UDP, dir);
5480478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(tmp, b1);
5481478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = gen_portrangeop6(port1, port2, IPPROTO_SCTP, dir);
5482478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(tmp, b1);
5483478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5484478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5485478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
5486478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
5487478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5488478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(b0, b1);
5489478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b1;
5490478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5491478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5492478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
5493478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectlookup_proto(name, proto)
5494478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register const char *name;
5495478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int proto;
5496478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5497478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int v;
5498478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5499478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (proto) {
5500478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5501478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
5502478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IP:
5503478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IPV6:
5504478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		v = pcap_nametoproto(name);
5505478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (v == PROTO_UNDEF)
5506478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("unknown ip proto '%s'", name);
5507478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5508478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5509478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_LINK:
5510478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* XXX should look up h/w protocol type based on linktype */
5511478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		v = pcap_nametoeproto(name);
5512478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (v == PROTO_UNDEF) {
5513478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			v = pcap_nametollc(name);
5514478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (v == PROTO_UNDEF)
5515478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				bpf_error("unknown ether proto '%s'", name);
5516478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
5517478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5518478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5519478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISO:
5520478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (strcmp(name, "esis") == 0)
5521478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			v = ISO9542_ESIS;
5522478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else if (strcmp(name, "isis") == 0)
5523478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			v = ISO10589_ISIS;
5524478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else if (strcmp(name, "clnp") == 0)
5525478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			v = ISO8473_CLNP;
5526478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else
5527478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("unknown osi proto '%s'", name);
5528478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5529478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5530478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
5531478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		v = PROTO_UNDEF;
5532478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5533478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5534478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return v;
5535478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5536478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5537478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#if 0
5538478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct stmt *
5539478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_joinsp(s, n)
5540478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct stmt **s;
5541478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int n;
5542478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5543478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return NULL;
5544478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5545478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
5546478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5547478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
5548478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_protochain(v, proto, dir)
5549478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int v;
5550478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int proto;
5551478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir;
5552478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5553478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef NO_PROTOCHAIN
5554478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return gen_proto(v, proto, dir);
5555478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
5556478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b;
5557478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s[100];
5558478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int fix2, fix3, fix4, fix5;
5559478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int ahcheck, again, end;
5560478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int i, max;
5561478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int reg2 = alloc_reg();
5562478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5563478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	memset(s, 0, sizeof(s));
5564478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	fix2 = fix3 = fix4 = fix5 = 0;
5565478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5566478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (proto) {
5567478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IP:
5568478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IPV6:
5569478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5570478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
5571478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_protochain(v, Q_IP, dir);
5572478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b = gen_protochain(v, Q_IPV6, dir);
5573478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b);
5574478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b;
5575478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
5576478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("bad protocol applied for 'protochain'");
5577478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*NOTREACHED*/
5578478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5579478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5580478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
5581511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We don't handle variable-length prefixes before the link-layer
5582511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * header, or variable-length link-layer headers, here yet.
5583478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * We might want to add BPF instructions to do the protochain
5584478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * work, to simplify that and, on platforms that have a BPF
5585478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * interpreter with the new instructions, let the filtering
5586478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * be done in the kernel.  (We already require a modified BPF
5587478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * engine to do the protochain stuff, to support backward
5588478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * branches, and backward branch support is unlikely to appear
5589478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * in kernel BPF engines.)
5590478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
5591d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	if (off_linkpl.is_variable)
5592d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		bpf_error("'protochain' not supported with variable length headers");
5593478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5594478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	no_optimize = 1; /*this code is not compatible with optimzer yet */
5595478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5596478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
5597478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * s[0] is a dummy entry to protect other BPF insn from damage
5598478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * by s[fix] = foo with uninitialized variable "fix".  It is somewhat
5599478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * hard to find interdependency made by jump table fixup.
5600478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
5601478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i = 0;
5602478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i] = new_stmt(0);	/*dummy*/
5603478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5604478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5605478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (proto) {
5606478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IP:
5607478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_linktype(ETHERTYPE_IP);
5608478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5609478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* A = ip->ip_p */
5610478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
5611d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s[i]->s.k = off_linkpl.constant_part + off_nl + 9;
5612478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5613478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* X = ip->ip_hl << 2 */
5614478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
5615d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s[i]->s.k = off_linkpl.constant_part + off_nl;
5616478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5617478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5618511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5619478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IPV6:
5620478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_linktype(ETHERTYPE_IPV6);
5621478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5622478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* A = ip6->ip_nxt */
5623478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
5624d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s[i]->s.k = off_linkpl.constant_part + off_nl + 6;
5625478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5626478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* X = sizeof(struct ip6_hdr) */
5627478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i] = new_stmt(BPF_LDX|BPF_IMM);
5628478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.k = 40;
5629478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5630478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
5631511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5632478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
5633478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("unsupported proto to gen_protochain");
5634478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*NOTREACHED*/
5635478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5636478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5637478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* again: if (A == v) goto end; else fall through; */
5638478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	again = i;
5639478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
5640478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i]->s.k = v;
5641478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i]->s.jt = NULL;		/*later*/
5642478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i]->s.jf = NULL;		/*update in next stmt*/
5643478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	fix5 = i;
5644478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5645478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5646478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef IPPROTO_NONE
5647478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define IPPROTO_NONE	59
5648478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
5649478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* if (A == IPPROTO_NONE) goto end */
5650478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
5651478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i]->s.jt = NULL;	/*later*/
5652478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i]->s.jf = NULL;	/*update in next stmt*/
5653478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i]->s.k = IPPROTO_NONE;
5654478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[fix5]->s.jf = s[i];
5655478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	fix2 = i;
5656478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5657478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5658478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (proto == Q_IPV6) {
5659478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		int v6start, v6end, v6advance, j;
5660478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5661478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		v6start = i;
5662478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* if (A == IPPROTO_HOPOPTS) goto v6advance */
5663478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
5664478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.jt = NULL;	/*later*/
5665478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.jf = NULL;	/*update in next stmt*/
5666478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.k = IPPROTO_HOPOPTS;
5667478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[fix2]->s.jf = s[i];
5668478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5669478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* if (A == IPPROTO_DSTOPTS) goto v6advance */
5670478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
5671478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.jt = NULL;	/*later*/
5672478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.jf = NULL;	/*update in next stmt*/
5673478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.k = IPPROTO_DSTOPTS;
5674478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5675478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* if (A == IPPROTO_ROUTING) goto v6advance */
5676478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
5677478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.jt = NULL;	/*later*/
5678478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.jf = NULL;	/*update in next stmt*/
5679478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.k = IPPROTO_ROUTING;
5680478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5681478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* if (A == IPPROTO_FRAGMENT) goto v6advance; else goto ahcheck; */
5682478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
5683478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.jt = NULL;	/*later*/
5684478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.jf = NULL;	/*later*/
5685478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.k = IPPROTO_FRAGMENT;
5686478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		fix3 = i;
5687478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		v6end = i;
5688478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5689478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5690478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* v6advance: */
5691478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		v6advance = i;
5692478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5693478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
5694478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * in short,
5695511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * A = P[X + packet head];
5696511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * X = X + (P[X + packet head + 1] + 1) * 8;
5697478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
5698478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* A = P[X + packet head] */
5699478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
5700d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s[i]->s.k = off_linkpl.constant_part + off_nl;
5701478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5702478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* MEM[reg2] = A */
5703478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i] = new_stmt(BPF_ST);
5704478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.k = reg2;
5705478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5706511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* A = P[X + packet head + 1]; */
5707478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
5708d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s[i]->s.k = off_linkpl.constant_part + off_nl + 1;
5709478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5710478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* A += 1 */
5711478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
5712478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.k = 1;
5713478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5714478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* A *= 8 */
5715478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
5716478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.k = 8;
5717478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5718511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* A += X */
5719511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_X);
5720511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		s[i]->s.k = 0;
5721511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		i++;
5722478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* X = A; */
5723478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i] = new_stmt(BPF_MISC|BPF_TAX);
5724478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5725478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* A = MEM[reg2] */
5726478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i] = new_stmt(BPF_LD|BPF_MEM);
5727478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.k = reg2;
5728478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5729478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5730478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* goto again; (must use BPF_JA for backward jump) */
5731478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i] = new_stmt(BPF_JMP|BPF_JA);
5732478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.k = again - i - 1;
5733478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i - 1]->s.jf = s[i];
5734478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5735478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5736478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* fixup */
5737478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		for (j = v6start; j <= v6end; j++)
5738478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			s[j]->s.jt = s[v6advance];
5739511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else {
5740478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* nop */
5741478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
5742478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->s.k = 0;
5743478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[fix2]->s.jf = s[i];
5744478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		i++;
5745478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5746478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5747478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* ahcheck: */
5748478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	ahcheck = i;
5749478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* if (A == IPPROTO_AH) then fall through; else goto end; */
5750478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
5751478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i]->s.jt = NULL;	/*later*/
5752478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i]->s.jf = NULL;	/*later*/
5753478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i]->s.k = IPPROTO_AH;
5754478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (fix3)
5755478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[fix3]->s.jf = s[ahcheck];
5756478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	fix4 = i;
5757478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5758478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5759478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
5760478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * in short,
5761478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * A = P[X];
5762478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * X = X + (P[X + 1] + 2) * 4;
5763478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
5764478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* A = X */
5765478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA);
5766478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5767478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* A = P[X + packet head]; */
5768478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
5769d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s[i]->s.k = off_linkpl.constant_part + off_nl;
5770478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5771478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* MEM[reg2] = A */
5772478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i] = new_stmt(BPF_ST);
5773478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i]->s.k = reg2;
5774478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5775478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* A = X */
5776478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA);
5777478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5778478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* A += 1 */
5779478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
5780478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i]->s.k = 1;
5781478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5782478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* X = A */
5783478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i] = new_stmt(BPF_MISC|BPF_TAX);
5784478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5785478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* A = P[X + packet head] */
5786478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
5787d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s[i]->s.k = off_linkpl.constant_part + off_nl;
5788478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5789478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* A += 2 */
5790478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
5791478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i]->s.k = 2;
5792478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5793478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* A *= 4 */
5794478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
5795478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i]->s.k = 4;
5796478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5797478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* X = A; */
5798478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i] = new_stmt(BPF_MISC|BPF_TAX);
5799478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5800478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* A = MEM[reg2] */
5801478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i] = new_stmt(BPF_LD|BPF_MEM);
5802478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i]->s.k = reg2;
5803478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5804478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5805478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* goto again; (must use BPF_JA for backward jump) */
5806478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i] = new_stmt(BPF_JMP|BPF_JA);
5807478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i]->s.k = again - i - 1;
5808478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5809478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5810478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* end: nop */
5811478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	end = i;
5812478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
5813478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[i]->s.k = 0;
5814478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[fix2]->s.jt = s[end];
5815478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[fix4]->s.jf = s[end];
5816478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[fix5]->s.jt = s[end];
5817478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	i++;
5818478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5819478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
5820478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * make slist chain
5821478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
5822478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	max = i;
5823478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	for (i = 0; i < max - 1; i++)
5824478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s[i]->next = s[i + 1];
5825478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s[max - 1]->next = NULL;
5826478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5827478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
5828478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * emit final check
5829478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
5830478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b = new_block(JMP(BPF_JEQ));
5831478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b->stmts = s[1];	/*remember, s[0] is dummy*/
5832478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b->s.k = v;
5833478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5834478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	free_reg(reg2);
5835478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5836478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_and(b0, b);
5837478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b;
5838478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
5839478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5840478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5841511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic struct block *
5842511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallgen_check_802_11_data_frame()
5843511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
5844511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct slist *s;
5845511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct block *b0, *b1;
5846511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5847511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5848511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * A data frame has the 0x08 bit (b3) in the frame control field set
5849511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * and the 0x04 bit (b2) clear.
5850511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5851d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s = gen_load_a(OR_LINKHDR, 0, BPF_B);
5852511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	b0 = new_block(JMP(BPF_JSET));
5853511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	b0->s.k = 0x08;
5854511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	b0->stmts = s;
5855d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
5856d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s = gen_load_a(OR_LINKHDR, 0, BPF_B);
5857511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	b1 = new_block(JMP(BPF_JSET));
5858511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	b1->s.k = 0x04;
5859511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	b1->stmts = s;
5860511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	gen_not(b1);
5861511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5862511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	gen_and(b1, b0);
5863511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5864511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return b0;
5865511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
5866478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5867478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
5868478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Generate code that checks whether the packet is a packet for protocol
5869478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * <proto> and whether the type field in that protocol's header has
5870478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * the value <v>, e.g. if <proto> is Q_IP, it checks whether it's an
5871478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * IP packet and checks the protocol number in the IP header against <v>.
5872478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
5873478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * If <proto> is Q_DEFAULT, i.e. just "proto" was specified, it checks
5874478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * against Q_IP and Q_IPV6.
5875478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
5876478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
5877478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_proto(v, proto, dir)
5878478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int v;
5879478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int proto;
5880478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir;
5881478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5882478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1;
5883511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef CHASE_CHAIN
5884511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct block *b2;
5885511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
5886478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5887478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (dir != Q_DEFAULT)
5888478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("direction applied to 'proto'");
5889478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5890478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (proto) {
5891478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
5892478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(v, Q_IP, dir);
5893478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_proto(v, Q_IPV6, dir);
5894478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
5895478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
5896511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5897478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IP:
5898478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
5899478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * For FDDI, RFC 1188 says that SNAP encapsulation is used,
5900478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * not LLC encapsulation with LLCSAP_IP.
5901478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
5902478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * For IEEE 802 networks - which includes 802.5 token ring
5903478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042
5904478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * says that SNAP encapsulation is used, not LLC encapsulation
5905478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * with LLCSAP_IP.
5906478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
5907478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and
5908478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * RFC 2225 say that SNAP encapsulation is used, not LLC
5909478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * encapsulation with LLCSAP_IP.
5910478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
5911478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * So we always check for ETHERTYPE_IP.
5912478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
5913478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_linktype(ETHERTYPE_IP);
5914478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef CHASE_CHAIN
5915d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_cmp(OR_LINKPL, 9, BPF_B, (bpf_int32)v);
5916478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
5917478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_protochain(v, Q_IP);
5918478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
5919478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
5920478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
5921478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5922478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISO:
5923478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		switch (linktype) {
5924478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5925478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case DLT_FRELAY:
5926478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
5927478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * Frame Relay packets typically have an OSI
5928478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * NLPID at the beginning; "gen_linktype(LLCSAP_ISONS)"
5929478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * generates code to check for all the OSI
5930478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * NLPIDs, so calling it and then adding a check
5931478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * for the particular NLPID for which we're
5932478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * looking is bogus, as we can just check for
5933478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * the NLPID.
5934478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 *
5935478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * What we check for is the NLPID and a frame
5936478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * control field value of UI, i.e. 0x03 followed
5937478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * by the NLPID.
5938478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 *
5939478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * XXX - assumes a 2-byte Frame Relay header with
5940478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * DLCI and flags.  What if the address is longer?
5941478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 *
5942478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * XXX - what about SNAP-encapsulated frames?
5943478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
5944d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | v);
5945478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*NOTREACHED*/
5946478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			break;
5947478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5948478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case DLT_C_HDLC:
5949478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
5950478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * Cisco uses an Ethertype lookalike - for OSI,
5951478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * it's 0xfefe.
5952478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
5953478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			b0 = gen_linktype(LLCSAP_ISONS<<8 | LLCSAP_ISONS);
5954478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/* OSI in C-HDLC is stuffed with a fudge byte */
5955d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b1 = gen_cmp(OR_LINKPL_NOSNAP, 1, BPF_B, (long)v);
5956478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_and(b0, b1);
5957478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return b1;
5958478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5959478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		default:
5960478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			b0 = gen_linktype(LLCSAP_ISONS);
5961d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b1 = gen_cmp(OR_LINKPL_NOSNAP, 0, BPF_B, (long)v);
5962478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_and(b0, b1);
5963478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return b1;
5964478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
5965478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5966478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ISIS:
5967478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
5968478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
5969478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * 4 is the offset of the PDU type relative to the IS-IS
5970478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * header.
5971478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
5972d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_cmp(OR_LINKPL_NOSNAP, 4, BPF_B, (long)v);
5973478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
5974478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
5975478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5976478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ARP:
5977478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("arp does not encapsulate another protocol");
5978478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
5979478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5980478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_RARP:
5981478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("rarp does not encapsulate another protocol");
5982478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
5983478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5984478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ATALK:
5985478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("atalk encapsulation is not specifiable");
5986478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
5987478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5988478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DECNET:
5989478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("decnet encapsulation is not specifiable");
5990478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
5991478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5992478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SCA:
5993478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("sca does not encapsulate another protocol");
5994478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
5995478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5996478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_LAT:
5997478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("lat does not encapsulate another protocol");
5998478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
5999478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6000478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_MOPRC:
6001478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("moprc does not encapsulate another protocol");
6002478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6003478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6004478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_MOPDL:
6005478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("mopdl does not encapsulate another protocol");
6006478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6007478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6008478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_LINK:
6009478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return gen_linktype(v);
6010478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6011478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_UDP:
6012478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'udp proto' is bogus");
6013478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6014478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6015478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_TCP:
6016478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'tcp proto' is bogus");
6017478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6018478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6019478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SCTP:
6020478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'sctp proto' is bogus");
6021478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6022478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6023478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ICMP:
6024478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'icmp proto' is bogus");
6025478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6026478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6027478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IGMP:
6028478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'igmp proto' is bogus");
6029478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6030478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6031478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IGRP:
6032478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'igrp proto' is bogus");
6033478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6034478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6035478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_PIM:
6036478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'pim proto' is bogus");
6037478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6038478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6039478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_VRRP:
6040478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'vrrp proto' is bogus");
6041478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6042478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6043511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_CARP:
6044511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'carp proto' is bogus");
6045511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* NOTREACHED */
6046511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
6047478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IPV6:
6048478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_linktype(ETHERTYPE_IPV6);
6049478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef CHASE_CHAIN
6050511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
6051511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Also check for a fragment header before the final
6052511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * header.
6053511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
6054d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b2 = gen_cmp(OR_LINKPL, 6, BPF_B, IPPROTO_FRAGMENT);
6055d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_cmp(OR_LINKPL, 40, BPF_B, (bpf_int32)v);
6056511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_and(b2, b1);
6057d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b2 = gen_cmp(OR_LINKPL, 6, BPF_B, (bpf_int32)v);
6058511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_or(b2, b1);
6059478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
6060478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_protochain(v, Q_IPV6);
6061478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
6062478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
6063478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
6064478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6065478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ICMPV6:
6066478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'icmp6 proto' is bogus");
6067478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6068478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AH:
6069478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'ah proto' is bogus");
6070478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6071478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ESP:
6072478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'ah proto' is bogus");
6073478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6074478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_STP:
6075478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'stp proto' is bogus");
6076478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6077478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IPX:
6078478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'ipx proto' is bogus");
6079478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6080478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_NETBEUI:
6081478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'netbeui proto' is bogus");
6082478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6083478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_RADIO:
6084478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'radio proto' is bogus");
6085478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6086478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
6087478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
6088478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6089478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
6090478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
6091478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
6092478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6093478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
6094478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_scode(name, q)
6095478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register const char *name;
6096478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct qual q;
6097478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
6098478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int proto = q.proto;
6099478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir = q.dir;
6100478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int tproto;
6101478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_char *eaddr;
6102478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 mask, addr;
6103478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef INET6
6104478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 **alist;
6105478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
6106478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int tproto6;
6107478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct sockaddr_in *sin4;
6108478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct sockaddr_in6 *sin6;
6109478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct addrinfo *res, *res0;
6110478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct in6_addr mask128;
6111478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif /*INET6*/
6112478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b, *tmp;
6113478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int port, real_proto;
6114478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int port1, port2;
6115478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6116478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (q.addr) {
6117478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6118478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_NET:
6119478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		addr = pcap_nametonetaddr(name);
6120478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (addr == 0)
6121478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("unknown network '%s'", name);
6122478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* Left justify network addr and calculate its network mask */
6123478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		mask = 0xffffffff;
6124478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		while (addr && (addr & 0xff000000) == 0) {
6125478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			addr <<= 8;
6126478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			mask <<= 8;
6127478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
6128478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return gen_host(addr, mask, proto, dir, q.addr);
6129478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6130478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
6131478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_HOST:
6132478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto == Q_LINK) {
6133478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			switch (linktype) {
6134478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6135478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			case DLT_EN10MB:
6136511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			case DLT_NETANALYZER:
6137511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			case DLT_NETANALYZER_TRANSPARENT:
6138478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				eaddr = pcap_ether_hostton(name);
6139478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (eaddr == NULL)
6140478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					bpf_error(
6141478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					    "unknown ether host '%s'", name);
6142d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes				tmp = gen_prevlinkhdr_check();
6143478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				b = gen_ehostop(eaddr, dir);
6144d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes				if (tmp != NULL)
6145d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes					gen_and(tmp, b);
6146478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				free(eaddr);
6147478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				return b;
6148478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6149478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			case DLT_FDDI:
6150478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				eaddr = pcap_ether_hostton(name);
6151478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (eaddr == NULL)
6152478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					bpf_error(
6153478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					    "unknown FDDI host '%s'", name);
6154478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				b = gen_fhostop(eaddr, dir);
6155478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				free(eaddr);
6156478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				return b;
6157478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6158478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			case DLT_IEEE802:
6159478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				eaddr = pcap_ether_hostton(name);
6160478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (eaddr == NULL)
6161478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					bpf_error(
6162478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					    "unknown token ring host '%s'", name);
6163478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				b = gen_thostop(eaddr, dir);
6164478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				free(eaddr);
6165478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				return b;
6166478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6167478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			case DLT_IEEE802_11:
6168511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			case DLT_PRISM_HEADER:
6169478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			case DLT_IEEE802_11_RADIO_AVS:
6170478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			case DLT_IEEE802_11_RADIO:
6171478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			case DLT_PPI:
6172478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				eaddr = pcap_ether_hostton(name);
6173478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (eaddr == NULL)
6174478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					bpf_error(
6175478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					    "unknown 802.11 host '%s'", name);
6176478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				b = gen_wlanhostop(eaddr, dir);
6177478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				free(eaddr);
6178478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				return b;
6179478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6180478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			case DLT_IP_OVER_FC:
6181478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				eaddr = pcap_ether_hostton(name);
6182478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (eaddr == NULL)
6183478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					bpf_error(
6184478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					    "unknown Fibre Channel host '%s'", name);
6185478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				b = gen_ipfchostop(eaddr, dir);
6186478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				free(eaddr);
6187478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				return b;
6188478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
6189478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6190478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("only ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel supports link-level host name");
6191478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		} else if (proto == Q_DECNET) {
6192478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			unsigned short dn_addr = __pcap_nametodnaddr(name);
6193478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
6194478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * I don't think DECNET hosts can be multihomed, so
6195478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * there is no need to build up a list of addresses
6196478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
6197478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return (gen_host(dn_addr, 0, proto, dir, q.addr));
6198478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		} else {
6199478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef INET6
6200478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			alist = pcap_nametoaddr(name);
6201478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (alist == NULL || *alist == NULL)
6202478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				bpf_error("unknown host '%s'", name);
6203478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			tproto = proto;
6204d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			if (off_linktype.constant_part == (u_int)-1 &&
6205d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			    tproto == Q_DEFAULT)
6206478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				tproto = Q_IP;
6207478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			b = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr);
6208478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			while (*alist) {
6209478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				tmp = gen_host(**alist++, 0xffffffff,
6210478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					       tproto, dir, q.addr);
6211478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				gen_or(b, tmp);
6212478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				b = tmp;
6213478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
6214478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return b;
6215478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
6216478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			memset(&mask128, 0xff, sizeof(mask128));
6217478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			res0 = res = pcap_nametoaddrinfo(name);
6218478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (res == NULL)
6219478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				bpf_error("unknown host '%s'", name);
6220511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ai = res;
6221478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			b = tmp = NULL;
6222478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			tproto = tproto6 = proto;
6223d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			if (off_linktype.constant_part == -1 &&
6224d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			    tproto == Q_DEFAULT) {
6225478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				tproto = Q_IP;
6226478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				tproto6 = Q_IPV6;
6227478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
6228478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			for (res = res0; res; res = res->ai_next) {
6229478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				switch (res->ai_family) {
6230478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				case AF_INET:
6231478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					if (tproto == Q_IPV6)
6232478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project						continue;
6233478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6234478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					sin4 = (struct sockaddr_in *)
6235478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project						res->ai_addr;
6236478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					tmp = gen_host(ntohl(sin4->sin_addr.s_addr),
6237478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project						0xffffffff, tproto, dir, q.addr);
6238478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					break;
6239478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				case AF_INET6:
6240478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					if (tproto6 == Q_IP)
6241478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project						continue;
6242478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6243478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					sin6 = (struct sockaddr_in6 *)
6244478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project						res->ai_addr;
6245478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					tmp = gen_host6(&sin6->sin6_addr,
6246478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project						&mask128, tproto6, dir, q.addr);
6247478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					break;
6248478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				default:
6249478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					continue;
6250478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				}
6251478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				if (b)
6252478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					gen_or(b, tmp);
6253478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				b = tmp;
6254478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
6255511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ai = NULL;
6256478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			freeaddrinfo(res0);
6257478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (b == NULL) {
6258478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				bpf_error("unknown host '%s'%s", name,
6259478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				    (proto == Q_DEFAULT)
6260478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					? ""
6261478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					: " for specified address family");
6262478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
6263478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return b;
6264478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif /*INET6*/
6265478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
6266478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6267478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_PORT:
6268478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto != Q_DEFAULT &&
6269478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
6270478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("illegal qualifier of 'port'");
6271478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (pcap_nametoport(name, &port, &real_proto) == 0)
6272478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("unknown port '%s'", name);
6273478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto == Q_UDP) {
6274478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (real_proto == IPPROTO_TCP)
6275478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				bpf_error("port '%s' is tcp", name);
6276478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			else if (real_proto == IPPROTO_SCTP)
6277478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				bpf_error("port '%s' is sctp", name);
6278478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			else
6279478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				/* override PROTO_UNDEF */
6280478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				real_proto = IPPROTO_UDP;
6281478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
6282478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto == Q_TCP) {
6283478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (real_proto == IPPROTO_UDP)
6284478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				bpf_error("port '%s' is udp", name);
6285478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6286478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			else if (real_proto == IPPROTO_SCTP)
6287478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				bpf_error("port '%s' is sctp", name);
6288478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			else
6289478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				/* override PROTO_UNDEF */
6290478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				real_proto = IPPROTO_TCP;
6291478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
6292478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto == Q_SCTP) {
6293478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (real_proto == IPPROTO_UDP)
6294478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				bpf_error("port '%s' is udp", name);
6295478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6296478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			else if (real_proto == IPPROTO_TCP)
6297478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				bpf_error("port '%s' is tcp", name);
6298478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			else
6299478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				/* override PROTO_UNDEF */
6300478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				real_proto = IPPROTO_SCTP;
6301478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
6302511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (port < 0)
6303511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error("illegal port number %d < 0", port);
6304511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (port > 65535)
6305511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error("illegal port number %d > 65535", port);
6306478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b = gen_port(port, real_proto, dir);
6307478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(gen_port6(port, real_proto, dir), b);
6308478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b;
6309478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6310478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_PORTRANGE:
6311478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto != Q_DEFAULT &&
6312478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
6313478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("illegal qualifier of 'portrange'");
6314d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0)
6315478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("unknown port in range '%s'", name);
6316478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto == Q_UDP) {
6317478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (real_proto == IPPROTO_TCP)
6318478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				bpf_error("port in range '%s' is tcp", name);
6319478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			else if (real_proto == IPPROTO_SCTP)
6320478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				bpf_error("port in range '%s' is sctp", name);
6321478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			else
6322478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				/* override PROTO_UNDEF */
6323478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				real_proto = IPPROTO_UDP;
6324478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
6325478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto == Q_TCP) {
6326478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (real_proto == IPPROTO_UDP)
6327478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				bpf_error("port in range '%s' is udp", name);
6328478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			else if (real_proto == IPPROTO_SCTP)
6329478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				bpf_error("port in range '%s' is sctp", name);
6330478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			else
6331478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				/* override PROTO_UNDEF */
6332478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				real_proto = IPPROTO_TCP;
6333478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
6334478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto == Q_SCTP) {
6335478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (real_proto == IPPROTO_UDP)
6336478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				bpf_error("port in range '%s' is udp", name);
6337478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			else if (real_proto == IPPROTO_TCP)
6338478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				bpf_error("port in range '%s' is tcp", name);
6339478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			else
6340478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				/* override PROTO_UNDEF */
6341d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes				real_proto = IPPROTO_SCTP;
6342478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
6343511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (port1 < 0)
6344511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error("illegal port number %d < 0", port1);
6345511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (port1 > 65535)
6346511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error("illegal port number %d > 65535", port1);
6347511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (port2 < 0)
6348511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error("illegal port number %d < 0", port2);
6349511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (port2 > 65535)
6350511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error("illegal port number %d > 65535", port2);
6351511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
6352478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b = gen_portrange(port1, port2, real_proto, dir);
6353478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(gen_portrange6(port1, port2, real_proto, dir), b);
6354478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b;
6355478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6356478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_GATEWAY:
6357478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef INET6
6358478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		eaddr = pcap_ether_hostton(name);
6359478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (eaddr == NULL)
6360478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("unknown ether host: %s", name);
6361478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6362478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		alist = pcap_nametoaddr(name);
6363478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (alist == NULL || *alist == NULL)
6364478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("unknown host '%s'", name);
6365478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b = gen_gateway(eaddr, alist, proto, dir);
6366478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		free(eaddr);
6367478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b;
6368478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else
6369478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'gateway' not supported in this configuration");
6370478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif /*INET6*/
6371478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6372478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_PROTO:
6373478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		real_proto = lookup_proto(name, proto);
6374478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (real_proto >= 0)
6375478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return gen_proto(real_proto, proto, dir);
6376478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else
6377478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("unknown protocol: %s", name);
6378478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6379478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_PROTOCHAIN:
6380478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		real_proto = lookup_proto(name, proto);
6381478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (real_proto >= 0)
6382478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return gen_protochain(real_proto, proto, dir);
6383478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else
6384478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("unknown protocol: %s", name);
6385478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6386478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_UNDEF:
6387478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		syntax();
6388478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6389478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
6390478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	abort();
6391478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
6392478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
6393478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6394478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
6395478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_mcode(s1, s2, masklen, q)
6396478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register const char *s1, *s2;
6397d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	register unsigned int masklen;
6398478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct qual q;
6399478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
6400478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int nlen, mlen;
6401478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 n, m;
6402478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6403478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	nlen = __pcap_atoin(s1, &n);
6404478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* Promote short ipaddr */
6405478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	n <<= 32 - nlen;
6406478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6407478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (s2 != NULL) {
6408478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		mlen = __pcap_atoin(s2, &m);
6409478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* Promote short ipaddr */
6410478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		m <<= 32 - mlen;
6411478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if ((n & ~m) != 0)
6412478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("non-network bits set in \"%s mask %s\"",
6413478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			    s1, s2);
6414478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	} else {
6415478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* Convert mask len to mask */
6416478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (masklen > 32)
6417478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("mask length must be <= 32");
6418478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (masklen == 0) {
6419478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
6420478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * X << 32 is not guaranteed by C to be 0; it's
6421478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * undefined.
6422478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
6423478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			m = 0;
6424478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		} else
6425478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			m = 0xffffffff << (32 - masklen);
6426478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if ((n & ~m) != 0)
6427478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("non-network bits set in \"%s/%d\"",
6428478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			    s1, masklen);
6429478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
6430478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6431478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (q.addr) {
6432478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6433478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_NET:
6434478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return gen_host(n, m, q.proto, q.dir, q.addr);
6435478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6436478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
6437478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("Mask syntax for networks only");
6438478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6439478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
6440478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
6441478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return NULL;
6442478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
6443478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6444478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
6445478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_ncode(s, v, q)
6446478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register const char *s;
6447478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 v;
6448478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct qual q;
6449478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
6450478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 mask;
6451478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int proto = q.proto;
6452478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir = q.dir;
6453478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int vlen;
6454478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6455478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (s == NULL)
6456478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		vlen = 32;
6457478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	else if (q.proto == Q_DECNET)
6458478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		vlen = __pcap_atodn(s, &v);
6459478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	else
6460478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		vlen = __pcap_atoin(s, &v);
6461478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6462478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (q.addr) {
6463478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6464478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
6465478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_HOST:
6466478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_NET:
6467478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto == Q_DECNET)
6468478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return gen_host(v, 0, proto, dir, q.addr);
6469478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else if (proto == Q_LINK) {
6470478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("illegal link layer address");
6471478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		} else {
6472478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			mask = 0xffffffff;
6473478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (s == NULL && q.addr == Q_NET) {
6474478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				/* Promote short net number */
6475478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				while (v && (v & 0xff000000) == 0) {
6476478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					v <<= 8;
6477478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					mask <<= 8;
6478478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				}
6479478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			} else {
6480478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				/* Promote short ipaddr */
6481478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				v <<= 32 - vlen;
6482478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				mask <<= 32 - vlen;
6483478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
6484478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return gen_host(v, mask, proto, dir, q.addr);
6485478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
6486478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6487478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_PORT:
6488478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto == Q_UDP)
6489478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			proto = IPPROTO_UDP;
6490478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else if (proto == Q_TCP)
6491478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			proto = IPPROTO_TCP;
6492478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else if (proto == Q_SCTP)
6493478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			proto = IPPROTO_SCTP;
6494478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else if (proto == Q_DEFAULT)
6495478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			proto = PROTO_UNDEF;
6496478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else
6497478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("illegal qualifier of 'port'");
6498478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6499511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (v > 65535)
6500511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error("illegal port number %u > 65535", v);
6501511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
6502478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	    {
6503478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		struct block *b;
6504478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b = gen_port((int)v, proto, dir);
6505478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(gen_port6((int)v, proto, dir), b);
6506478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b;
6507478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	    }
6508478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6509478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_PORTRANGE:
6510478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (proto == Q_UDP)
6511478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			proto = IPPROTO_UDP;
6512478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else if (proto == Q_TCP)
6513478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			proto = IPPROTO_TCP;
6514478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else if (proto == Q_SCTP)
6515478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			proto = IPPROTO_SCTP;
6516478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else if (proto == Q_DEFAULT)
6517478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			proto = PROTO_UNDEF;
6518478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else
6519478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("illegal qualifier of 'portrange'");
6520478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6521511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (v > 65535)
6522511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error("illegal port number %u > 65535", v);
6523511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
6524478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	    {
6525478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		struct block *b;
6526478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b = gen_portrange((int)v, (int)v, proto, dir);
6527478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(gen_portrange6((int)v, (int)v, proto, dir), b);
6528478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b;
6529478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	    }
6530478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6531478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_GATEWAY:
6532478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("'gateway' requires a name");
6533478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6534478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6535478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_PROTO:
6536478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return gen_proto((int)v, proto, dir);
6537478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6538478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_PROTOCHAIN:
6539478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return gen_protochain((int)v, proto, dir);
6540478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6541478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_UNDEF:
6542478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		syntax();
6543478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6544478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6545478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
6546478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
6547478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6548478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
6549478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
6550478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
6551478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6552478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef INET6
6553478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
6554478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_mcode6(s1, s2, masklen, q)
6555478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register const char *s1, *s2;
6556d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	register unsigned int masklen;
6557478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct qual q;
6558478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
6559478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct addrinfo *res;
6560478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct in6_addr *addr;
6561478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct in6_addr mask;
6562478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b;
6563478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int32_t *a, *m;
6564478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6565478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (s2)
6566478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("no mask %s supported", s2);
6567478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6568478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	res = pcap_nametoaddrinfo(s1);
6569478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (!res)
6570478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("invalid ip6 address %s", s1);
6571511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ai = res;
6572478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (res->ai_next)
6573478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("%s resolved to multiple address", s1);
6574478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
6575478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6576478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (sizeof(mask) * 8 < masklen)
6577478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("mask length must be <= %u", (unsigned int)(sizeof(mask) * 8));
6578478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	memset(&mask, 0, sizeof(mask));
6579478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	memset(&mask, 0xff, masklen / 8);
6580478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (masklen % 8) {
6581478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		mask.s6_addr[masklen / 8] =
6582478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			(0xff << (8 - masklen % 8)) & 0xff;
6583478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
6584478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6585478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	a = (u_int32_t *)addr;
6586478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	m = (u_int32_t *)&mask;
6587478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if ((a[0] & ~m[0]) || (a[1] & ~m[1])
6588478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 || (a[2] & ~m[2]) || (a[3] & ~m[3])) {
6589478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("non-network bits set in \"%s/%d\"", s1, masklen);
6590478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
6591478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6592478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (q.addr) {
6593478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6594478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
6595478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_HOST:
6596478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (masklen != 128)
6597478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("Mask syntax for networks only");
6598478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* FALLTHROUGH */
6599478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6600478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_NET:
6601478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b = gen_host6(addr, &mask, q.proto, q.dir, q.addr);
6602511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ai = NULL;
6603478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		freeaddrinfo(res);
6604478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b;
6605478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6606478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
6607478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("invalid qualifier against IPv6 address");
6608478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
6609478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
6610478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return NULL;
6611478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
6612478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif /*INET6*/
6613478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6614478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
6615478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_ecode(eaddr, q)
6616478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register const u_char *eaddr;
6617478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct qual q;
6618478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
6619478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b, *tmp;
6620478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6621478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
6622511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		switch (linktype) {
6623511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_EN10MB:
6624511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_NETANALYZER:
6625511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_NETANALYZER_TRANSPARENT:
6626d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			tmp = gen_prevlinkhdr_check();
6627d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b = gen_ehostop(eaddr, (int)q.dir);
6628d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			if (tmp != NULL)
6629d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes				gen_and(tmp, b);
6630d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return b;
6631511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_FDDI:
6632511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return gen_fhostop(eaddr, (int)q.dir);
6633511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_IEEE802:
6634511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return gen_thostop(eaddr, (int)q.dir);
6635511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_IEEE802_11:
6636511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_PRISM_HEADER:
6637511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_IEEE802_11_RADIO_AVS:
6638511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_IEEE802_11_RADIO:
6639511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_PPI:
6640511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return gen_wlanhostop(eaddr, (int)q.dir);
6641511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_IP_OVER_FC:
6642511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return gen_ipfchostop(eaddr, (int)q.dir);
6643511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		default:
6644511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
6645511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
6646511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
6647478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
6648478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_error("ethernet address used in non-ether expression");
6649478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
6650478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return NULL;
6651478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
6652478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6653478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectvoid
6654478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectsappend(s0, s1)
6655478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s0, *s1;
6656478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
6657478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
6658478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * This is definitely not the best way to do this, but the
6659478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * lists will rarely get long.
6660478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
6661478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	while (s0->next)
6662478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s0 = s0->next;
6663478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s0->next = s1;
6664478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
6665478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6666478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct slist *
6667478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectxfer_to_x(a)
6668478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct arth *a;
6669478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
6670478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s;
6671478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6672478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s = new_stmt(BPF_LDX|BPF_MEM);
6673478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s->s.k = a->regno;
6674478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return s;
6675478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
6676478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6677478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct slist *
6678478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectxfer_to_a(a)
6679478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct arth *a;
6680478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
6681478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s;
6682478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6683478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s = new_stmt(BPF_LD|BPF_MEM);
6684478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s->s.k = a->regno;
6685478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return s;
6686478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
6687478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6688478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
6689478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Modify "index" to use the value stored into its register as an
6690478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * offset relative to the beginning of the header for the protocol
6691478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * "proto", and allocate a register and put an item "size" bytes long
6692478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * (1, 2, or 4) at that offset into that register, making it the register
6693478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * for "index".
6694478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
6695478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct arth *
6696478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_load(proto, inst, size)
6697478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int proto;
6698478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct arth *inst;
6699478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int size;
6700478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
6701478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s, *tmp;
6702478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b;
6703478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int regno = alloc_reg();
6704478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6705478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	free_reg(inst->regno);
6706478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (size) {
6707478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6708478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
6709478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("data size must be 1, 2, or 4");
6710478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6711478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case 1:
6712478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		size = BPF_B;
6713478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
6714478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6715478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case 2:
6716478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		size = BPF_H;
6717478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
6718478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6719478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case 4:
6720478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		size = BPF_W;
6721478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
6722478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
6723478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (proto) {
6724478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
6725478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("unsupported index operation");
6726478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6727478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_RADIO:
6728478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6729478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * The offset is relative to the beginning of the packet
6730478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * data, if we have a radio header.  (If we don't, this
6731478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * is an error.)
6732478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6733478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (linktype != DLT_IEEE802_11_RADIO_AVS &&
6734478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    linktype != DLT_IEEE802_11_RADIO &&
6735478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    linktype != DLT_PRISM_HEADER)
6736478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("radio information not present in capture");
6737478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6738478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6739478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Load into the X register the offset computed into the
6740511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * register specified by "index".
6741478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6742478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s = xfer_to_x(inst);
6743478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6744478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6745478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Load the item at that offset.
6746478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6747478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = new_stmt(BPF_LD|BPF_IND|size);
6748478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s, tmp);
6749478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(inst->s, s);
6750478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
6751478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6752478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_LINK:
6753478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6754478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * The offset is relative to the beginning of
6755478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the link-layer header.
6756478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
6757478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - what about ATM LANE?  Should the index be
6758478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * relative to the beginning of the AAL5 frame, so
6759478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * that 0 refers to the beginning of the LE Control
6760478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * field, or relative to the beginning of the LAN
6761478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * frame, so that 0 refers, for Ethernet LANE, to
6762478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the beginning of the destination address?
6763478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6764d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_abs_offset_varpart(&off_linkhdr);
6765478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6766478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6767478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * If "s" is non-null, it has code to arrange that the
6768478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * X register contains the length of the prefix preceding
6769478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the link-layer header.  Add to it the offset computed
6770478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * into the register specified by "index", and move that
6771478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * into the X register.  Otherwise, just load into the X
6772511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * register the offset computed into the register specified
6773478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * by "index".
6774478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6775478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (s != NULL) {
6776478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			sappend(s, xfer_to_a(inst));
6777478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
6778478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			sappend(s, new_stmt(BPF_MISC|BPF_TAX));
6779478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		} else
6780478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			s = xfer_to_x(inst);
6781478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6782478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6783478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Load the item at the sum of the offset we've put in the
6784478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * X register and the offset of the start of the link
6785478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * layer header (which is 0 if the radio header is
6786478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * variable-length; that header length is what we put
6787478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * into the X register and then added to the index).
6788478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6789478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = new_stmt(BPF_LD|BPF_IND|size);
6790d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		tmp->s.k = off_linkhdr.constant_part;
6791478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s, tmp);
6792478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(inst->s, s);
6793478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
6794478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6795478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IP:
6796478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ARP:
6797478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_RARP:
6798478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ATALK:
6799478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DECNET:
6800478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SCA:
6801478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_LAT:
6802478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_MOPRC:
6803478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_MOPDL:
6804478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IPV6:
6805478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6806478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * The offset is relative to the beginning of
6807478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the network-layer header.
6808478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - are there any cases where we want
6809478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * off_nl_nosnap?
6810478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6811d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = gen_abs_offset_varpart(&off_linkpl);
6812478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6813478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6814478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * If "s" is non-null, it has code to arrange that the
6815d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * X register contains the variable part of the offset
6816d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * of the link-layer payload.  Add to it the offset
6817d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * computed into the register specified by "index",
6818d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * and move that into the X register.  Otherwise, just
6819d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * load into the X register the offset computed into
6820d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * the register specified by "index".
6821478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6822478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (s != NULL) {
6823478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			sappend(s, xfer_to_a(inst));
6824478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
6825478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			sappend(s, new_stmt(BPF_MISC|BPF_TAX));
6826478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		} else
6827478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			s = xfer_to_x(inst);
6828478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6829478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6830478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Load the item at the sum of the offset we've put in the
6831478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * X register, the offset of the start of the network
6832d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * layer header from the beginning of the link-layer
6833d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * payload, and the constant part of the offset of the
6834d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * start of the link-layer payload.
6835478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6836478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = new_stmt(BPF_LD|BPF_IND|size);
6837d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		tmp->s.k = off_linkpl.constant_part + off_nl;
6838478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s, tmp);
6839478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(inst->s, s);
6840478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6841478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6842478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Do the computation only if the packet contains
6843478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the protocol in question.
6844478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6845478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b = gen_proto_abbrev(proto);
6846478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (inst->b)
6847478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_and(inst->b, b);
6848478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		inst->b = b;
6849478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
6850478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6851478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SCTP:
6852478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_TCP:
6853478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_UDP:
6854478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ICMP:
6855478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IGMP:
6856478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IGRP:
6857478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_PIM:
6858478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_VRRP:
6859511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_CARP:
6860478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6861478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * The offset is relative to the beginning of
6862478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the transport-layer header.
6863478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
6864478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Load the X register with the length of the IPv4 header
6865478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * (plus the offset of the link-layer header, if it's
6866478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * a variable-length header), in bytes.
6867478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
6868478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - are there any cases where we want
6869478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * off_nl_nosnap?
6870478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - we should, if we're built with
6871478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * IPv6 support, generate code to load either
6872478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * IPv4, IPv6, or both, as appropriate.
6873478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6874478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s = gen_loadx_iphdrlen();
6875478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6876478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6877d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * The X register now contains the sum of the variable
6878d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * part of the offset of the link-layer payload and the
6879511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * length of the network-layer header.
6880511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
6881478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Load into the A register the offset relative to
6882478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the beginning of the transport layer header,
6883478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * add the X register to that, move that to the
6884478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * X register, and load with an offset from the
6885d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * X register equal to the sum of the constant part of
6886d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * the offset of the link-layer payload and the offset,
6887d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * relative to the beginning of the link-layer payload,
6888d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * of the network-layer header.
6889478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6890478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s, xfer_to_a(inst));
6891478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
6892478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s, new_stmt(BPF_MISC|BPF_TAX));
6893478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size));
6894d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		tmp->s.k = off_linkpl.constant_part + off_nl;
6895478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(inst->s, s);
6896478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6897478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6898478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Do the computation only if the packet contains
6899478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the protocol in question - which is true only
6900478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * if this is an IP datagram and is the first or
6901478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * only fragment of that datagram.
6902478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6903478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
6904478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (inst->b)
6905478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_and(inst->b, b);
6906478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(gen_proto_abbrev(Q_IP), b);
6907478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		inst->b = b;
6908478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
6909478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_ICMPV6:
6910478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("IPv6 upper-layer protocol is not supported by proto[x]");
6911478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*NOTREACHED*/
6912478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
6913478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	inst->regno = regno;
6914478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s = new_stmt(BPF_ST);
6915478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s->s.k = regno;
6916478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	sappend(inst->s, s);
6917478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6918478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return inst;
6919478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
6920478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6921478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
6922478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_relation(code, a0, a1, reversed)
6923478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int code;
6924478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct arth *a0, *a1;
6925478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int reversed;
6926478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
6927478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s0, *s1, *s2;
6928478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b, *tmp;
6929478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6930478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s0 = xfer_to_x(a1);
6931478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s1 = xfer_to_a(a0);
6932478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (code == BPF_JEQ) {
6933478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X);
6934478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b = new_block(JMP(code));
6935478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		sappend(s1, s2);
6936478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
6937478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	else
6938478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b = new_block(BPF_JMP|code|BPF_X);
6939478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (reversed)
6940478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_not(b);
6941478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6942478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	sappend(s0, s1);
6943478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	sappend(a1->s, s0);
6944478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	sappend(a0->s, a1->s);
6945478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6946478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b->stmts = a0->s;
6947478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6948478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	free_reg(a0->regno);
6949478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	free_reg(a1->regno);
6950478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6951478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* 'and' together protocol checks */
6952478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (a0->b) {
6953478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (a1->b) {
6954478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_and(a0->b, tmp = a1->b);
6955478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
6956478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else
6957478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			tmp = a0->b;
6958478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	} else
6959478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		tmp = a1->b;
6960478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6961478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (tmp)
6962478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(tmp, b);
6963478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6964478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b;
6965478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
6966478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6967478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct arth *
6968478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_loadlen()
6969478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
6970478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int regno = alloc_reg();
6971478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct arth *a = (struct arth *)newchunk(sizeof(*a));
6972478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s;
6973478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6974478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s = new_stmt(BPF_LD|BPF_LEN);
6975478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s->next = new_stmt(BPF_ST);
6976478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s->next->s.k = regno;
6977478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	a->s = s;
6978478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	a->regno = regno;
6979478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6980478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return a;
6981478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
6982478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6983478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct arth *
6984478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_loadi(val)
6985478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int val;
6986478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
6987478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct arth *a;
6988478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s;
6989478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int reg;
6990478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6991478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	a = (struct arth *)newchunk(sizeof(*a));
6992478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6993478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	reg = alloc_reg();
6994478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6995478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s = new_stmt(BPF_LD|BPF_IMM);
6996478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s->s.k = val;
6997478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s->next = new_stmt(BPF_ST);
6998478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s->next->s.k = reg;
6999478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	a->s = s;
7000478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	a->regno = reg;
7001478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7002478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return a;
7003478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7004478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7005478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct arth *
7006478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_neg(a)
7007478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct arth *a;
7008478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7009478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s;
7010478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7011478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s = xfer_to_a(a);
7012478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	sappend(a->s, s);
7013478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s = new_stmt(BPF_ALU|BPF_NEG);
7014478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s->s.k = 0;
7015478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	sappend(a->s, s);
7016478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s = new_stmt(BPF_ST);
7017478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s->s.k = a->regno;
7018478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	sappend(a->s, s);
7019478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7020478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return a;
7021478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7022478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7023478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct arth *
7024478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_arth(code, a0, a1)
7025478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int code;
7026478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct arth *a0, *a1;
7027478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7028478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s0, *s1, *s2;
7029478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7030478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s0 = xfer_to_x(a1);
7031478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s1 = xfer_to_a(a0);
7032478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s2 = new_stmt(BPF_ALU|BPF_X|code);
7033478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7034478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	sappend(s1, s2);
7035478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	sappend(s0, s1);
7036478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	sappend(a1->s, s0);
7037478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	sappend(a0->s, a1->s);
7038478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7039478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	free_reg(a0->regno);
7040478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	free_reg(a1->regno);
7041478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7042478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s0 = new_stmt(BPF_ST);
7043478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	a0->regno = s0->s.k = alloc_reg();
7044478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	sappend(a0->s, s0);
7045478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7046478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return a0;
7047478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7048478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7049478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
7050478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Here we handle simple allocation of the scratch registers.
7051478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * If too many registers are alloc'd, the allocator punts.
7052478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
7053478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int regused[BPF_MEMWORDS];
7054478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int curreg;
7055478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7056478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
7057511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Initialize the table of used registers and the current register.
7058511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
7059511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void
7060511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallinit_regs()
7061511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
7062511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	curreg = 0;
7063511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	memset(regused, 0, sizeof regused);
7064511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
7065511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7066511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
7067478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Return the next free register.
7068478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
7069478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
7070478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectalloc_reg()
7071478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7072478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int n = BPF_MEMWORDS;
7073478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7074478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	while (--n >= 0) {
7075478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (regused[curreg])
7076478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			curreg = (curreg + 1) % BPF_MEMWORDS;
7077478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		else {
7078478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			regused[curreg] = 1;
7079478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return curreg;
7080478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
7081478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
7082478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_error("too many registers needed to evaluate expression");
7083478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
7084478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return 0;
7085478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7086478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7087478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
7088478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Return a register to the table so it can
7089478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * be used later.
7090478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
7091478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic void
7092478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectfree_reg(n)
7093478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int n;
7094478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7095478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	regused[n] = 0;
7096478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7097478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7098478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
7099478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_len(jmp, n)
7100478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int jmp, n;
7101478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7102478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s;
7103478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b;
7104478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7105478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s = new_stmt(BPF_LD|BPF_LEN);
7106478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b = new_block(JMP(jmp));
7107478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b->stmts = s;
7108478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b->s.k = n;
7109478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7110478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b;
7111478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7112478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7113478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7114478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_greater(n)
7115478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int n;
7116478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7117478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return gen_len(BPF_JGE, n);
7118478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7119478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7120478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
7121478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Actually, this is less than or equal.
7122478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
7123478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7124478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_less(n)
7125478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int n;
7126478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7127478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b;
7128478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7129478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b = gen_len(BPF_JGT, n);
7130478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_not(b);
7131478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7132478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b;
7133478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7134478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7135478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
7136478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * This is for "byte {idx} {op} {val}"; "idx" is treated as relative to
7137478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * the beginning of the link-layer header.
7138478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * XXX - that means you can't test values in the radiotap header, but
7139478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * as that header is difficult if not impossible to parse generally
7140478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * without a loop, that might not be a severe problem.  A new keyword
7141478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * "radio" could be added for that, although what you'd really want
7142478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * would be a way of testing particular radio header values, which
7143478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * would generate code appropriate to the radio header in question.
7144478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
7145478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7146478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_byteop(op, idx, val)
7147478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int op, idx, val;
7148478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7149478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b;
7150478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct slist *s;
7151478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7152478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (op) {
7153478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
7154478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
7155478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7156478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case '=':
7157d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_cmp(OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
7158478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7159478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case '<':
7160d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b = gen_cmp_lt(OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
7161478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b;
7162478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7163478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case '>':
7164d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b = gen_cmp_gt(OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
7165478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b;
7166478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7167478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case '|':
7168478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s = new_stmt(BPF_ALU|BPF_OR|BPF_K);
7169478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
7170478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7171478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case '&':
7172478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
7173478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
7174478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
7175478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	s->s.k = val;
7176478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b = new_block(JMP(BPF_JEQ));
7177478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b->stmts = s;
7178478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	gen_not(b);
7179478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7180478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b;
7181478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7182478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7183478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic u_char abroadcast[] = { 0x0 };
7184478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7185478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7186478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_broadcast(proto)
7187478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int proto;
7188478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7189478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 hostmask;
7190478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1, *b2;
7191478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
7192478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7193478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (proto) {
7194478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7195478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
7196478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_LINK:
7197511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		switch (linktype) {
7198511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_ARCNET:
7199511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_ARCNET_LINUX:
7200511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return gen_ahostop(abroadcast, Q_DST);
7201511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_EN10MB:
7202511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_NETANALYZER:
7203511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_NETANALYZER_TRANSPARENT:
7204d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b1 = gen_prevlinkhdr_check();
7205d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_ehostop(ebroadcast, Q_DST);
7206d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			if (b1 != NULL)
7207d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes				gen_and(b1, b0);
7208d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return b0;
7209511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_FDDI:
7210511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return gen_fhostop(ebroadcast, Q_DST);
7211511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_IEEE802:
7212511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return gen_thostop(ebroadcast, Q_DST);
7213511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_IEEE802_11:
7214511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_PRISM_HEADER:
7215511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_IEEE802_11_RADIO_AVS:
7216511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_IEEE802_11_RADIO:
7217511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_PPI:
7218511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return gen_wlanhostop(ebroadcast, Q_DST);
7219511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_IP_OVER_FC:
7220511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return gen_ipfchostop(ebroadcast, Q_DST);
7221511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		default:
7222511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error("not a broadcast link");
7223511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
7224478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
7225478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7226478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IP:
7227511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
7228511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * We treat a netmask of PCAP_NETMASK_UNKNOWN (0xffffffff)
7229511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * as an indication that we don't know the netmask, and fail
7230511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * in that case.
7231511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
7232511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (netmask == PCAP_NETMASK_UNKNOWN)
7233511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error("netmask not known, so 'ip broadcast' not supported");
7234478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_linktype(ETHERTYPE_IP);
7235478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		hostmask = ~netmask;
7236d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_mcmp(OR_LINKPL, 16, BPF_W, (bpf_int32)0, hostmask);
7237d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b2 = gen_mcmp(OR_LINKPL, 16, BPF_W,
7238478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			      (bpf_int32)(~0 & hostmask), hostmask);
7239478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b1, b2);
7240478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b2);
7241478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b2;
7242478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
7243478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_error("only link-layer/IP broadcast filters supported");
7244478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
7245478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return NULL;
7246478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7247478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7248478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
7249478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Generate code to test the low-order bit of a MAC address (that's
7250478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * the bottom bit of the *first* byte).
7251478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
7252478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
7253478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_mac_multicast(offset)
7254478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int offset;
7255478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7256478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct block *b0;
7257478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct slist *s;
7258478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7259478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* link[offset] & 1 != 0 */
7260d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s = gen_load_a(OR_LINKHDR, offset, BPF_B);
7261478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b0 = new_block(JMP(BPF_JSET));
7262478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b0->s.k = 1;
7263478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b0->stmts = s;
7264478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b0;
7265478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7266478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7267478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7268478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_multicast(proto)
7269478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int proto;
7270478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7271478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct block *b0, *b1, *b2;
7272478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct slist *s;
7273478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7274478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (proto) {
7275478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7276478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
7277478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_LINK:
7278511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		switch (linktype) {
7279511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_ARCNET:
7280511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_ARCNET_LINUX:
7281511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* all ARCnet multicasts use the same address */
7282511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return gen_ahostop(abroadcast, Q_DST);
7283511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_EN10MB:
7284511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_NETANALYZER:
7285511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_NETANALYZER_TRANSPARENT:
7286d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b1 = gen_prevlinkhdr_check();
7287511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* ether[0] & 1 != 0 */
7288d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_mac_multicast(0);
7289d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			if (b1 != NULL)
7290d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes				gen_and(b1, b0);
7291d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			return b0;
7292511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_FDDI:
7293478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
7294511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX
7295511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *
7296511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * XXX - was that referring to bit-order issues?
7297478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
7298511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* fddi[1] & 1 != 0 */
7299511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return gen_mac_multicast(1);
7300511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_IEEE802:
7301511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* tr[2] & 1 != 0 */
7302511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return gen_mac_multicast(2);
7303511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_IEEE802_11:
7304511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_PRISM_HEADER:
7305511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_IEEE802_11_RADIO_AVS:
7306511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_IEEE802_11_RADIO:
7307511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_PPI:
7308511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
7309511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Oh, yuk.
7310511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *
7311511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *	For control frames, there is no DA.
7312511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *
7313511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *	For management frames, DA is at an
7314511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *	offset of 4 from the beginning of
7315511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *	the packet.
7316511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *
7317511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *	For data frames, DA is at an offset
7318511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *	of 4 from the beginning of the packet
7319511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *	if To DS is clear and at an offset of
7320511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *	16 from the beginning of the packet
7321511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *	if To DS is set.
7322511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
7323511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7324511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
7325511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Generate the tests to be done for data frames.
7326511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *
7327511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * First, check for To DS set, i.e. "link[1] & 0x01".
7328511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
7329d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			s = gen_load_a(OR_LINKHDR, 1, BPF_B);
7330511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b1 = new_block(JMP(BPF_JSET));
7331511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b1->s.k = 0x01;	/* To DS */
7332511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b1->stmts = s;
7333511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7334511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
7335511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * If To DS is set, the DA is at 16.
7336511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
7337511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b0 = gen_mac_multicast(16);
7338511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			gen_and(b1, b0);
7339511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7340511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
7341511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Now, check for To DS not set, i.e. check
7342511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * "!(link[1] & 0x01)".
7343511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
7344d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			s = gen_load_a(OR_LINKHDR, 1, BPF_B);
7345511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b2 = new_block(JMP(BPF_JSET));
7346511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b2->s.k = 0x01;	/* To DS */
7347511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b2->stmts = s;
7348511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			gen_not(b2);
7349511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7350511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
7351511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * If To DS is not set, the DA is at 4.
7352511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
7353511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b1 = gen_mac_multicast(4);
7354511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			gen_and(b2, b1);
7355511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7356511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
7357511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Now OR together the last two checks.  That gives
7358511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * the complete set of checks for data frames.
7359511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
7360511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			gen_or(b1, b0);
7361511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7362511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
7363511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Now check for a data frame.
7364511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * I.e, check "link[0] & 0x08".
7365511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
7366d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			s = gen_load_a(OR_LINKHDR, 0, BPF_B);
7367511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b1 = new_block(JMP(BPF_JSET));
7368511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b1->s.k = 0x08;
7369511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b1->stmts = s;
7370511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7371511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
7372511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * AND that with the checks done for data frames.
7373511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
7374511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			gen_and(b1, b0);
7375511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7376511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
7377511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * If the high-order bit of the type value is 0, this
7378511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * is a management frame.
7379511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * I.e, check "!(link[0] & 0x08)".
7380511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
7381d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			s = gen_load_a(OR_LINKHDR, 0, BPF_B);
7382511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b2 = new_block(JMP(BPF_JSET));
7383511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b2->s.k = 0x08;
7384511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b2->stmts = s;
7385511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			gen_not(b2);
7386511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7387511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
7388511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * For management frames, the DA is at 4.
7389511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
7390511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b1 = gen_mac_multicast(4);
7391511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			gen_and(b2, b1);
7392511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7393511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
7394511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * OR that with the checks done for data frames.
7395511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * That gives the checks done for management and
7396511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * data frames.
7397511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
7398511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			gen_or(b1, b0);
7399511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7400511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
7401511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * If the low-order bit of the type value is 1,
7402511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * this is either a control frame or a frame
7403511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * with a reserved type, and thus not a
7404511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * frame with an SA.
7405511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *
7406511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * I.e., check "!(link[0] & 0x04)".
7407511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
7408d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			s = gen_load_a(OR_LINKHDR, 0, BPF_B);
7409511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b1 = new_block(JMP(BPF_JSET));
7410511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b1->s.k = 0x04;
7411511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b1->stmts = s;
7412478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_not(b1);
7413478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7414511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
7415511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * AND that with the checks for data and management
7416511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * frames.
7417511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
7418478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			gen_and(b1, b0);
7419478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			return b0;
7420511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case DLT_IP_OVER_FC:
7421511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b0 = gen_mac_multicast(2);
7422511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return b0;
7423511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		default:
7424511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
7425511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
7426511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Link not known to support multicasts */
7427511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
7428478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7429478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IP:
7430478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_linktype(ETHERTYPE_IP);
7431d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_cmp_ge(OR_LINKPL, 16, BPF_B, (bpf_int32)224);
7432478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
7433478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
7434478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7435478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_IPV6:
7436478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_linktype(ETHERTYPE_IPV6);
7437d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_cmp(OR_LINKPL, 24, BPF_B, (bpf_int32)255);
7438478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
7439478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
7440478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
7441478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
7442478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
7443478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return NULL;
7444478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7445478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7446478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
7447511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Filter on inbound (dir == 0) or outbound (dir == 1) traffic.
7448511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Outbound traffic is sent by this machine, while inbound traffic is
7449511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * sent by a remote machine (and may include packets destined for a
7450511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * unicast or multicast link-layer address we are not subscribing to).
7451511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * These are the same definitions implemented by pcap_setdirection().
7452511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Capturing only unicast traffic destined for this host is probably
7453511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * better accomplished using a higher-layer filter.
7454478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
7455478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7456478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_inbound(dir)
7457478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dir;
7458478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7459478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct block *b0;
7460478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7461478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
7462478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * Only some data link types support inbound/outbound qualifiers.
7463478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
7464478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (linktype) {
7465478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_SLIP:
7466478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_relation(BPF_JEQ,
7467478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			  gen_load(Q_LINK, gen_loadi(0), 1),
7468478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			  gen_loadi(0),
7469478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			  dir);
7470478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
7471478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7472511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IPNET:
7473478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (dir) {
7474511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* match outgoing packets */
7475d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_cmp(OR_LINKHDR, 2, BPF_H, IPNET_OUTBOUND);
7476478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		} else {
7477511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* match incoming packets */
7478d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_cmp(OR_LINKHDR, 2, BPF_H, IPNET_INBOUND);
7479511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
7480511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
7481511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7482511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_LINUX_SLL:
7483511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* match outgoing packets */
7484d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp(OR_LINKHDR, 0, BPF_H, LINUX_SLL_OUTGOING);
7485511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (!dir) {
7486511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* to filter on inbound traffic, invert the match */
7487511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			gen_not(b0);
7488478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
7489478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
7490478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7491478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef HAVE_NET_PFVAR_H
7492478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_PFLOG:
7493d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, dir), BPF_B,
7494478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    (bpf_int32)((dir == 0) ? PF_IN : PF_OUT));
7495478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
7496478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
7497478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7498478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_PPP_PPPD:
7499478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (dir) {
7500478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/* match outgoing packets */
7501d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_cmp(OR_LINKHDR, 0, BPF_B, PPP_PPPD_OUT);
7502478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		} else {
7503478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/* match incoming packets */
7504d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_cmp(OR_LINKHDR, 0, BPF_B, PPP_PPPD_IN);
7505478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
7506478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
7507478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7508478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_MFR:
7509478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_MLFR:
7510478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_MLPPP:
7511478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_ATM1:
7512478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_ATM2:
7513478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_PPPOE:
7514478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_JUNIPER_PPPOE_ATM:
7515478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_GGSN:
7516478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_ES:
7517478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_MONITOR:
7518478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_SERVICES:
7519478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_ETHER:
7520478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_PPP:
7521478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_FRELAY:
7522478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_CHDLC:
7523478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case DLT_JUNIPER_VP:
7524511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall        case DLT_JUNIPER_ST:
7525511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall        case DLT_JUNIPER_ISM:
7526511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall        case DLT_JUNIPER_VS:
7527511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall        case DLT_JUNIPER_SRX_E2E:
7528511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall        case DLT_JUNIPER_FIBRECHANNEL:
7529511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_JUNIPER_ATM_CEMIC:
7530511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7531478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* juniper flags (including direction) are stored
7532478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the byte after the 3-byte magic number */
7533478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (dir) {
7534478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/* match outgoing packets */
7535d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_mcmp(OR_LINKHDR, 3, BPF_B, 0, 0x01);
7536478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		} else {
7537478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/* match incoming packets */
7538d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_mcmp(OR_LINKHDR, 3, BPF_B, 1, 0x01);
7539478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
7540511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
7541478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7542478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
7543511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
7544511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If we have packet meta-data indicating a direction,
7545511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * check it, otherwise give up as this link-layer type
7546511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * has nothing in the packet data.
7547511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
7548511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
7549511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
7550511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * This is Linux with PF_PACKET support.
7551511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If this is a *live* capture, we can look at
7552511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * special meta-data in the filter expression;
7553511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * if it's a savefile, we can't.
7554511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
7555511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (bpf_pcap->rfile != NULL) {
7556511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* We have a FILE *, so this is a savefile */
7557511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error("inbound/outbound not supported on linktype %d when reading savefiles",
7558511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    linktype);
7559511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			b0 = NULL;
7560511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* NOTREACHED */
7561511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
7562511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* match outgoing packets */
7563d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_cmp(OR_LINKHDR, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H,
7564511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		             PACKET_OUTGOING);
7565511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (!dir) {
7566511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* to filter on inbound traffic, invert the match */
7567511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			gen_not(b0);
7568511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
7569511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
7570478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("inbound/outbound not supported on linktype %d",
7571478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    linktype);
7572478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = NULL;
7573478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
7574511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
7575478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
7576478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (b0);
7577478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7578478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7579478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef HAVE_NET_PFVAR_H
7580478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/* PF firewall log matched interface */
7581478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7582478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_pf_ifname(const char *ifname)
7583478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7584478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0;
7585478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	u_int len, off;
7586478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7587511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (linktype != DLT_PFLOG) {
7588511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("ifname supported only on PF linktype");
7589478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
7590478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
7591511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	len = sizeof(((struct pfloghdr *)0)->ifname);
7592511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	off = offsetof(struct pfloghdr, ifname);
7593478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (strlen(ifname) >= len) {
7594478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("ifname interface names can only be %d characters",
7595478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    len-1);
7596478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
7597478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
7598d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_bcmp(OR_LINKHDR, off, strlen(ifname), (const u_char *)ifname);
7599478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (b0);
7600478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7601478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7602478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/* PF firewall log ruleset name */
7603478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7604478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_pf_ruleset(char *ruleset)
7605478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7606478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0;
7607478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7608478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (linktype != DLT_PFLOG) {
7609511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("ruleset supported only on PF linktype");
7610478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
7611478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
7612511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7613478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (strlen(ruleset) >= sizeof(((struct pfloghdr *)0)->ruleset)) {
7614478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("ruleset names can only be %ld characters",
7615478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    (long)(sizeof(((struct pfloghdr *)0)->ruleset) - 1));
7616478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
7617478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
7618511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7619d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_bcmp(OR_LINKHDR, offsetof(struct pfloghdr, ruleset),
7620478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	    strlen(ruleset), (const u_char *)ruleset);
7621478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (b0);
7622478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7623478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7624478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/* PF firewall log rule number */
7625478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7626478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_pf_rnr(int rnr)
7627478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7628478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0;
7629478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7630511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (linktype != DLT_PFLOG) {
7631511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("rnr supported only on PF linktype");
7632478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
7633478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
7634478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7635d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, rulenr), BPF_W,
7636511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 (bpf_int32)rnr);
7637478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (b0);
7638478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7639478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7640478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/* PF firewall log sub-rule number */
7641478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7642478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_pf_srnr(int srnr)
7643478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7644478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0;
7645478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7646478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (linktype != DLT_PFLOG) {
7647511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("srnr supported only on PF linktype");
7648478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
7649478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
7650478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7651d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, subrulenr), BPF_W,
7652478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	    (bpf_int32)srnr);
7653478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (b0);
7654478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7655478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7656478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/* PF firewall log reason code */
7657478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7658478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_pf_reason(int reason)
7659478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7660478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0;
7661478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7662511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (linktype != DLT_PFLOG) {
7663511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("reason supported only on PF linktype");
7664478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
7665478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
7666478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7667d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, reason), BPF_B,
7668511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    (bpf_int32)reason);
7669478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (b0);
7670478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7671478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7672478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/* PF firewall log action */
7673478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7674478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_pf_action(int action)
7675478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7676478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0;
7677478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7678511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (linktype != DLT_PFLOG) {
7679511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("action supported only on PF linktype");
7680478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* NOTREACHED */
7681478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
7682478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7683d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, action), BPF_B,
7684511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    (bpf_int32)action);
7685478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (b0);
7686478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7687478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#else /* !HAVE_NET_PFVAR_H */
7688478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7689478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_pf_ifname(const char *ifname)
7690478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7691478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_error("libpcap was compiled without pf support");
7692478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
7693478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (NULL);
7694478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7695478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7696478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7697478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_pf_ruleset(char *ruleset)
7698478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7699478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_error("libpcap was compiled on a machine without pf support");
7700478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
7701478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (NULL);
7702478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7703478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7704478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7705478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_pf_rnr(int rnr)
7706478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7707478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_error("libpcap was compiled on a machine without pf support");
7708478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
7709478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (NULL);
7710478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7711478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7712478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7713478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_pf_srnr(int srnr)
7714478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7715478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_error("libpcap was compiled on a machine without pf support");
7716478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
7717478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (NULL);
7718478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7719478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7720478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7721478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_pf_reason(int reason)
7722478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7723478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_error("libpcap was compiled on a machine without pf support");
7724478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
7725478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (NULL);
7726478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7727478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7728478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7729478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_pf_action(int action)
7730478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7731478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_error("libpcap was compiled on a machine without pf support");
7732478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
7733478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (NULL);
7734478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7735478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif /* HAVE_NET_PFVAR_H */
7736478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7737511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* IEEE 802.11 wireless header */
7738511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstruct block *
7739511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallgen_p80211_type(int type, int mask)
7740511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
7741511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct block *b0;
7742511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7743511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	switch (linktype) {
7744511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7745511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_11:
7746511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_PRISM_HEADER:
7747511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_11_RADIO_AVS:
7748511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_11_RADIO:
7749d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_mcmp(OR_LINKHDR, 0, BPF_B, (bpf_int32)type,
7750511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    (bpf_int32)mask);
7751511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
7752511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7753511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	default:
7754511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("802.11 link-layer types supported only on 802.11");
7755511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* NOTREACHED */
7756511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
7757511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7758511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return (b0);
7759511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
7760511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7761511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstruct block *
7762511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallgen_p80211_fcdir(int fcdir)
7763511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
7764511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct block *b0;
7765511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7766511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	switch (linktype) {
7767511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7768511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_11:
7769511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_PRISM_HEADER:
7770511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_11_RADIO_AVS:
7771511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_IEEE802_11_RADIO:
7772511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
7773511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7774511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	default:
7775511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("frame direction supported only with 802.11 headers");
7776511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* NOTREACHED */
7777511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
7778511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7779d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_mcmp(OR_LINKHDR, 1, BPF_B, (bpf_int32)fcdir,
7780511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		(bpf_u_int32)IEEE80211_FC1_DIR_MASK);
7781511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7782511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return (b0);
7783511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
7784511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7785478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7786478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_acode(eaddr, q)
7787478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register const u_char *eaddr;
7788478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct qual q;
7789478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7790511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	switch (linktype) {
7791511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7792511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_ARCNET:
7793511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_ARCNET_LINUX:
7794511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) &&
7795511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    q.proto == Q_LINK)
7796511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return (gen_ahostop(eaddr, (int)q.dir));
7797511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		else {
7798511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error("ARCnet address used in non-arc expression");
7799511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* NOTREACHED */
7800511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
7801511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
7802511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7803511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	default:
7804511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("aid supported only on ARCnet");
7805511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* NOTREACHED */
7806478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
7807478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_error("ARCnet address used in non-arc expression");
7808478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
7809478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return NULL;
7810478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7811478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7812478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
7813478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_ahostop(eaddr, dir)
7814478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register const u_char *eaddr;
7815478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int dir;
7816478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7817478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct block *b0, *b1;
7818478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7819478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (dir) {
7820478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* src comes first, different from Ethernet */
7821478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_SRC:
7822d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_bcmp(OR_LINKHDR, 0, 1, eaddr);
7823478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7824478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DST:
7825d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		return gen_bcmp(OR_LINKHDR, 1, 1, eaddr);
7826478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7827478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_AND:
7828478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_ahostop(eaddr, Q_SRC);
7829478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_ahostop(eaddr, Q_DST);
7830478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
7831478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
7832478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7833478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_DEFAULT:
7834478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case Q_OR:
7835478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_ahostop(eaddr, Q_SRC);
7836478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_ahostop(eaddr, Q_DST);
7837478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
7838478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return b1;
7839511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7840511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR1:
7841511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr1' is only supported on 802.11");
7842511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
7843511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7844511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR2:
7845511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr2' is only supported on 802.11");
7846511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
7847511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7848511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR3:
7849511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr3' is only supported on 802.11");
7850511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
7851511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7852511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_ADDR4:
7853511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'addr4' is only supported on 802.11");
7854511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
7855511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7856511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_RA:
7857511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'ra' is only supported on 802.11");
7858511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
7859511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
7860511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case Q_TA:
7861511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bpf_error("'ta' is only supported on 802.11");
7862511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
7863478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
7864478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	abort();
7865478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* NOTREACHED */
7866478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
7867478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7868d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
7869d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic struct block *
7870d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_vlan_bpf_extensions(int vlan_num)
7871d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes{
7872d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        struct block *b0, *b1;
7873d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        struct slist *s;
7874d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
7875d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        /* generate new filter code based on extracting packet
7876d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes         * metadata */
7877d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
7878d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT;
7879d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
7880d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        b0 = new_block(JMP(BPF_JEQ));
7881d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        b0->stmts = s;
7882d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        b0->s.k = 1;
7883d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
7884d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        if (vlan_num >= 0) {
7885d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
7886d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG;
7887d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
7888d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                b1 = new_block(JMP(BPF_JEQ));
7889d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                b1->stmts = s;
7890d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                b1->s.k = (bpf_int32) vlan_num;
7891d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
7892d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                gen_and(b0,b1);
7893d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                b0 = b1;
7894d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        }
7895d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
7896d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        return b0;
7897d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes}
7898d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes#endif
7899d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
7900d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic struct block *
7901d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_vlan_no_bpf_extensions(int vlan_num)
7902d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes{
7903d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        struct block *b0, *b1;
7904d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
7905d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        /* check for VLAN, including QinQ */
7906d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        b0 = gen_linktype(ETHERTYPE_8021Q);
7907d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        b1 = gen_linktype(ETHERTYPE_8021QINQ);
7908d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        gen_or(b0,b1);
7909d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        b0 = b1;
7910d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
7911d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        /* If a specific VLAN is requested, check VLAN id */
7912d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        if (vlan_num >= 0) {
7913d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                b1 = gen_mcmp(OR_LINKPL, 0, BPF_H,
7914d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                              (bpf_int32)vlan_num, 0x0fff);
7915d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                gen_and(b0, b1);
7916d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                b0 = b1;
7917d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        }
7918d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
7919d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/*
7920d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * The payload follows the full header, including the
7921d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * VLAN tags, so skip past this VLAN tag.
7922d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 */
7923d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        off_linkpl.constant_part += 4;
7924d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
7925d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/*
7926d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * The link-layer type information follows the VLAN tags, so
7927d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * skip past this VLAN tag.
7928d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 */
7929d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        off_linktype.constant_part += 4;
7930d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
7931d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        return b0;
7932d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes}
7933d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
7934478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
7935478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * support IEEE 802.1Q VLAN trunk over ethernet
7936478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
7937478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
7938478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_vlan(vlan_num)
7939478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int vlan_num;
7940478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
7941d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct	block	*b0;
7942478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7943478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* can't check for VLAN-encapsulated packets inside MPLS */
7944478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (label_stack_depth > 0)
7945478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("no VLAN match after MPLS");
7946478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7947478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
7948511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Check for a VLAN packet, and then change the offsets to point
7949511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * to the type and data fields within the VLAN packet.  Just
7950511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * increment the offsets, so that we can support a hierarchy, e.g.
7951511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * "vlan 300 && vlan 200" to capture VLAN 200 encapsulated within
7952511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * VLAN 100.
7953478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 *
7954478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * XXX - this is a bit of a kludge.  If we were to split the
7955478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * compiler into a parser that parses an expression and
7956478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * generates an expression tree, and a code generator that
7957478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * takes an expression tree (which could come from our
7958478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * parser or from some other parser) and generates BPF code,
7959478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * we could perhaps make the offsets parameters of routines
7960478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * and, in the handler for an "AND" node, pass to subnodes
7961478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * other than the VLAN node the adjusted offsets.
7962478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 *
7963478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * This would mean that "vlan" would, instead of changing the
7964478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * behavior of *all* tests after it, change only the behavior
7965478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * of tests ANDed with it.  That would change the documented
7966478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * semantics of "vlan", which might break some expressions.
7967478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * However, it would mean that "(vlan and ip) or ip" would check
7968478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
7969478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * checking only for VLAN-encapsulated IP, so that could still
7970478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * be considered worth doing; it wouldn't break expressions
7971478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * that are of the form "vlan and ..." or "vlan N and ...",
7972478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * which I suspect are the most common expressions involving
7973478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * "vlan".  "vlan or ..." doesn't necessarily do what the user
7974478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * would really want, now, as all the "or ..." tests would
7975478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * be done assuming a VLAN, even though the "or" could be viewed
7976478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * as meaning "or, if this isn't a VLAN packet...".
7977478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
7978478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (linktype) {
7979478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
7980478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case DLT_EN10MB:
7981511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_NETANALYZER:
7982511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_NETANALYZER_TRANSPARENT:
7983d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
7984d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		/* Verify that this is the outer part of the packet and
7985d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * not encapsulated somehow. */
7986d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		if (vlan_stack_depth == 0 && !off_linkhdr.is_variable &&
7987d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		    off_linkhdr.constant_part ==
7988d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		    off_outermostlinkhdr.constant_part) {
7989d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			/*
7990d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			 * Do we need special VLAN handling?
7991d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			 */
7992d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			if (bpf_pcap->bpf_codegen_flags & BPF_SPECIAL_VLAN_HANDLING)
7993d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes				b0 = gen_vlan_bpf_extensions(vlan_num);
7994d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			else
7995d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes				b0 = gen_vlan_no_bpf_extensions(vlan_num);
7996d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		} else
7997511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
7998d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			b0 = gen_vlan_no_bpf_extensions(vlan_num);
7999d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes                break;
8000d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8001d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_IEEE802_11:
8002d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_PRISM_HEADER:
8003d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_IEEE802_11_RADIO_AVS:
8004d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	case DLT_IEEE802_11_RADIO:
8005d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_vlan_no_bpf_extensions(vlan_num);
8006478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8007478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8008478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
8009478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		bpf_error("no VLAN support for data link type %d",
8010478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		      linktype);
8011478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*NOTREACHED*/
8012478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
8013478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8014d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        vlan_stack_depth++;
8015d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8016478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (b0);
8017478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
8018478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8019478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
8020478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * support for MPLS
8021478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
8022478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
8023478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_mpls(label_num)
8024478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int label_num;
8025478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
8026d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct	block	*b0, *b1;
8027478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8028478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        if (label_stack_depth > 0) {
8029478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project            /* just match the bottom-of-stack bit clear */
8030d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes            b0 = gen_mcmp(OR_PREVMPLSHDR, 2, BPF_B, 0, 0x01);
8031478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        } else {
8032478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project            /*
8033d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes             * We're not in an MPLS stack yet, so check the link-layer
8034d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes             * type against MPLS.
8035478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project             */
8036478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project            switch (linktype) {
8037d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8038478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project            case DLT_C_HDLC: /* fall through */
8039478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project            case DLT_EN10MB:
8040511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall            case DLT_NETANALYZER:
8041511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall            case DLT_NETANALYZER_TRANSPARENT:
8042478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                    b0 = gen_linktype(ETHERTYPE_MPLS);
8043478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                    break;
8044d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8045478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project            case DLT_PPP:
8046478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                    b0 = gen_linktype(PPP_MPLS_UCAST);
8047478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                    break;
8048d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8049478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                    /* FIXME add other DLT_s ...
8050478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                     * for Frame-Relay/and ATM this may get messy due to SNAP headers
8051478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                     * leave it for now */
8052d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8053478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project            default:
8054478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                    bpf_error("no MPLS support for data link type %d",
8055478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                          linktype);
8056478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                    b0 = NULL;
8057478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                    /*NOTREACHED*/
8058478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project                    break;
8059478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project            }
8060478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        }
8061478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8062478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* If a specific MPLS label is requested, check it */
8063478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (label_num >= 0) {
8064478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		label_num = label_num << 12; /* label is shifted 12 bits on the wire */
8065d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_mcmp(OR_LINKPL, 0, BPF_W, (bpf_int32)label_num,
8066478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    0xfffff000); /* only compare the first 20 bits */
8067478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
8068478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = b1;
8069478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
8070478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8071d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes        /*
8072d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes         * Change the offsets to point to the type and data fields within
8073d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes         * the MPLS packet.  Just increment the offsets, so that we
8074d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes         * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to
8075d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes         * capture packets with an outer label of 100000 and an inner
8076d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes         * label of 1024.
8077d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes         *
8078d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes         * Increment the MPLS stack depth as well; this indicates that
8079d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes         * we're checking MPLS-encapsulated headers, to make sure higher
8080d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes         * level code generators don't try to match against IP-related
8081d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes         * protocols such as Q_ARP, Q_RARP etc.
8082d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes         *
8083d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes         * XXX - this is a bit of a kludge.  See comments in gen_vlan().
8084d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes         */
8085478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        off_nl_nosnap += 4;
8086478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        off_nl += 4;
8087478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        label_stack_depth++;
8088478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return (b0);
8089478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
8090478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8091478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
8092478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Support PPPOE discovery and session.
8093478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
8094478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
8095478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_pppoed()
8096478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
8097478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* check for PPPoE discovery */
8098478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return gen_linktype((bpf_int32)ETHERTYPE_PPPOED);
8099478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
8100478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8101478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
8102511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallgen_pppoes(sess_num)
8103511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int sess_num;
8104478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
8105511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct block *b0, *b1;
8106478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8107478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
8108478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * Test against the PPPoE session link-layer type.
8109478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
8110478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	b0 = gen_linktype((bpf_int32)ETHERTYPE_PPPOES);
8111478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8112d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* If a specific session is requested, check PPPoE session id */
8113d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	if (sess_num >= 0) {
8114d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_mcmp(OR_LINKPL, 0, BPF_W,
8115d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		    (bpf_int32)sess_num, 0x0000ffff);
8116d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		gen_and(b0, b1);
8117d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = b1;
8118d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	}
8119d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8120478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
8121478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * Change the offsets to point to the type and data fields within
8122511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the PPP packet, and note that this is PPPoE rather than
8123511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * raw PPP.
8124478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 *
8125478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * XXX - this is a bit of a kludge.  If we were to split the
8126478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * compiler into a parser that parses an expression and
8127478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * generates an expression tree, and a code generator that
8128478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * takes an expression tree (which could come from our
8129478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * parser or from some other parser) and generates BPF code,
8130478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * we could perhaps make the offsets parameters of routines
8131478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * and, in the handler for an "AND" node, pass to subnodes
8132478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * other than the PPPoE node the adjusted offsets.
8133478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 *
8134478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * This would mean that "pppoes" would, instead of changing the
8135478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * behavior of *all* tests after it, change only the behavior
8136478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * of tests ANDed with it.  That would change the documented
8137478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * semantics of "pppoes", which might break some expressions.
8138478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * However, it would mean that "(pppoes and ip) or ip" would check
8139478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
8140478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * checking only for VLAN-encapsulated IP, so that could still
8141478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * be considered worth doing; it wouldn't break expressions
8142478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * that are of the form "pppoes and ..." which I suspect are the
8143478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * most common expressions involving "pppoes".  "pppoes or ..."
8144478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * doesn't necessarily do what the user would really want, now,
8145478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * as all the "or ..." tests would be done assuming PPPoE, even
8146478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * though the "or" could be viewed as meaning "or, if this isn't
8147478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * a PPPoE packet...".
8148d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 *
8149478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * The "network-layer" protocol is PPPoE, which has a 6-byte
8150511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * PPPoE header, followed by a PPP packet.
8151511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
8152511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * There is no HDLC encapsulation for the PPP packet (it's
8153511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * encapsulated in PPPoES instead), so the link-layer type
8154511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * starts at the first byte of the PPP packet.  For PPPoE,
8155511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * that offset is relative to the beginning of the total
8156511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * link-layer payload, including any 802.2 LLC header, so
8157511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * it's 6 bytes past off_nl.
8158478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
8159d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	PUSH_LINKHDR(DLT_PPP, off_linkpl.is_variable,
8160d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	    off_linkpl.constant_part + off_nl + 6, /* 6 bytes past the PPPoE header */
8161d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	    off_linkpl.reg);
8162478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8163d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linktype = off_linkhdr;
8164d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linkpl.constant_part = off_linkhdr.constant_part + 2;
8165d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8166d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_nl = 0;
8167d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_nl_nosnap = 0;	/* no 802.2 LLC */
8168d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8169d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	return b0;
8170d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes}
8171d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8172d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes/* Check that this is Geneve and the VNI is correct if
8173d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * specified. Parameterized to handle both IPv4 and IPv6. */
8174d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic struct block *
8175d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_geneve_check(struct block *(*gen_portfn)(int, int, int),
8176d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 enum e_offrel offrel, int vni)
8177d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes{
8178d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct block *b0, *b1;
8179d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8180d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_portfn(GENEVE_PORT, IPPROTO_UDP, Q_DST);
8181d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8182d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Check that we are operating on version 0. Otherwise, we
8183d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * can't decode the rest of the fields. The version is 2 bits
8184d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * in the first byte of the Geneve header. */
8185d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1 = gen_mcmp(offrel, 8, BPF_B, (bpf_int32)0, 0xc0);
8186d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	gen_and(b0, b1);
8187d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = b1;
8188d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8189d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	if (vni >= 0) {
8190d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		vni <<= 8; /* VNI is in the upper 3 bytes */
8191d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b1 = gen_mcmp(offrel, 12, BPF_W, (bpf_int32)vni,
8192d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes			      0xffffff00);
8193d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		gen_and(b0, b1);
8194d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = b1;
8195d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	}
8196d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8197d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	return b0;
8198d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes}
8199d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8200d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes/* The IPv4 and IPv6 Geneve checks need to do two things:
8201d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * - Verify that this actually is Geneve with the right VNI.
8202d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * - Place the IP header length (plus variable link prefix if
8203d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *   needed) into register A to be used later to compute
8204d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes *   the inner packet offsets. */
8205d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic struct block *
8206d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_geneve4(int vni)
8207d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes{
8208d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct block *b0, *b1;
8209d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct slist *s, *s1;
8210d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8211d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_geneve_check(gen_port, OR_TRAN_IPV4, vni);
8212d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8213d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Load the IP header length into A. */
8214d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s = gen_loadx_iphdrlen();
8215d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8216d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_MISC|BPF_TXA);
8217d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8218d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8219d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Forcibly append these statements to the true condition
8220d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * of the protocol check by creating a new block that is
8221d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * always true and ANDing them. */
8222d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1 = new_block(BPF_JMP|BPF_JEQ|BPF_X);
8223d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1->stmts = s;
8224d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1->s.k = 0;
8225d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8226d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	gen_and(b0, b1);
8227d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8228d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	return b1;
8229d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes}
8230d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8231d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic struct block *
8232d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_geneve6(int vni)
8233d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes{
8234d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct block *b0, *b1;
8235d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct slist *s, *s1;
8236d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8237d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_geneve_check(gen_port6, OR_TRAN_IPV6, vni);
8238d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8239d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Load the IP header length. We need to account for a
8240d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * variable length link prefix if there is one. */
8241d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s = gen_abs_offset_varpart(&off_linkpl);
8242d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	if (s) {
8243d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s1 = new_stmt(BPF_LD|BPF_IMM);
8244d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s1->s.k = 40;
8245d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		sappend(s, s1);
8246d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8247d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_X);
8248d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s1->s.k = 0;
8249d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		sappend(s, s1);
8250d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	} else {
8251d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s = new_stmt(BPF_LD|BPF_IMM);
8252d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		s->s.k = 40;;
8253d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	}
8254d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8255d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Forcibly append these statements to the true condition
8256d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * of the protocol check by creating a new block that is
8257d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * always true and ANDing them. */
8258d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_MISC|BPF_TAX);
8259d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8260d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8261d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1 = new_block(BPF_JMP|BPF_JEQ|BPF_X);
8262d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1->stmts = s;
8263d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1->s.k = 0;
8264d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8265d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	gen_and(b0, b1);
8266d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8267d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	return b1;
8268d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes}
8269d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8270d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes/* We need to store three values based on the Geneve header::
8271d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * - The offset of the linktype.
8272d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * - The offset of the end of the Geneve header.
8273d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * - The offset of the end of the encapsulated MAC header. */
8274d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic struct slist *
8275d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_geneve_offsets(void)
8276d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes{
8277d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct slist *s, *s1, *s_proto;
8278d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8279d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* First we need to calculate the offset of the Geneve header
8280d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * itself. This is composed of the IP header previously calculated
8281d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * (include any variable link prefix) and stored in A plus the
8282d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * fixed sized headers (fixed link prefix, MAC length, and UDP
8283d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * header). */
8284d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
8285d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s->s.k = off_linkpl.constant_part + off_nl + 8;
8286d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8287d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Stash this in X since we'll need it later. */
8288d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_MISC|BPF_TAX);
8289d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8290d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8291d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* The EtherType in Geneve is 2 bytes in. Calculate this and
8292d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * store it. */
8293d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
8294d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1->s.k = 2;
8295d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8296d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8297d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linktype.reg = alloc_reg();
8298d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linktype.is_variable = 1;
8299d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linktype.constant_part = 0;
8300d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8301d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_ST);
8302d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1->s.k = off_linktype.reg;
8303d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8304d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8305d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Load the Geneve option length and mask and shift to get the
8306d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * number of bytes. It is stored in the first byte of the Geneve
8307d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * header. */
8308d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_LD|BPF_IND|BPF_B);
8309d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1->s.k = 0;
8310d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8311d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8312d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
8313d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1->s.k = 0x3f;
8314d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8315d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8316d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
8317d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1->s.k = 4;
8318d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8319d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8320d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Add in the rest of the Geneve base header. */
8321d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
8322d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1->s.k = 8;
8323d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8324d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8325d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Add the Geneve header length to its offset and store. */
8326d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_X);
8327d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1->s.k = 0;
8328d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8329d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8330d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Set the encapsulated type as Ethernet. Even though we may
8331d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * not actually have Ethernet inside there are two reasons this
8332d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * is useful:
8333d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * - The linktype field is always in EtherType format regardless
8334d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 *   of whether it is in Geneve or an inner Ethernet frame.
8335d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * - The only link layer that we have specific support for is
8336d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 *   Ethernet. We will confirm that the packet actually is
8337d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 *   Ethernet at runtime before executing these checks. */
8338d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	PUSH_LINKHDR(DLT_EN10MB, 1, 0, alloc_reg());
8339d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8340d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_ST);
8341d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1->s.k = off_linkhdr.reg;
8342d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8343d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8344d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Calculate whether we have an Ethernet header or just raw IP/
8345d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * MPLS/etc. If we have Ethernet, advance the end of the MAC offset
8346d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * and linktype by 14 bytes so that the network header can be found
8347d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * seamlessly. Otherwise, keep what we've calculated already. */
8348d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8349d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* We have a bare jmp so we can't use the optimizer. */
8350d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	no_optimize = 1;
8351d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8352d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Load the EtherType in the Geneve header, 2 bytes in. */
8353d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_LD|BPF_IND|BPF_H);
8354d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1->s.k = 2;
8355d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8356d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8357d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Load X with the end of the Geneve header. */
8358d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_LDX|BPF_MEM);
8359d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1->s.k = off_linkhdr.reg;
8360d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8361d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8362d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Check if the EtherType is Transparent Ethernet Bridging. At the
8363d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * end of this check, we should have the total length in X. In
8364d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * the non-Ethernet case, it's already there. */
8365d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s_proto = new_stmt(JMP(BPF_JEQ));
8366d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s_proto->s.k = ETHERTYPE_TEB;
8367d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s_proto);
8368d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8369d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_MISC|BPF_TXA);
8370d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8371d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s_proto->s.jt = s1;
8372d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8373d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Since this is Ethernet, use the EtherType of the payload
8374d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * directly as the linktype. Overwrite what we already have. */
8375d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
8376d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1->s.k = 12;
8377d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8378d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8379d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_ST);
8380d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1->s.k = off_linktype.reg;
8381d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8382d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8383d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Advance two bytes further to get the end of the Ethernet
8384d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * header. */
8385d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
8386d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1->s.k = 2;
8387d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8388d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8389d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Move the result to X. */
8390d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_MISC|BPF_TAX);
8391d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8392d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8393d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Store the final result of our linkpl calculation. */
8394d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linkpl.reg = alloc_reg();
8395d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linkpl.is_variable = 1;
8396d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_linkpl.constant_part = 0;
8397d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8398d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_STX);
8399d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1->s.k = off_linkpl.reg;
8400d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8401d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s_proto->s.jf = s1;
8402d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8403d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	off_nl = 0;
8404d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8405d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	return s;
8406d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes}
8407d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8408d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes/* Check to see if this is a Geneve packet. */
8409d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstruct block *
8410d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_geneve(int vni)
8411d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes{
8412d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct block *b0, *b1;
8413d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct slist *s;
8414d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8415d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = gen_geneve4(vni);
8416d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1 = gen_geneve6(vni);
8417d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8418d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	gen_or(b0, b1);
8419d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = b1;
8420d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8421d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Later filters should act on the payload of the Geneve frame,
8422d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * update all of the header pointers. Attach this code so that
8423d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * it gets executed in the event that the Geneve filter matches. */
8424d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s = gen_geneve_offsets();
8425d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8426d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1 = gen_true();
8427d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, b1->stmts);
8428d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b1->stmts = s;
8429d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8430d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	gen_and(b0, b1);
8431d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8432d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	is_geneve = 1;
8433d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8434d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	return b1;
8435d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes}
8436d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8437d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes/* Check that the encapsulated frame has a link layer header
8438d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes * for Ethernet filters. */
8439d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesstatic struct block *
8440d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughesgen_geneve_ll_check()
8441d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes{
8442d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct block *b0;
8443d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	struct slist *s, *s1;
8444d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8445d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* The easiest way to see if there is a link layer present
8446d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * is to check if the link layer header and payload are not
8447d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * the same. */
8448d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8449d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	/* Geneve always generates pure variable offsets so we can
8450d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	 * compare only the registers. */
8451d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s = new_stmt(BPF_LD|BPF_MEM);
8452d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s->s.k = off_linkhdr.reg;
8453d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8454d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1 = new_stmt(BPF_LDX|BPF_MEM);
8455d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	s1->s.k = off_linkpl.reg;
8456d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	sappend(s, s1);
8457d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes
8458d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0 = new_block(BPF_JMP|BPF_JEQ|BPF_X);
8459d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0->stmts = s;
8460d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	b0->s.k = 0;
8461d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes	gen_not(b0);
8462478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8463478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b0;
8464478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
8465478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8466478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
8467478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_atmfield_code(atmfield, jvalue, jtype, reverse)
8468478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int atmfield;
8469478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_int32 jvalue;
8470478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 jtype;
8471478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int reverse;
8472478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
8473478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0;
8474478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8475478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (atmfield) {
8476478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8477478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_VPI:
8478478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (!is_atm)
8479478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'vpi' supported only on raw ATM");
8480478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (off_vpi == (u_int)-1)
8481478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			abort();
8482d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_ncmp(OR_LINKHDR, off_vpi, BPF_B, 0xffffffff, jtype,
8483478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    reverse, jvalue);
8484478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8485478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8486478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_VCI:
8487478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (!is_atm)
8488478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'vci' supported only on raw ATM");
8489478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (off_vci == (u_int)-1)
8490478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			abort();
8491d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_ncmp(OR_LINKHDR, off_vci, BPF_H, 0xffffffff, jtype,
8492478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    reverse, jvalue);
8493478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8494478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8495478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_PROTOTYPE:
8496478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (off_proto == (u_int)-1)
8497478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			abort();	/* XXX - this isn't on FreeBSD */
8498d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_ncmp(OR_LINKHDR, off_proto, BPF_B, 0x0f, jtype,
8499478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    reverse, jvalue);
8500478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8501478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8502478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_MSGTYPE:
8503478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (off_payload == (u_int)-1)
8504478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			abort();
8505d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_ncmp(OR_LINKHDR, off_payload + MSG_TYPE_POS, BPF_B,
8506478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    0xffffffff, jtype, reverse, jvalue);
8507478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8508478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8509478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_CALLREFTYPE:
8510478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (!is_atm)
8511478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'callref' supported only on raw ATM");
8512478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (off_proto == (u_int)-1)
8513478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			abort();
8514d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		b0 = gen_ncmp(OR_LINKHDR, off_proto, BPF_B, 0xffffffff,
8515478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    jtype, reverse, jvalue);
8516478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8517478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8518478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
8519478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
8520478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
8521478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b0;
8522478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
8523478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8524478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
8525478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_atmtype_abbrev(type)
8526478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int type;
8527478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
8528478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1;
8529478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8530478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (type) {
8531478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8532478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_METAC:
8533478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* Get all packets in Meta signalling Circuit */
8534478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (!is_atm)
8535478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'metac' supported only on raw ATM");
8536478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8537478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_atmfield_code(A_VCI, 1, BPF_JEQ, 0);
8538478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
8539478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8540478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8541478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_BCC:
8542478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* Get all packets in Broadcast Circuit*/
8543478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (!is_atm)
8544478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'bcc' supported only on raw ATM");
8545478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8546478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_atmfield_code(A_VCI, 2, BPF_JEQ, 0);
8547478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
8548478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8549478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8550478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_OAMF4SC:
8551478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* Get all cells in Segment OAM F4 circuit*/
8552478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (!is_atm)
8553478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'oam4sc' supported only on raw ATM");
8554478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8555478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
8556478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
8557478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8558478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8559478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_OAMF4EC:
8560478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* Get all cells in End-to-End OAM F4 Circuit*/
8561478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (!is_atm)
8562478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'oam4ec' supported only on raw ATM");
8563478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8564478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0);
8565478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
8566478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8567478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8568478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_SC:
8569478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*  Get all packets in connection Signalling Circuit */
8570478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (!is_atm)
8571478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'sc' supported only on raw ATM");
8572478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8573478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_atmfield_code(A_VCI, 5, BPF_JEQ, 0);
8574478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
8575478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8576478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8577478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_ILMIC:
8578478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* Get all packets in ILMI Circuit */
8579478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (!is_atm)
8580478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'ilmic' supported only on raw ATM");
8581478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8582478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_atmfield_code(A_VCI, 16, BPF_JEQ, 0);
8583478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
8584478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8585478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8586478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_LANE:
8587478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* Get all LANE packets */
8588478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (!is_atm)
8589478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'lane' supported only on raw ATM");
8590478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_atmfield_code(A_PROTOTYPE, PT_LANE, BPF_JEQ, 0);
8591478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8592478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
8593478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Arrange that all subsequent tests assume LANE
8594478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * rather than LLC-encapsulated packets, and set
8595478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * the offsets appropriately for LANE-encapsulated
8596478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Ethernet.
8597478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
8598d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 * We assume LANE means Ethernet, not Token Ring.
8599d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		 */
8600d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		PUSH_LINKHDR(DLT_EN10MB, 0,
8601d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		    off_payload + 2,	/* Ethernet header */
8602d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		    -1);
8603d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linktype.constant_part = off_linkhdr.constant_part + 12;
8604d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		off_linkpl.constant_part = off_linkhdr.constant_part + 14;	/* Ethernet */
8605511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl = 0;			/* Ethernet II */
8606511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		off_nl_nosnap = 3;		/* 802.3+802.2 */
8607478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8608478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8609478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_LLC:
8610478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* Get all LLC-encapsulated packets */
8611478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (!is_atm)
8612478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'llc' supported only on raw ATM");
8613478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
8614d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes		linktype = prevlinktype;
8615478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8616478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8617478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
8618478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
8619478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
8620478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b1;
8621478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
8622478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8623d8845d7191ca81aae8aab4c29410fc8a3d012687Elliott Hughes/*
8624478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Filtering for MTP2 messages based on li value
8625478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * FISU, length is null
8626478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * LSSU, length is 1 or 2
8627478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * MSU, length is 3 or more
8628511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * For MTP2_HSL, sequences are on 2 bytes, and length on 9 bits
8629478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
8630478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
8631478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_mtp2type_abbrev(type)
8632478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int type;
8633478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
8634478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1;
8635478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8636478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (type) {
8637478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8638478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case M_FISU:
8639478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if ( (linktype != DLT_MTP2) &&
8640511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		     (linktype != DLT_ERF) &&
8641478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		     (linktype != DLT_MTP2_WITH_PHDR) )
8642478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'fisu' supported only on MTP2");
8643478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */
8644478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JEQ, 0, 0);
8645478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8646478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8647478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case M_LSSU:
8648478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if ( (linktype != DLT_MTP2) &&
8649511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		     (linktype != DLT_ERF) &&
8650478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		     (linktype != DLT_MTP2_WITH_PHDR) )
8651478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'lssu' supported only on MTP2");
8652478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 1, 2);
8653478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 0);
8654478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b1, b0);
8655478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8656478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8657478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case M_MSU:
8658478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if ( (linktype != DLT_MTP2) &&
8659511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		     (linktype != DLT_ERF) &&
8660478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		     (linktype != DLT_MTP2_WITH_PHDR) )
8661478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'msu' supported only on MTP2");
8662478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 2);
8663478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8664478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8665511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case MH_FISU:
8666511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if ( (linktype != DLT_MTP2) &&
8667511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		     (linktype != DLT_ERF) &&
8668511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		     (linktype != DLT_MTP2_WITH_PHDR) )
8669511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error("'hfisu' supported only on MTP2_HSL");
8670511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */
8671511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JEQ, 0, 0);
8672511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
8673511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
8674511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case MH_LSSU:
8675511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if ( (linktype != DLT_MTP2) &&
8676511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		     (linktype != DLT_ERF) &&
8677511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		     (linktype != DLT_MTP2_WITH_PHDR) )
8678511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error("'hlssu' supported only on MTP2_HSL");
8679511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 1, 0x0100);
8680511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b1 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0);
8681511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		gen_and(b1, b0);
8682511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
8683511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
8684511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case MH_MSU:
8685511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if ( (linktype != DLT_MTP2) &&
8686511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		     (linktype != DLT_ERF) &&
8687511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		     (linktype != DLT_MTP2_WITH_PHDR) )
8688511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bpf_error("'hmsu' supported only on MTP2_HSL");
8689511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0x0100);
8690511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
8691511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
8692478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
8693478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
8694478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
8695478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b0;
8696478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
8697478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8698478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
8699478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
8700478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int mtp3field;
8701478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 jvalue;
8702478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 jtype;
8703478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int reverse;
8704478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
8705478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0;
8706478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	bpf_u_int32 val1 , val2 , val3;
8707511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_int newoff_sio=off_sio;
8708511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_int newoff_opc=off_opc;
8709511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_int newoff_dpc=off_dpc;
8710511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_int newoff_sls=off_sls;
8711478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8712478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (mtp3field) {
8713478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8714511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case MH_SIO:
8715511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		newoff_sio += 3; /* offset for MTP2_HSL */
8716511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* FALLTHROUGH */
8717511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
8718478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case M_SIO:
8719478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (off_sio == (u_int)-1)
8720478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'sio' supported only on SS7");
8721478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* sio coded on 1 byte so max value 255 */
8722478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if(jvalue > 255)
8723478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		        bpf_error("sio value %u too big; max value = 255",
8724478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		            jvalue);
8725511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b0 = gen_ncmp(OR_PACKET, newoff_sio, BPF_B, 0xffffffff,
8726478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    (u_int)jtype, reverse, (u_int)jvalue);
8727478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8728478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8729511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case MH_OPC:
8730511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		newoff_opc+=3;
8731478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project        case M_OPC:
8732478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	        if (off_opc == (u_int)-1)
8733478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'opc' supported only on SS7");
8734478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* opc coded on 14 bits so max value 16383 */
8735478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (jvalue > 16383)
8736478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		        bpf_error("opc value %u too big; max value = 16383",
8737478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		            jvalue);
8738478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* the following instructions are made to convert jvalue
8739478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * to the form used to write opc in an ss7 message*/
8740478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		val1 = jvalue & 0x00003c00;
8741478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		val1 = val1 >>10;
8742478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		val2 = jvalue & 0x000003fc;
8743478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		val2 = val2 <<6;
8744478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		val3 = jvalue & 0x00000003;
8745478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		val3 = val3 <<22;
8746478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		jvalue = val1 + val2 + val3;
8747511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b0 = gen_ncmp(OR_PACKET, newoff_opc, BPF_W, 0x00c0ff0f,
8748478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    (u_int)jtype, reverse, (u_int)jvalue);
8749478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8750478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8751511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case MH_DPC:
8752511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		newoff_dpc += 3;
8753511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* FALLTHROUGH */
8754511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
8755478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case M_DPC:
8756478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	        if (off_dpc == (u_int)-1)
8757478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'dpc' supported only on SS7");
8758478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* dpc coded on 14 bits so max value 16383 */
8759478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (jvalue > 16383)
8760478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		        bpf_error("dpc value %u too big; max value = 16383",
8761478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		            jvalue);
8762478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* the following instructions are made to convert jvalue
8763478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * to the forme used to write dpc in an ss7 message*/
8764478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		val1 = jvalue & 0x000000ff;
8765478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		val1 = val1 << 24;
8766478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		val2 = jvalue & 0x00003f00;
8767478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		val2 = val2 << 8;
8768478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		jvalue = val1 + val2;
8769511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b0 = gen_ncmp(OR_PACKET, newoff_dpc, BPF_W, 0xff3f0000,
8770478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    (u_int)jtype, reverse, (u_int)jvalue);
8771478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8772478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8773511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case MH_SLS:
8774511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	  newoff_sls+=3;
8775478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case M_SLS:
8776478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	        if (off_sls == (u_int)-1)
8777478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'sls' supported only on SS7");
8778478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* sls coded on 4 bits so max value 15 */
8779478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (jvalue > 15)
8780478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		         bpf_error("sls value %u too big; max value = 15",
8781478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		             jvalue);
8782478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* the following instruction is made to convert jvalue
8783478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * to the forme used to write sls in an ss7 message*/
8784478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		jvalue = jvalue << 4;
8785511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		b0 = gen_ncmp(OR_PACKET, newoff_sls, BPF_B, 0xf0,
8786478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    (u_int)jtype,reverse, (u_int)jvalue);
8787478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8788478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8789478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
8790478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
8791478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
8792478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b0;
8793478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
8794478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8795478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct block *
8796478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_msg_abbrev(type)
8797478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int type;
8798478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
8799478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b1;
8800478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8801478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
8802478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * Q.2931 signalling protocol messages for handling virtual circuits
8803478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * establishment and teardown
8804478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
8805478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (type) {
8806478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8807478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_SETUP:
8808478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_atmfield_code(A_MSGTYPE, SETUP, BPF_JEQ, 0);
8809478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8810478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8811478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_CALLPROCEED:
8812478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
8813478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8814478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8815478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_CONNECT:
8816478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_atmfield_code(A_MSGTYPE, CONNECT, BPF_JEQ, 0);
8817478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8818478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8819478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_CONNECTACK:
8820478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
8821478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8822478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8823478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_RELEASE:
8824478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_atmfield_code(A_MSGTYPE, RELEASE, BPF_JEQ, 0);
8825478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8826478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8827478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_RELEASE_DONE:
8828478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
8829478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8830478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8831478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
8832478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
8833478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
8834478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b1;
8835478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
8836478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8837478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstruct block *
8838478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectgen_atmmulti_abbrev(type)
8839478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int type;
8840478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
8841478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct block *b0, *b1;
8842478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8843478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	switch (type) {
8844478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8845478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_OAM:
8846478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (!is_atm)
8847478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'oam' supported only on raw ATM");
8848478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_atmmulti_abbrev(A_OAMF4);
8849478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8850478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8851478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_OAMF4:
8852478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (!is_atm)
8853478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'oamf4' supported only on raw ATM");
8854478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/* OAM F4 type */
8855478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
8856478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0);
8857478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
8858478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8859478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
8860478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8861478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8862478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_CONNECTMSG:
8863478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
8864478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Get Q.2931 signalling messages for switched
8865478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * virtual connection
8866478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
8867478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (!is_atm)
8868478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'connectmsg' supported only on raw ATM");
8869478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_msg_abbrev(A_SETUP);
8870478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_msg_abbrev(A_CALLPROCEED);
8871478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
8872478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_msg_abbrev(A_CONNECT);
8873478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
8874478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_msg_abbrev(A_CONNECTACK);
8875478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
8876478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_msg_abbrev(A_RELEASE);
8877478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
8878478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_msg_abbrev(A_RELEASE_DONE);
8879478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
8880478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_atmtype_abbrev(A_SC);
8881478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
8882478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8883478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8884478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	case A_METACONNECT:
8885478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (!is_atm)
8886478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			bpf_error("'metaconnect' supported only on raw ATM");
8887478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_msg_abbrev(A_SETUP);
8888478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b1 = gen_msg_abbrev(A_CALLPROCEED);
8889478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
8890478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_msg_abbrev(A_CONNECT);
8891478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
8892478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_msg_abbrev(A_RELEASE);
8893478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
8894478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_msg_abbrev(A_RELEASE_DONE);
8895478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_or(b0, b1);
8896478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		b0 = gen_atmtype_abbrev(A_METAC);
8897478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		gen_and(b0, b1);
8898478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		break;
8899478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
8900478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	default:
8901478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		abort();
8902478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
8903478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return b1;
8904478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
8905