1*d56f51eaSDavid van Moolenbroek /* $NetBSD: gencode.c,v 1.8 2015/03/31 21:39:42 christos Exp $ */
2*d56f51eaSDavid van Moolenbroek
3*d56f51eaSDavid van Moolenbroek /*#define CHASE_CHAIN*/
4*d56f51eaSDavid van Moolenbroek /*
5*d56f51eaSDavid van Moolenbroek * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
6*d56f51eaSDavid van Moolenbroek * The Regents of the University of California. All rights reserved.
7*d56f51eaSDavid van Moolenbroek *
8*d56f51eaSDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
9*d56f51eaSDavid van Moolenbroek * modification, are permitted provided that: (1) source code distributions
10*d56f51eaSDavid van Moolenbroek * retain the above copyright notice and this paragraph in its entirety, (2)
11*d56f51eaSDavid van Moolenbroek * distributions including binary code include the above copyright notice and
12*d56f51eaSDavid van Moolenbroek * this paragraph in its entirety in the documentation or other materials
13*d56f51eaSDavid van Moolenbroek * provided with the distribution, and (3) all advertising materials mentioning
14*d56f51eaSDavid van Moolenbroek * features or use of this software display the following acknowledgement:
15*d56f51eaSDavid van Moolenbroek * ``This product includes software developed by the University of California,
16*d56f51eaSDavid van Moolenbroek * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
17*d56f51eaSDavid van Moolenbroek * the University nor the names of its contributors may be used to endorse
18*d56f51eaSDavid van Moolenbroek * or promote products derived from this software without specific prior
19*d56f51eaSDavid van Moolenbroek * written permission.
20*d56f51eaSDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
21*d56f51eaSDavid van Moolenbroek * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
22*d56f51eaSDavid van Moolenbroek * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23*d56f51eaSDavid van Moolenbroek */
24*d56f51eaSDavid van Moolenbroek
25*d56f51eaSDavid van Moolenbroek #include <sys/cdefs.h>
26*d56f51eaSDavid van Moolenbroek __RCSID("$NetBSD: gencode.c,v 1.8 2015/03/31 21:39:42 christos Exp $");
27*d56f51eaSDavid van Moolenbroek
28*d56f51eaSDavid van Moolenbroek #ifdef HAVE_CONFIG_H
29*d56f51eaSDavid van Moolenbroek #include "config.h"
30*d56f51eaSDavid van Moolenbroek #endif
31*d56f51eaSDavid van Moolenbroek
32*d56f51eaSDavid van Moolenbroek #ifdef WIN32
33*d56f51eaSDavid van Moolenbroek #include <pcap-stdinc.h>
34*d56f51eaSDavid van Moolenbroek #else /* WIN32 */
35*d56f51eaSDavid van Moolenbroek #if HAVE_INTTYPES_H
36*d56f51eaSDavid van Moolenbroek #include <inttypes.h>
37*d56f51eaSDavid van Moolenbroek #elif HAVE_STDINT_H
38*d56f51eaSDavid van Moolenbroek #include <stdint.h>
39*d56f51eaSDavid van Moolenbroek #endif
40*d56f51eaSDavid van Moolenbroek #ifdef HAVE_SYS_BITYPES_H
41*d56f51eaSDavid van Moolenbroek #include <sys/bitypes.h>
42*d56f51eaSDavid van Moolenbroek #endif
43*d56f51eaSDavid van Moolenbroek #include <sys/types.h>
44*d56f51eaSDavid van Moolenbroek #include <sys/socket.h>
45*d56f51eaSDavid van Moolenbroek #endif /* WIN32 */
46*d56f51eaSDavid van Moolenbroek
47*d56f51eaSDavid van Moolenbroek /*
48*d56f51eaSDavid van Moolenbroek * XXX - why was this included even on UNIX?
49*d56f51eaSDavid van Moolenbroek */
50*d56f51eaSDavid van Moolenbroek #ifdef __MINGW32__
51*d56f51eaSDavid van Moolenbroek #include "ip6_misc.h"
52*d56f51eaSDavid van Moolenbroek #endif
53*d56f51eaSDavid van Moolenbroek
54*d56f51eaSDavid van Moolenbroek #ifndef WIN32
55*d56f51eaSDavid van Moolenbroek
56*d56f51eaSDavid van Moolenbroek #ifdef __NetBSD__
57*d56f51eaSDavid van Moolenbroek #include <sys/param.h>
58*d56f51eaSDavid van Moolenbroek #include <net/dlt.h>
59*d56f51eaSDavid van Moolenbroek #endif
60*d56f51eaSDavid van Moolenbroek
61*d56f51eaSDavid van Moolenbroek #include <netinet/in.h>
62*d56f51eaSDavid van Moolenbroek #include <arpa/inet.h>
63*d56f51eaSDavid van Moolenbroek
64*d56f51eaSDavid van Moolenbroek #endif /* WIN32 */
65*d56f51eaSDavid van Moolenbroek
66*d56f51eaSDavid van Moolenbroek #include <stdlib.h>
67*d56f51eaSDavid van Moolenbroek #include <string.h>
68*d56f51eaSDavid van Moolenbroek #include <memory.h>
69*d56f51eaSDavid van Moolenbroek #include <setjmp.h>
70*d56f51eaSDavid van Moolenbroek #include <stdarg.h>
71*d56f51eaSDavid van Moolenbroek
72*d56f51eaSDavid van Moolenbroek #ifdef MSDOS
73*d56f51eaSDavid van Moolenbroek #include "pcap-dos.h"
74*d56f51eaSDavid van Moolenbroek #endif
75*d56f51eaSDavid van Moolenbroek
76*d56f51eaSDavid van Moolenbroek #include "pcap-int.h"
77*d56f51eaSDavid van Moolenbroek
78*d56f51eaSDavid van Moolenbroek #include "ethertype.h"
79*d56f51eaSDavid van Moolenbroek #include "nlpid.h"
80*d56f51eaSDavid van Moolenbroek #include "llc.h"
81*d56f51eaSDavid van Moolenbroek #include "gencode.h"
82*d56f51eaSDavid van Moolenbroek #include "ieee80211.h"
83*d56f51eaSDavid van Moolenbroek #include "atmuni31.h"
84*d56f51eaSDavid van Moolenbroek #include "sunatmpos.h"
85*d56f51eaSDavid van Moolenbroek #include "ppp.h"
86*d56f51eaSDavid van Moolenbroek #include "pcap/sll.h"
87*d56f51eaSDavid van Moolenbroek #include "pcap/ipnet.h"
88*d56f51eaSDavid van Moolenbroek #include "arcnet.h"
89*d56f51eaSDavid van Moolenbroek #if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
90*d56f51eaSDavid van Moolenbroek #include <linux/types.h>
91*d56f51eaSDavid van Moolenbroek #include <linux/if_packet.h>
92*d56f51eaSDavid van Moolenbroek #include <linux/filter.h>
93*d56f51eaSDavid van Moolenbroek #endif
94*d56f51eaSDavid van Moolenbroek #ifdef HAVE_NET_PFVAR_H
95*d56f51eaSDavid van Moolenbroek #include <sys/socket.h>
96*d56f51eaSDavid van Moolenbroek #include <net/if.h>
97*d56f51eaSDavid van Moolenbroek #include <net/pfvar.h>
98*d56f51eaSDavid van Moolenbroek #include <net/if_pflog.h>
99*d56f51eaSDavid van Moolenbroek #endif
100*d56f51eaSDavid van Moolenbroek #ifndef offsetof
101*d56f51eaSDavid van Moolenbroek #define offsetof(s, e) ((size_t)&((s *)0)->e)
102*d56f51eaSDavid van Moolenbroek #endif
103*d56f51eaSDavid van Moolenbroek #ifdef INET6
104*d56f51eaSDavid van Moolenbroek #ifndef WIN32
105*d56f51eaSDavid van Moolenbroek #include <netdb.h> /* for "struct addrinfo" */
106*d56f51eaSDavid van Moolenbroek #endif /* WIN32 */
107*d56f51eaSDavid van Moolenbroek #endif /*INET6*/
108*d56f51eaSDavid van Moolenbroek #include <pcap/namedb.h>
109*d56f51eaSDavid van Moolenbroek
110*d56f51eaSDavid van Moolenbroek #define ETHERMTU 1500
111*d56f51eaSDavid van Moolenbroek
112*d56f51eaSDavid van Moolenbroek #ifndef ETHERTYPE_TEB
113*d56f51eaSDavid van Moolenbroek #define ETHERTYPE_TEB 0x6558
114*d56f51eaSDavid van Moolenbroek #endif
115*d56f51eaSDavid van Moolenbroek
116*d56f51eaSDavid van Moolenbroek #ifndef IPPROTO_HOPOPTS
117*d56f51eaSDavid van Moolenbroek #define IPPROTO_HOPOPTS 0
118*d56f51eaSDavid van Moolenbroek #endif
119*d56f51eaSDavid van Moolenbroek #ifndef IPPROTO_ROUTING
120*d56f51eaSDavid van Moolenbroek #define IPPROTO_ROUTING 43
121*d56f51eaSDavid van Moolenbroek #endif
122*d56f51eaSDavid van Moolenbroek #ifndef IPPROTO_FRAGMENT
123*d56f51eaSDavid van Moolenbroek #define IPPROTO_FRAGMENT 44
124*d56f51eaSDavid van Moolenbroek #endif
125*d56f51eaSDavid van Moolenbroek #ifndef IPPROTO_DSTOPTS
126*d56f51eaSDavid van Moolenbroek #define IPPROTO_DSTOPTS 60
127*d56f51eaSDavid van Moolenbroek #endif
128*d56f51eaSDavid van Moolenbroek #ifndef IPPROTO_SCTP
129*d56f51eaSDavid van Moolenbroek #define IPPROTO_SCTP 132
130*d56f51eaSDavid van Moolenbroek #endif
131*d56f51eaSDavid van Moolenbroek
132*d56f51eaSDavid van Moolenbroek #define GENEVE_PORT 6081
133*d56f51eaSDavid van Moolenbroek
134*d56f51eaSDavid van Moolenbroek #ifdef HAVE_OS_PROTO_H
135*d56f51eaSDavid van Moolenbroek #include "os-proto.h"
136*d56f51eaSDavid van Moolenbroek #endif
137*d56f51eaSDavid van Moolenbroek
138*d56f51eaSDavid van Moolenbroek #define JMP(c) ((c)|BPF_JMP|BPF_K)
139*d56f51eaSDavid van Moolenbroek
140*d56f51eaSDavid van Moolenbroek /* Locals */
141*d56f51eaSDavid van Moolenbroek static jmp_buf top_ctx;
142*d56f51eaSDavid van Moolenbroek static pcap_t *bpf_pcap;
143*d56f51eaSDavid van Moolenbroek
144*d56f51eaSDavid van Moolenbroek /* Hack for handling VLAN and MPLS stacks. */
145*d56f51eaSDavid van Moolenbroek #ifdef WIN32
146*d56f51eaSDavid van Moolenbroek static u_int label_stack_depth = (u_int)-1, vlan_stack_depth = (u_int)-1;
147*d56f51eaSDavid van Moolenbroek #else
148*d56f51eaSDavid van Moolenbroek static u_int label_stack_depth = -1U, vlan_stack_depth = -1U;
149*d56f51eaSDavid van Moolenbroek #endif
150*d56f51eaSDavid van Moolenbroek
151*d56f51eaSDavid van Moolenbroek /* XXX */
152*d56f51eaSDavid van Moolenbroek static int pcap_fddipad;
153*d56f51eaSDavid van Moolenbroek
154*d56f51eaSDavid van Moolenbroek /* VARARGS */
155*d56f51eaSDavid van Moolenbroek void
bpf_error(const char * fmt,...)156*d56f51eaSDavid van Moolenbroek bpf_error(const char *fmt, ...)
157*d56f51eaSDavid van Moolenbroek {
158*d56f51eaSDavid van Moolenbroek va_list ap;
159*d56f51eaSDavid van Moolenbroek
160*d56f51eaSDavid van Moolenbroek va_start(ap, fmt);
161*d56f51eaSDavid van Moolenbroek if (bpf_pcap != NULL)
162*d56f51eaSDavid van Moolenbroek (void)vsnprintf(pcap_geterr(bpf_pcap), PCAP_ERRBUF_SIZE,
163*d56f51eaSDavid van Moolenbroek fmt, ap);
164*d56f51eaSDavid van Moolenbroek va_end(ap);
165*d56f51eaSDavid van Moolenbroek longjmp(top_ctx, 1);
166*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
167*d56f51eaSDavid van Moolenbroek }
168*d56f51eaSDavid van Moolenbroek
169*d56f51eaSDavid van Moolenbroek static void init_linktype(pcap_t *);
170*d56f51eaSDavid van Moolenbroek
171*d56f51eaSDavid van Moolenbroek static void init_regs(void);
172*d56f51eaSDavid van Moolenbroek static int alloc_reg(void);
173*d56f51eaSDavid van Moolenbroek static void free_reg(int);
174*d56f51eaSDavid van Moolenbroek
175*d56f51eaSDavid van Moolenbroek static struct block *root;
176*d56f51eaSDavid van Moolenbroek
177*d56f51eaSDavid van Moolenbroek /*
178*d56f51eaSDavid van Moolenbroek * Absolute offsets, which are offsets from the beginning of the raw
179*d56f51eaSDavid van Moolenbroek * packet data, are, in the general case, the sum of a variable value
180*d56f51eaSDavid van Moolenbroek * and a constant value; the variable value may be absent, in which
181*d56f51eaSDavid van Moolenbroek * case the offset is only the constant value, and the constant value
182*d56f51eaSDavid van Moolenbroek * may be zero, in which case the offset is only the variable value.
183*d56f51eaSDavid van Moolenbroek *
184*d56f51eaSDavid van Moolenbroek * bpf_abs_offset is a structure containing all that information:
185*d56f51eaSDavid van Moolenbroek *
186*d56f51eaSDavid van Moolenbroek * is_variable is 1 if there's a variable part.
187*d56f51eaSDavid van Moolenbroek *
188*d56f51eaSDavid van Moolenbroek * constant_part is the constant part of the value, possibly zero;
189*d56f51eaSDavid van Moolenbroek *
190*d56f51eaSDavid van Moolenbroek * if is_variable is 1, reg is the register number for a register
191*d56f51eaSDavid van Moolenbroek * containing the variable value if the register has been assigned,
192*d56f51eaSDavid van Moolenbroek * and -1 otherwise.
193*d56f51eaSDavid van Moolenbroek */
194*d56f51eaSDavid van Moolenbroek typedef struct {
195*d56f51eaSDavid van Moolenbroek int is_variable;
196*d56f51eaSDavid van Moolenbroek u_int constant_part;
197*d56f51eaSDavid van Moolenbroek int reg;
198*d56f51eaSDavid van Moolenbroek } bpf_abs_offset;
199*d56f51eaSDavid van Moolenbroek
200*d56f51eaSDavid van Moolenbroek /*
201*d56f51eaSDavid van Moolenbroek * Value passed to gen_load_a() to indicate what the offset argument
202*d56f51eaSDavid van Moolenbroek * is relative to the beginning of.
203*d56f51eaSDavid van Moolenbroek */
204*d56f51eaSDavid van Moolenbroek enum e_offrel {
205*d56f51eaSDavid van Moolenbroek OR_PACKET, /* full packet data */
206*d56f51eaSDavid van Moolenbroek OR_LINKHDR, /* link-layer header */
207*d56f51eaSDavid van Moolenbroek OR_PREVLINKHDR, /* previous link-layer header */
208*d56f51eaSDavid van Moolenbroek OR_LLC, /* 802.2 LLC header */
209*d56f51eaSDavid van Moolenbroek OR_PREVMPLSHDR, /* previous MPLS header */
210*d56f51eaSDavid van Moolenbroek OR_LINKTYPE, /* link-layer type */
211*d56f51eaSDavid van Moolenbroek OR_LINKPL, /* link-layer payload */
212*d56f51eaSDavid van Moolenbroek OR_LINKPL_NOSNAP, /* link-layer payload, with no SNAP header at the link layer */
213*d56f51eaSDavid van Moolenbroek OR_TRAN_IPV4, /* transport-layer header, with IPv4 network layer */
214*d56f51eaSDavid van Moolenbroek OR_TRAN_IPV6 /* transport-layer header, with IPv6 network layer */
215*d56f51eaSDavid van Moolenbroek };
216*d56f51eaSDavid van Moolenbroek
217*d56f51eaSDavid van Moolenbroek #ifdef INET6
218*d56f51eaSDavid van Moolenbroek /*
219*d56f51eaSDavid van Moolenbroek * As errors are handled by a longjmp, anything allocated must be freed
220*d56f51eaSDavid van Moolenbroek * in the longjmp handler, so it must be reachable from that handler.
221*d56f51eaSDavid van Moolenbroek * One thing that's allocated is the result of pcap_nametoaddrinfo();
222*d56f51eaSDavid van Moolenbroek * it must be freed with freeaddrinfo(). This variable points to any
223*d56f51eaSDavid van Moolenbroek * addrinfo structure that would need to be freed.
224*d56f51eaSDavid van Moolenbroek */
225*d56f51eaSDavid van Moolenbroek static struct addrinfo *ai;
226*d56f51eaSDavid van Moolenbroek #endif
227*d56f51eaSDavid van Moolenbroek
228*d56f51eaSDavid van Moolenbroek /*
229*d56f51eaSDavid van Moolenbroek * We divy out chunks of memory rather than call malloc each time so
230*d56f51eaSDavid van Moolenbroek * we don't have to worry about leaking memory. It's probably
231*d56f51eaSDavid van Moolenbroek * not a big deal if all this memory was wasted but if this ever
232*d56f51eaSDavid van Moolenbroek * goes into a library that would probably not be a good idea.
233*d56f51eaSDavid van Moolenbroek *
234*d56f51eaSDavid van Moolenbroek * XXX - this *is* in a library....
235*d56f51eaSDavid van Moolenbroek */
236*d56f51eaSDavid van Moolenbroek #define NCHUNKS 16
237*d56f51eaSDavid van Moolenbroek #define CHUNK0SIZE 1024
238*d56f51eaSDavid van Moolenbroek struct chunk {
239*d56f51eaSDavid van Moolenbroek u_int n_left;
240*d56f51eaSDavid van Moolenbroek void *m;
241*d56f51eaSDavid van Moolenbroek };
242*d56f51eaSDavid van Moolenbroek
243*d56f51eaSDavid van Moolenbroek static struct chunk chunks[NCHUNKS];
244*d56f51eaSDavid van Moolenbroek static int cur_chunk;
245*d56f51eaSDavid van Moolenbroek
246*d56f51eaSDavid van Moolenbroek static void *newchunk(u_int);
247*d56f51eaSDavid van Moolenbroek static void freechunks(void);
248*d56f51eaSDavid van Moolenbroek static inline struct block *new_block(int);
249*d56f51eaSDavid van Moolenbroek static inline struct slist *new_stmt(int);
250*d56f51eaSDavid van Moolenbroek static struct block *gen_retblk(int);
251*d56f51eaSDavid van Moolenbroek static inline void syntax(void);
252*d56f51eaSDavid van Moolenbroek
253*d56f51eaSDavid van Moolenbroek static void backpatch(struct block *, struct block *);
254*d56f51eaSDavid van Moolenbroek static void merge(struct block *, struct block *);
255*d56f51eaSDavid van Moolenbroek static struct block *gen_cmp(enum e_offrel, u_int, u_int, bpf_int32);
256*d56f51eaSDavid van Moolenbroek static struct block *gen_cmp_gt(enum e_offrel, u_int, u_int, bpf_int32);
257*d56f51eaSDavid van Moolenbroek static struct block *gen_cmp_ge(enum e_offrel, u_int, u_int, bpf_int32);
258*d56f51eaSDavid van Moolenbroek static struct block *gen_cmp_lt(enum e_offrel, u_int, u_int, bpf_int32);
259*d56f51eaSDavid van Moolenbroek static struct block *gen_cmp_le(enum e_offrel, u_int, u_int, bpf_int32);
260*d56f51eaSDavid van Moolenbroek static struct block *gen_mcmp(enum e_offrel, u_int, u_int, bpf_int32,
261*d56f51eaSDavid van Moolenbroek bpf_u_int32);
262*d56f51eaSDavid van Moolenbroek static struct block *gen_bcmp(enum e_offrel, u_int, u_int, const u_char *);
263*d56f51eaSDavid van Moolenbroek static struct block *gen_ncmp(enum e_offrel, bpf_u_int32, bpf_u_int32,
264*d56f51eaSDavid van Moolenbroek bpf_u_int32, bpf_u_int32, int, bpf_int32);
265*d56f51eaSDavid van Moolenbroek static struct slist *gen_load_absoffsetrel(bpf_abs_offset *, u_int, u_int);
266*d56f51eaSDavid van Moolenbroek static struct slist *gen_load_a(enum e_offrel, u_int, u_int);
267*d56f51eaSDavid van Moolenbroek static struct slist *gen_loadx_iphdrlen(void);
268*d56f51eaSDavid van Moolenbroek static struct block *gen_uncond(int);
269*d56f51eaSDavid van Moolenbroek static inline struct block *gen_true(void);
270*d56f51eaSDavid van Moolenbroek static inline struct block *gen_false(void);
271*d56f51eaSDavid van Moolenbroek static struct block *gen_ether_linktype(int);
272*d56f51eaSDavid van Moolenbroek static struct block *gen_ipnet_linktype(int);
273*d56f51eaSDavid van Moolenbroek static struct block *gen_linux_sll_linktype(int);
274*d56f51eaSDavid van Moolenbroek static struct slist *gen_load_prism_llprefixlen(void);
275*d56f51eaSDavid van Moolenbroek static struct slist *gen_load_avs_llprefixlen(void);
276*d56f51eaSDavid van Moolenbroek static struct slist *gen_load_radiotap_llprefixlen(void);
277*d56f51eaSDavid van Moolenbroek static struct slist *gen_load_ppi_llprefixlen(void);
278*d56f51eaSDavid van Moolenbroek static void insert_compute_vloffsets(struct block *);
279*d56f51eaSDavid van Moolenbroek static struct slist *gen_abs_offset_varpart(bpf_abs_offset *);
280*d56f51eaSDavid van Moolenbroek static int ethertype_to_ppptype(int);
281*d56f51eaSDavid van Moolenbroek static struct block *gen_linktype(int);
282*d56f51eaSDavid van Moolenbroek static struct block *gen_snap(bpf_u_int32, bpf_u_int32);
283*d56f51eaSDavid van Moolenbroek static struct block *gen_llc_linktype(int);
284*d56f51eaSDavid van Moolenbroek static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int);
285*d56f51eaSDavid van Moolenbroek #ifdef INET6
286*d56f51eaSDavid van Moolenbroek static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int);
287*d56f51eaSDavid van Moolenbroek #endif
288*d56f51eaSDavid van Moolenbroek static struct block *gen_ahostop(const u_char *, int);
289*d56f51eaSDavid van Moolenbroek static struct block *gen_ehostop(const u_char *, int);
290*d56f51eaSDavid van Moolenbroek static struct block *gen_fhostop(const u_char *, int);
291*d56f51eaSDavid van Moolenbroek static struct block *gen_thostop(const u_char *, int);
292*d56f51eaSDavid van Moolenbroek static struct block *gen_wlanhostop(const u_char *, int);
293*d56f51eaSDavid van Moolenbroek static struct block *gen_ipfchostop(const u_char *, int);
294*d56f51eaSDavid van Moolenbroek static struct block *gen_dnhostop(bpf_u_int32, int);
295*d56f51eaSDavid van Moolenbroek static struct block *gen_mpls_linktype(int);
296*d56f51eaSDavid van Moolenbroek static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int, int);
297*d56f51eaSDavid van Moolenbroek #ifdef INET6
298*d56f51eaSDavid van Moolenbroek static struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int, int);
299*d56f51eaSDavid van Moolenbroek #endif
300*d56f51eaSDavid van Moolenbroek #ifndef INET6
301*d56f51eaSDavid van Moolenbroek static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);
302*d56f51eaSDavid van Moolenbroek #endif
303*d56f51eaSDavid van Moolenbroek static struct block *gen_ipfrag(void);
304*d56f51eaSDavid van Moolenbroek static struct block *gen_portatom(int, bpf_int32);
305*d56f51eaSDavid van Moolenbroek static struct block *gen_portrangeatom(int, bpf_int32, bpf_int32);
306*d56f51eaSDavid van Moolenbroek static struct block *gen_portatom6(int, bpf_int32);
307*d56f51eaSDavid van Moolenbroek static struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32);
308*d56f51eaSDavid van Moolenbroek struct block *gen_portop(int, int, int);
309*d56f51eaSDavid van Moolenbroek static struct block *gen_port(int, int, int);
310*d56f51eaSDavid van Moolenbroek struct block *gen_portrangeop(int, int, int, int);
311*d56f51eaSDavid van Moolenbroek static struct block *gen_portrange(int, int, int, int);
312*d56f51eaSDavid van Moolenbroek struct block *gen_portop6(int, int, int);
313*d56f51eaSDavid van Moolenbroek static struct block *gen_port6(int, int, int);
314*d56f51eaSDavid van Moolenbroek struct block *gen_portrangeop6(int, int, int, int);
315*d56f51eaSDavid van Moolenbroek static struct block *gen_portrange6(int, int, int, int);
316*d56f51eaSDavid van Moolenbroek static int lookup_proto(const char *, int);
317*d56f51eaSDavid van Moolenbroek static struct block *gen_protochain(int, int, int);
318*d56f51eaSDavid van Moolenbroek static struct block *gen_proto(int, int, int);
319*d56f51eaSDavid van Moolenbroek static struct slist *xfer_to_x(struct arth *);
320*d56f51eaSDavid van Moolenbroek static struct slist *xfer_to_a(struct arth *);
321*d56f51eaSDavid van Moolenbroek static struct block *gen_mac_multicast(int);
322*d56f51eaSDavid van Moolenbroek static struct block *gen_len(int, int);
323*d56f51eaSDavid van Moolenbroek static struct block *gen_check_802_11_data_frame(void);
324*d56f51eaSDavid van Moolenbroek static struct block *gen_geneve_ll_check(void);
325*d56f51eaSDavid van Moolenbroek
326*d56f51eaSDavid van Moolenbroek static struct block *gen_ppi_dlt_check(void);
327*d56f51eaSDavid van Moolenbroek static struct block *gen_msg_abbrev(int type);
328*d56f51eaSDavid van Moolenbroek
329*d56f51eaSDavid van Moolenbroek static void *
newchunk(n)330*d56f51eaSDavid van Moolenbroek newchunk(n)
331*d56f51eaSDavid van Moolenbroek u_int n;
332*d56f51eaSDavid van Moolenbroek {
333*d56f51eaSDavid van Moolenbroek struct chunk *cp;
334*d56f51eaSDavid van Moolenbroek int k;
335*d56f51eaSDavid van Moolenbroek size_t size;
336*d56f51eaSDavid van Moolenbroek
337*d56f51eaSDavid van Moolenbroek #ifndef __NetBSD__
338*d56f51eaSDavid van Moolenbroek /* XXX Round up to nearest long. */
339*d56f51eaSDavid van Moolenbroek n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);
340*d56f51eaSDavid van Moolenbroek #else
341*d56f51eaSDavid van Moolenbroek /* XXX Round up to structure boundary. */
342*d56f51eaSDavid van Moolenbroek n = ALIGN(n);
343*d56f51eaSDavid van Moolenbroek #endif
344*d56f51eaSDavid van Moolenbroek
345*d56f51eaSDavid van Moolenbroek cp = &chunks[cur_chunk];
346*d56f51eaSDavid van Moolenbroek if (n > cp->n_left) {
347*d56f51eaSDavid van Moolenbroek ++cp, k = ++cur_chunk;
348*d56f51eaSDavid van Moolenbroek if (k >= NCHUNKS)
349*d56f51eaSDavid van Moolenbroek bpf_error("out of memory");
350*d56f51eaSDavid van Moolenbroek size = CHUNK0SIZE << k;
351*d56f51eaSDavid van Moolenbroek cp->m = (void *)malloc(size);
352*d56f51eaSDavid van Moolenbroek if (cp->m == NULL)
353*d56f51eaSDavid van Moolenbroek bpf_error("out of memory");
354*d56f51eaSDavid van Moolenbroek memset((char *)cp->m, 0, size);
355*d56f51eaSDavid van Moolenbroek cp->n_left = size;
356*d56f51eaSDavid van Moolenbroek if (n > size)
357*d56f51eaSDavid van Moolenbroek bpf_error("out of memory");
358*d56f51eaSDavid van Moolenbroek }
359*d56f51eaSDavid van Moolenbroek cp->n_left -= n;
360*d56f51eaSDavid van Moolenbroek return (void *)((char *)cp->m + cp->n_left);
361*d56f51eaSDavid van Moolenbroek }
362*d56f51eaSDavid van Moolenbroek
363*d56f51eaSDavid van Moolenbroek static void
freechunks()364*d56f51eaSDavid van Moolenbroek freechunks()
365*d56f51eaSDavid van Moolenbroek {
366*d56f51eaSDavid van Moolenbroek int i;
367*d56f51eaSDavid van Moolenbroek
368*d56f51eaSDavid van Moolenbroek cur_chunk = 0;
369*d56f51eaSDavid van Moolenbroek for (i = 0; i < NCHUNKS; ++i)
370*d56f51eaSDavid van Moolenbroek if (chunks[i].m != NULL) {
371*d56f51eaSDavid van Moolenbroek free(chunks[i].m);
372*d56f51eaSDavid van Moolenbroek chunks[i].m = NULL;
373*d56f51eaSDavid van Moolenbroek }
374*d56f51eaSDavid van Moolenbroek }
375*d56f51eaSDavid van Moolenbroek
376*d56f51eaSDavid van Moolenbroek /*
377*d56f51eaSDavid van Moolenbroek * A strdup whose allocations are freed after code generation is over.
378*d56f51eaSDavid van Moolenbroek */
379*d56f51eaSDavid van Moolenbroek char *
sdup(s)380*d56f51eaSDavid van Moolenbroek sdup(s)
381*d56f51eaSDavid van Moolenbroek register const char *s;
382*d56f51eaSDavid van Moolenbroek {
383*d56f51eaSDavid van Moolenbroek int n = strlen(s) + 1;
384*d56f51eaSDavid van Moolenbroek char *cp = newchunk(n);
385*d56f51eaSDavid van Moolenbroek
386*d56f51eaSDavid van Moolenbroek strlcpy(cp, s, n);
387*d56f51eaSDavid van Moolenbroek return (cp);
388*d56f51eaSDavid van Moolenbroek }
389*d56f51eaSDavid van Moolenbroek
390*d56f51eaSDavid van Moolenbroek static inline struct block *
new_block(code)391*d56f51eaSDavid van Moolenbroek new_block(code)
392*d56f51eaSDavid van Moolenbroek int code;
393*d56f51eaSDavid van Moolenbroek {
394*d56f51eaSDavid van Moolenbroek struct block *p;
395*d56f51eaSDavid van Moolenbroek
396*d56f51eaSDavid van Moolenbroek p = (struct block *)newchunk(sizeof(*p));
397*d56f51eaSDavid van Moolenbroek p->s.code = code;
398*d56f51eaSDavid van Moolenbroek p->head = p;
399*d56f51eaSDavid van Moolenbroek
400*d56f51eaSDavid van Moolenbroek return p;
401*d56f51eaSDavid van Moolenbroek }
402*d56f51eaSDavid van Moolenbroek
403*d56f51eaSDavid van Moolenbroek static inline struct slist *
new_stmt(code)404*d56f51eaSDavid van Moolenbroek new_stmt(code)
405*d56f51eaSDavid van Moolenbroek int code;
406*d56f51eaSDavid van Moolenbroek {
407*d56f51eaSDavid van Moolenbroek struct slist *p;
408*d56f51eaSDavid van Moolenbroek
409*d56f51eaSDavid van Moolenbroek p = (struct slist *)newchunk(sizeof(*p));
410*d56f51eaSDavid van Moolenbroek p->s.code = code;
411*d56f51eaSDavid van Moolenbroek
412*d56f51eaSDavid van Moolenbroek return p;
413*d56f51eaSDavid van Moolenbroek }
414*d56f51eaSDavid van Moolenbroek
415*d56f51eaSDavid van Moolenbroek static struct block *
gen_retblk(v)416*d56f51eaSDavid van Moolenbroek gen_retblk(v)
417*d56f51eaSDavid van Moolenbroek int v;
418*d56f51eaSDavid van Moolenbroek {
419*d56f51eaSDavid van Moolenbroek struct block *b = new_block(BPF_RET|BPF_K);
420*d56f51eaSDavid van Moolenbroek
421*d56f51eaSDavid van Moolenbroek b->s.k = v;
422*d56f51eaSDavid van Moolenbroek return b;
423*d56f51eaSDavid van Moolenbroek }
424*d56f51eaSDavid van Moolenbroek
425*d56f51eaSDavid van Moolenbroek __dead static inline void
syntax(void)426*d56f51eaSDavid van Moolenbroek syntax(void)
427*d56f51eaSDavid van Moolenbroek {
428*d56f51eaSDavid van Moolenbroek bpf_error("syntax error in filter expression");
429*d56f51eaSDavid van Moolenbroek }
430*d56f51eaSDavid van Moolenbroek
431*d56f51eaSDavid van Moolenbroek static bpf_u_int32 netmask;
432*d56f51eaSDavid van Moolenbroek static int snaplen;
433*d56f51eaSDavid van Moolenbroek int no_optimize;
434*d56f51eaSDavid van Moolenbroek
435*d56f51eaSDavid van Moolenbroek int
pcap_compile(pcap_t * p,struct bpf_program * program,const char * buf,int optimize,bpf_u_int32 mask)436*d56f51eaSDavid van Moolenbroek pcap_compile(pcap_t *p, struct bpf_program *program,
437*d56f51eaSDavid van Moolenbroek const char *buf, int optimize, bpf_u_int32 mask)
438*d56f51eaSDavid van Moolenbroek {
439*d56f51eaSDavid van Moolenbroek extern int n_errors;
440*d56f51eaSDavid van Moolenbroek const char * volatile xbuf = buf;
441*d56f51eaSDavid van Moolenbroek u_int len;
442*d56f51eaSDavid van Moolenbroek int rc;
443*d56f51eaSDavid van Moolenbroek
444*d56f51eaSDavid van Moolenbroek /*
445*d56f51eaSDavid van Moolenbroek * XXX - single-thread this code path with pthread calls on
446*d56f51eaSDavid van Moolenbroek * UN*X, if the platform supports pthreads? If that requires
447*d56f51eaSDavid van Moolenbroek * a separate -lpthread, we might not want to do that.
448*d56f51eaSDavid van Moolenbroek */
449*d56f51eaSDavid van Moolenbroek #ifdef WIN32
450*d56f51eaSDavid van Moolenbroek extern int wsockinit (void);
451*d56f51eaSDavid van Moolenbroek static int done = 0;
452*d56f51eaSDavid van Moolenbroek
453*d56f51eaSDavid van Moolenbroek if (!done)
454*d56f51eaSDavid van Moolenbroek wsockinit();
455*d56f51eaSDavid van Moolenbroek done = 1;
456*d56f51eaSDavid van Moolenbroek EnterCriticalSection(&g_PcapCompileCriticalSection);
457*d56f51eaSDavid van Moolenbroek #endif
458*d56f51eaSDavid van Moolenbroek
459*d56f51eaSDavid van Moolenbroek /*
460*d56f51eaSDavid van Moolenbroek * If this pcap_t hasn't been activated, it doesn't have a
461*d56f51eaSDavid van Moolenbroek * link-layer type, so we can't use it.
462*d56f51eaSDavid van Moolenbroek */
463*d56f51eaSDavid van Moolenbroek if (!p->activated) {
464*d56f51eaSDavid van Moolenbroek snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
465*d56f51eaSDavid van Moolenbroek "not-yet-activated pcap_t passed to pcap_compile");
466*d56f51eaSDavid van Moolenbroek rc = -1;
467*d56f51eaSDavid van Moolenbroek goto quit;
468*d56f51eaSDavid van Moolenbroek }
469*d56f51eaSDavid van Moolenbroek no_optimize = 0;
470*d56f51eaSDavid van Moolenbroek n_errors = 0;
471*d56f51eaSDavid van Moolenbroek root = NULL;
472*d56f51eaSDavid van Moolenbroek bpf_pcap = p;
473*d56f51eaSDavid van Moolenbroek init_regs();
474*d56f51eaSDavid van Moolenbroek
475*d56f51eaSDavid van Moolenbroek if (setjmp(top_ctx)) {
476*d56f51eaSDavid van Moolenbroek #ifdef INET6
477*d56f51eaSDavid van Moolenbroek if (ai != NULL) {
478*d56f51eaSDavid van Moolenbroek freeaddrinfo(ai);
479*d56f51eaSDavid van Moolenbroek ai = NULL;
480*d56f51eaSDavid van Moolenbroek }
481*d56f51eaSDavid van Moolenbroek #endif
482*d56f51eaSDavid van Moolenbroek lex_cleanup();
483*d56f51eaSDavid van Moolenbroek freechunks();
484*d56f51eaSDavid van Moolenbroek rc = -1;
485*d56f51eaSDavid van Moolenbroek goto quit;
486*d56f51eaSDavid van Moolenbroek }
487*d56f51eaSDavid van Moolenbroek
488*d56f51eaSDavid van Moolenbroek netmask = mask;
489*d56f51eaSDavid van Moolenbroek
490*d56f51eaSDavid van Moolenbroek snaplen = pcap_snapshot(p);
491*d56f51eaSDavid van Moolenbroek if (snaplen == 0) {
492*d56f51eaSDavid van Moolenbroek snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
493*d56f51eaSDavid van Moolenbroek "snaplen of 0 rejects all packets");
494*d56f51eaSDavid van Moolenbroek rc = -1;
495*d56f51eaSDavid van Moolenbroek goto quit;
496*d56f51eaSDavid van Moolenbroek }
497*d56f51eaSDavid van Moolenbroek
498*d56f51eaSDavid van Moolenbroek lex_init(xbuf ? xbuf : "");
499*d56f51eaSDavid van Moolenbroek init_linktype(p);
500*d56f51eaSDavid van Moolenbroek (void)pcap_parse();
501*d56f51eaSDavid van Moolenbroek
502*d56f51eaSDavid van Moolenbroek if (n_errors)
503*d56f51eaSDavid van Moolenbroek syntax();
504*d56f51eaSDavid van Moolenbroek
505*d56f51eaSDavid van Moolenbroek if (root == NULL)
506*d56f51eaSDavid van Moolenbroek root = gen_retblk(snaplen);
507*d56f51eaSDavid van Moolenbroek
508*d56f51eaSDavid van Moolenbroek if (optimize && !no_optimize) {
509*d56f51eaSDavid van Moolenbroek bpf_optimize(&root);
510*d56f51eaSDavid van Moolenbroek if (root == NULL ||
511*d56f51eaSDavid van Moolenbroek (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0))
512*d56f51eaSDavid van Moolenbroek bpf_error("expression rejects all packets");
513*d56f51eaSDavid van Moolenbroek }
514*d56f51eaSDavid van Moolenbroek program->bf_insns = icode_to_fcode(root, &len);
515*d56f51eaSDavid van Moolenbroek program->bf_len = len;
516*d56f51eaSDavid van Moolenbroek
517*d56f51eaSDavid van Moolenbroek lex_cleanup();
518*d56f51eaSDavid van Moolenbroek freechunks();
519*d56f51eaSDavid van Moolenbroek
520*d56f51eaSDavid van Moolenbroek rc = 0; /* We're all okay */
521*d56f51eaSDavid van Moolenbroek
522*d56f51eaSDavid van Moolenbroek quit:
523*d56f51eaSDavid van Moolenbroek
524*d56f51eaSDavid van Moolenbroek #ifdef WIN32
525*d56f51eaSDavid van Moolenbroek LeaveCriticalSection(&g_PcapCompileCriticalSection);
526*d56f51eaSDavid van Moolenbroek #endif
527*d56f51eaSDavid van Moolenbroek
528*d56f51eaSDavid van Moolenbroek return (rc);
529*d56f51eaSDavid van Moolenbroek }
530*d56f51eaSDavid van Moolenbroek
531*d56f51eaSDavid van Moolenbroek /*
532*d56f51eaSDavid van Moolenbroek * entry point for using the compiler with no pcap open
533*d56f51eaSDavid van Moolenbroek * pass in all the stuff that is needed explicitly instead.
534*d56f51eaSDavid van Moolenbroek */
535*d56f51eaSDavid van Moolenbroek int
pcap_compile_nopcap(int snaplen_arg,int linktype_arg,struct bpf_program * program,const char * buf,int optimize,bpf_u_int32 mask)536*d56f51eaSDavid van Moolenbroek pcap_compile_nopcap(int snaplen_arg, int linktype_arg,
537*d56f51eaSDavid van Moolenbroek struct bpf_program *program,
538*d56f51eaSDavid van Moolenbroek const char *buf, int optimize, bpf_u_int32 mask)
539*d56f51eaSDavid van Moolenbroek {
540*d56f51eaSDavid van Moolenbroek pcap_t *p;
541*d56f51eaSDavid van Moolenbroek int ret;
542*d56f51eaSDavid van Moolenbroek
543*d56f51eaSDavid van Moolenbroek p = pcap_open_dead(linktype_arg, snaplen_arg);
544*d56f51eaSDavid van Moolenbroek if (p == NULL)
545*d56f51eaSDavid van Moolenbroek return (-1);
546*d56f51eaSDavid van Moolenbroek ret = pcap_compile(p, program, buf, optimize, mask);
547*d56f51eaSDavid van Moolenbroek pcap_close(p);
548*d56f51eaSDavid van Moolenbroek return (ret);
549*d56f51eaSDavid van Moolenbroek }
550*d56f51eaSDavid van Moolenbroek
551*d56f51eaSDavid van Moolenbroek /*
552*d56f51eaSDavid van Moolenbroek * Clean up a "struct bpf_program" by freeing all the memory allocated
553*d56f51eaSDavid van Moolenbroek * in it.
554*d56f51eaSDavid van Moolenbroek */
555*d56f51eaSDavid van Moolenbroek void
pcap_freecode(struct bpf_program * program)556*d56f51eaSDavid van Moolenbroek pcap_freecode(struct bpf_program *program)
557*d56f51eaSDavid van Moolenbroek {
558*d56f51eaSDavid van Moolenbroek program->bf_len = 0;
559*d56f51eaSDavid van Moolenbroek if (program->bf_insns != NULL) {
560*d56f51eaSDavid van Moolenbroek free((char *)program->bf_insns);
561*d56f51eaSDavid van Moolenbroek program->bf_insns = NULL;
562*d56f51eaSDavid van Moolenbroek }
563*d56f51eaSDavid van Moolenbroek }
564*d56f51eaSDavid van Moolenbroek
565*d56f51eaSDavid van Moolenbroek /*
566*d56f51eaSDavid van Moolenbroek * Backpatch the blocks in 'list' to 'target'. The 'sense' field indicates
567*d56f51eaSDavid van Moolenbroek * which of the jt and jf fields has been resolved and which is a pointer
568*d56f51eaSDavid van Moolenbroek * back to another unresolved block (or nil). At least one of the fields
569*d56f51eaSDavid van Moolenbroek * in each block is already resolved.
570*d56f51eaSDavid van Moolenbroek */
571*d56f51eaSDavid van Moolenbroek static void
backpatch(list,target)572*d56f51eaSDavid van Moolenbroek backpatch(list, target)
573*d56f51eaSDavid van Moolenbroek struct block *list, *target;
574*d56f51eaSDavid van Moolenbroek {
575*d56f51eaSDavid van Moolenbroek struct block *next;
576*d56f51eaSDavid van Moolenbroek
577*d56f51eaSDavid van Moolenbroek while (list) {
578*d56f51eaSDavid van Moolenbroek if (!list->sense) {
579*d56f51eaSDavid van Moolenbroek next = JT(list);
580*d56f51eaSDavid van Moolenbroek JT(list) = target;
581*d56f51eaSDavid van Moolenbroek } else {
582*d56f51eaSDavid van Moolenbroek next = JF(list);
583*d56f51eaSDavid van Moolenbroek JF(list) = target;
584*d56f51eaSDavid van Moolenbroek }
585*d56f51eaSDavid van Moolenbroek list = next;
586*d56f51eaSDavid van Moolenbroek }
587*d56f51eaSDavid van Moolenbroek }
588*d56f51eaSDavid van Moolenbroek
589*d56f51eaSDavid van Moolenbroek /*
590*d56f51eaSDavid van Moolenbroek * Merge the lists in b0 and b1, using the 'sense' field to indicate
591*d56f51eaSDavid van Moolenbroek * which of jt and jf is the link.
592*d56f51eaSDavid van Moolenbroek */
593*d56f51eaSDavid van Moolenbroek static void
merge(b0,b1)594*d56f51eaSDavid van Moolenbroek merge(b0, b1)
595*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
596*d56f51eaSDavid van Moolenbroek {
597*d56f51eaSDavid van Moolenbroek register struct block **p = &b0;
598*d56f51eaSDavid van Moolenbroek
599*d56f51eaSDavid van Moolenbroek /* Find end of list. */
600*d56f51eaSDavid van Moolenbroek while (*p)
601*d56f51eaSDavid van Moolenbroek p = !((*p)->sense) ? &JT(*p) : &JF(*p);
602*d56f51eaSDavid van Moolenbroek
603*d56f51eaSDavid van Moolenbroek /* Concatenate the lists. */
604*d56f51eaSDavid van Moolenbroek *p = b1;
605*d56f51eaSDavid van Moolenbroek }
606*d56f51eaSDavid van Moolenbroek
607*d56f51eaSDavid van Moolenbroek void
finish_parse(p)608*d56f51eaSDavid van Moolenbroek finish_parse(p)
609*d56f51eaSDavid van Moolenbroek struct block *p;
610*d56f51eaSDavid van Moolenbroek {
611*d56f51eaSDavid van Moolenbroek struct block *ppi_dlt_check;
612*d56f51eaSDavid van Moolenbroek
613*d56f51eaSDavid van Moolenbroek /*
614*d56f51eaSDavid van Moolenbroek * Insert before the statements of the first (root) block any
615*d56f51eaSDavid van Moolenbroek * statements needed to load the lengths of any variable-length
616*d56f51eaSDavid van Moolenbroek * headers into registers.
617*d56f51eaSDavid van Moolenbroek *
618*d56f51eaSDavid van Moolenbroek * XXX - a fancier strategy would be to insert those before the
619*d56f51eaSDavid van Moolenbroek * statements of all blocks that use those lengths and that
620*d56f51eaSDavid van Moolenbroek * have no predecessors that use them, so that we only compute
621*d56f51eaSDavid van Moolenbroek * the lengths if we need them. There might be even better
622*d56f51eaSDavid van Moolenbroek * approaches than that.
623*d56f51eaSDavid van Moolenbroek *
624*d56f51eaSDavid van Moolenbroek * However, those strategies would be more complicated, and
625*d56f51eaSDavid van Moolenbroek * as we don't generate code to compute a length if the
626*d56f51eaSDavid van Moolenbroek * program has no tests that use the length, and as most
627*d56f51eaSDavid van Moolenbroek * tests will probably use those lengths, we would just
628*d56f51eaSDavid van Moolenbroek * postpone computing the lengths so that it's not done
629*d56f51eaSDavid van Moolenbroek * for tests that fail early, and it's not clear that's
630*d56f51eaSDavid van Moolenbroek * worth the effort.
631*d56f51eaSDavid van Moolenbroek */
632*d56f51eaSDavid van Moolenbroek insert_compute_vloffsets(p->head);
633*d56f51eaSDavid van Moolenbroek
634*d56f51eaSDavid van Moolenbroek /*
635*d56f51eaSDavid van Moolenbroek * For DLT_PPI captures, generate a check of the per-packet
636*d56f51eaSDavid van Moolenbroek * DLT value to make sure it's DLT_IEEE802_11.
637*d56f51eaSDavid van Moolenbroek */
638*d56f51eaSDavid van Moolenbroek ppi_dlt_check = gen_ppi_dlt_check();
639*d56f51eaSDavid van Moolenbroek if (ppi_dlt_check != NULL)
640*d56f51eaSDavid van Moolenbroek gen_and(ppi_dlt_check, p);
641*d56f51eaSDavid van Moolenbroek
642*d56f51eaSDavid van Moolenbroek backpatch(p, gen_retblk(snaplen));
643*d56f51eaSDavid van Moolenbroek p->sense = !p->sense;
644*d56f51eaSDavid van Moolenbroek backpatch(p, gen_retblk(0));
645*d56f51eaSDavid van Moolenbroek root = p->head;
646*d56f51eaSDavid van Moolenbroek }
647*d56f51eaSDavid van Moolenbroek
648*d56f51eaSDavid van Moolenbroek void
gen_and(b0,b1)649*d56f51eaSDavid van Moolenbroek gen_and(b0, b1)
650*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
651*d56f51eaSDavid van Moolenbroek {
652*d56f51eaSDavid van Moolenbroek backpatch(b0, b1->head);
653*d56f51eaSDavid van Moolenbroek b0->sense = !b0->sense;
654*d56f51eaSDavid van Moolenbroek b1->sense = !b1->sense;
655*d56f51eaSDavid van Moolenbroek merge(b1, b0);
656*d56f51eaSDavid van Moolenbroek b1->sense = !b1->sense;
657*d56f51eaSDavid van Moolenbroek b1->head = b0->head;
658*d56f51eaSDavid van Moolenbroek }
659*d56f51eaSDavid van Moolenbroek
660*d56f51eaSDavid van Moolenbroek void
gen_or(b0,b1)661*d56f51eaSDavid van Moolenbroek gen_or(b0, b1)
662*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
663*d56f51eaSDavid van Moolenbroek {
664*d56f51eaSDavid van Moolenbroek b0->sense = !b0->sense;
665*d56f51eaSDavid van Moolenbroek backpatch(b0, b1->head);
666*d56f51eaSDavid van Moolenbroek b0->sense = !b0->sense;
667*d56f51eaSDavid van Moolenbroek merge(b1, b0);
668*d56f51eaSDavid van Moolenbroek b1->head = b0->head;
669*d56f51eaSDavid van Moolenbroek }
670*d56f51eaSDavid van Moolenbroek
671*d56f51eaSDavid van Moolenbroek void
gen_not(b)672*d56f51eaSDavid van Moolenbroek gen_not(b)
673*d56f51eaSDavid van Moolenbroek struct block *b;
674*d56f51eaSDavid van Moolenbroek {
675*d56f51eaSDavid van Moolenbroek b->sense = !b->sense;
676*d56f51eaSDavid van Moolenbroek }
677*d56f51eaSDavid van Moolenbroek
678*d56f51eaSDavid van Moolenbroek static struct block *
gen_cmp(offrel,offset,size,v)679*d56f51eaSDavid van Moolenbroek gen_cmp(offrel, offset, size, v)
680*d56f51eaSDavid van Moolenbroek enum e_offrel offrel;
681*d56f51eaSDavid van Moolenbroek u_int offset, size;
682*d56f51eaSDavid van Moolenbroek bpf_int32 v;
683*d56f51eaSDavid van Moolenbroek {
684*d56f51eaSDavid van Moolenbroek return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v);
685*d56f51eaSDavid van Moolenbroek }
686*d56f51eaSDavid van Moolenbroek
687*d56f51eaSDavid van Moolenbroek static struct block *
gen_cmp_gt(offrel,offset,size,v)688*d56f51eaSDavid van Moolenbroek gen_cmp_gt(offrel, offset, size, v)
689*d56f51eaSDavid van Moolenbroek enum e_offrel offrel;
690*d56f51eaSDavid van Moolenbroek u_int offset, size;
691*d56f51eaSDavid van Moolenbroek bpf_int32 v;
692*d56f51eaSDavid van Moolenbroek {
693*d56f51eaSDavid van Moolenbroek return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 0, v);
694*d56f51eaSDavid van Moolenbroek }
695*d56f51eaSDavid van Moolenbroek
696*d56f51eaSDavid van Moolenbroek static struct block *
gen_cmp_ge(offrel,offset,size,v)697*d56f51eaSDavid van Moolenbroek gen_cmp_ge(offrel, offset, size, v)
698*d56f51eaSDavid van Moolenbroek enum e_offrel offrel;
699*d56f51eaSDavid van Moolenbroek u_int offset, size;
700*d56f51eaSDavid van Moolenbroek bpf_int32 v;
701*d56f51eaSDavid van Moolenbroek {
702*d56f51eaSDavid van Moolenbroek return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 0, v);
703*d56f51eaSDavid van Moolenbroek }
704*d56f51eaSDavid van Moolenbroek
705*d56f51eaSDavid van Moolenbroek static struct block *
gen_cmp_lt(offrel,offset,size,v)706*d56f51eaSDavid van Moolenbroek gen_cmp_lt(offrel, offset, size, v)
707*d56f51eaSDavid van Moolenbroek enum e_offrel offrel;
708*d56f51eaSDavid van Moolenbroek u_int offset, size;
709*d56f51eaSDavid van Moolenbroek bpf_int32 v;
710*d56f51eaSDavid van Moolenbroek {
711*d56f51eaSDavid van Moolenbroek return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 1, v);
712*d56f51eaSDavid van Moolenbroek }
713*d56f51eaSDavid van Moolenbroek
714*d56f51eaSDavid van Moolenbroek static struct block *
gen_cmp_le(offrel,offset,size,v)715*d56f51eaSDavid van Moolenbroek gen_cmp_le(offrel, offset, size, v)
716*d56f51eaSDavid van Moolenbroek enum e_offrel offrel;
717*d56f51eaSDavid van Moolenbroek u_int offset, size;
718*d56f51eaSDavid van Moolenbroek bpf_int32 v;
719*d56f51eaSDavid van Moolenbroek {
720*d56f51eaSDavid van Moolenbroek return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 1, v);
721*d56f51eaSDavid van Moolenbroek }
722*d56f51eaSDavid van Moolenbroek
723*d56f51eaSDavid van Moolenbroek static struct block *
gen_mcmp(offrel,offset,size,v,mask)724*d56f51eaSDavid van Moolenbroek gen_mcmp(offrel, offset, size, v, mask)
725*d56f51eaSDavid van Moolenbroek enum e_offrel offrel;
726*d56f51eaSDavid van Moolenbroek u_int offset, size;
727*d56f51eaSDavid van Moolenbroek bpf_int32 v;
728*d56f51eaSDavid van Moolenbroek bpf_u_int32 mask;
729*d56f51eaSDavid van Moolenbroek {
730*d56f51eaSDavid van Moolenbroek return gen_ncmp(offrel, offset, size, mask, BPF_JEQ, 0, v);
731*d56f51eaSDavid van Moolenbroek }
732*d56f51eaSDavid van Moolenbroek
733*d56f51eaSDavid van Moolenbroek static struct block *
gen_bcmp(offrel,offset,size,v)734*d56f51eaSDavid van Moolenbroek gen_bcmp(offrel, offset, size, v)
735*d56f51eaSDavid van Moolenbroek enum e_offrel offrel;
736*d56f51eaSDavid van Moolenbroek register u_int offset, size;
737*d56f51eaSDavid van Moolenbroek register const u_char *v;
738*d56f51eaSDavid van Moolenbroek {
739*d56f51eaSDavid van Moolenbroek register struct block *b, *tmp;
740*d56f51eaSDavid van Moolenbroek
741*d56f51eaSDavid van Moolenbroek b = NULL;
742*d56f51eaSDavid van Moolenbroek while (size >= 4) {
743*d56f51eaSDavid van Moolenbroek register const u_char *p = &v[size - 4];
744*d56f51eaSDavid van Moolenbroek bpf_int32 w = ((bpf_int32)p[0] << 24) |
745*d56f51eaSDavid van Moolenbroek ((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3];
746*d56f51eaSDavid van Moolenbroek
747*d56f51eaSDavid van Moolenbroek tmp = gen_cmp(offrel, offset + size - 4, BPF_W, w);
748*d56f51eaSDavid van Moolenbroek if (b != NULL)
749*d56f51eaSDavid van Moolenbroek gen_and(b, tmp);
750*d56f51eaSDavid van Moolenbroek b = tmp;
751*d56f51eaSDavid van Moolenbroek size -= 4;
752*d56f51eaSDavid van Moolenbroek }
753*d56f51eaSDavid van Moolenbroek while (size >= 2) {
754*d56f51eaSDavid van Moolenbroek register const u_char *p = &v[size - 2];
755*d56f51eaSDavid van Moolenbroek bpf_int32 w = ((bpf_int32)p[0] << 8) | p[1];
756*d56f51eaSDavid van Moolenbroek
757*d56f51eaSDavid van Moolenbroek tmp = gen_cmp(offrel, offset + size - 2, BPF_H, w);
758*d56f51eaSDavid van Moolenbroek if (b != NULL)
759*d56f51eaSDavid van Moolenbroek gen_and(b, tmp);
760*d56f51eaSDavid van Moolenbroek b = tmp;
761*d56f51eaSDavid van Moolenbroek size -= 2;
762*d56f51eaSDavid van Moolenbroek }
763*d56f51eaSDavid van Moolenbroek if (size > 0) {
764*d56f51eaSDavid van Moolenbroek tmp = gen_cmp(offrel, offset, BPF_B, (bpf_int32)v[0]);
765*d56f51eaSDavid van Moolenbroek if (b != NULL)
766*d56f51eaSDavid van Moolenbroek gen_and(b, tmp);
767*d56f51eaSDavid van Moolenbroek b = tmp;
768*d56f51eaSDavid van Moolenbroek }
769*d56f51eaSDavid van Moolenbroek return b;
770*d56f51eaSDavid van Moolenbroek }
771*d56f51eaSDavid van Moolenbroek
772*d56f51eaSDavid van Moolenbroek /*
773*d56f51eaSDavid van Moolenbroek * AND the field of size "size" at offset "offset" relative to the header
774*d56f51eaSDavid van Moolenbroek * specified by "offrel" with "mask", and compare it with the value "v"
775*d56f51eaSDavid van Moolenbroek * with the test specified by "jtype"; if "reverse" is true, the test
776*d56f51eaSDavid van Moolenbroek * should test the opposite of "jtype".
777*d56f51eaSDavid van Moolenbroek */
778*d56f51eaSDavid van Moolenbroek static struct block *
gen_ncmp(offrel,offset,size,mask,jtype,reverse,v)779*d56f51eaSDavid van Moolenbroek gen_ncmp(offrel, offset, size, mask, jtype, reverse, v)
780*d56f51eaSDavid van Moolenbroek enum e_offrel offrel;
781*d56f51eaSDavid van Moolenbroek bpf_int32 v;
782*d56f51eaSDavid van Moolenbroek bpf_u_int32 offset, size, mask, jtype;
783*d56f51eaSDavid van Moolenbroek int reverse;
784*d56f51eaSDavid van Moolenbroek {
785*d56f51eaSDavid van Moolenbroek struct slist *s, *s2;
786*d56f51eaSDavid van Moolenbroek struct block *b;
787*d56f51eaSDavid van Moolenbroek
788*d56f51eaSDavid van Moolenbroek s = gen_load_a(offrel, offset, size);
789*d56f51eaSDavid van Moolenbroek
790*d56f51eaSDavid van Moolenbroek if (mask != 0xffffffff) {
791*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
792*d56f51eaSDavid van Moolenbroek s2->s.k = mask;
793*d56f51eaSDavid van Moolenbroek sappend(s, s2);
794*d56f51eaSDavid van Moolenbroek }
795*d56f51eaSDavid van Moolenbroek
796*d56f51eaSDavid van Moolenbroek b = new_block(JMP(jtype));
797*d56f51eaSDavid van Moolenbroek b->stmts = s;
798*d56f51eaSDavid van Moolenbroek b->s.k = v;
799*d56f51eaSDavid van Moolenbroek if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE))
800*d56f51eaSDavid van Moolenbroek gen_not(b);
801*d56f51eaSDavid van Moolenbroek return b;
802*d56f51eaSDavid van Moolenbroek }
803*d56f51eaSDavid van Moolenbroek
804*d56f51eaSDavid van Moolenbroek /*
805*d56f51eaSDavid van Moolenbroek * Various code constructs need to know the layout of the packet.
806*d56f51eaSDavid van Moolenbroek * These variables give the necessary offsets from the beginning
807*d56f51eaSDavid van Moolenbroek * of the packet data.
808*d56f51eaSDavid van Moolenbroek */
809*d56f51eaSDavid van Moolenbroek
810*d56f51eaSDavid van Moolenbroek /*
811*d56f51eaSDavid van Moolenbroek * Absolute offset of the beginning of the link-layer header.
812*d56f51eaSDavid van Moolenbroek */
813*d56f51eaSDavid van Moolenbroek static bpf_abs_offset off_linkhdr;
814*d56f51eaSDavid van Moolenbroek
815*d56f51eaSDavid van Moolenbroek /*
816*d56f51eaSDavid van Moolenbroek * If we're checking a link-layer header for a packet encapsulated in
817*d56f51eaSDavid van Moolenbroek * another protocol layer, this is the equivalent information for the
818*d56f51eaSDavid van Moolenbroek * previous layers' link-layer header from the beginning of the raw
819*d56f51eaSDavid van Moolenbroek * packet data.
820*d56f51eaSDavid van Moolenbroek */
821*d56f51eaSDavid van Moolenbroek static bpf_abs_offset off_prevlinkhdr;
822*d56f51eaSDavid van Moolenbroek
823*d56f51eaSDavid van Moolenbroek /*
824*d56f51eaSDavid van Moolenbroek * This is the equivalent information for the outermost layers' link-layer
825*d56f51eaSDavid van Moolenbroek * header.
826*d56f51eaSDavid van Moolenbroek */
827*d56f51eaSDavid van Moolenbroek static bpf_abs_offset off_outermostlinkhdr;
828*d56f51eaSDavid van Moolenbroek
829*d56f51eaSDavid van Moolenbroek /*
830*d56f51eaSDavid van Moolenbroek * "Push" the current value of the link-layer header type and link-layer
831*d56f51eaSDavid van Moolenbroek * header offset onto a "stack", and set a new value. (It's not a
832*d56f51eaSDavid van Moolenbroek * full-blown stack; we keep only the top two items.)
833*d56f51eaSDavid van Moolenbroek */
834*d56f51eaSDavid van Moolenbroek #define PUSH_LINKHDR(new_linktype, new_is_variable, new_constant_part, new_reg) \
835*d56f51eaSDavid van Moolenbroek { \
836*d56f51eaSDavid van Moolenbroek prevlinktype = new_linktype; \
837*d56f51eaSDavid van Moolenbroek off_prevlinkhdr = off_linkhdr; \
838*d56f51eaSDavid van Moolenbroek linktype = new_linktype; \
839*d56f51eaSDavid van Moolenbroek off_linkhdr.is_variable = new_is_variable; \
840*d56f51eaSDavid van Moolenbroek off_linkhdr.constant_part = new_constant_part; \
841*d56f51eaSDavid van Moolenbroek off_linkhdr.reg = new_reg; \
842*d56f51eaSDavid van Moolenbroek is_geneve = 0; \
843*d56f51eaSDavid van Moolenbroek }
844*d56f51eaSDavid van Moolenbroek
845*d56f51eaSDavid van Moolenbroek /*
846*d56f51eaSDavid van Moolenbroek * Absolute offset of the beginning of the link-layer payload.
847*d56f51eaSDavid van Moolenbroek */
848*d56f51eaSDavid van Moolenbroek static bpf_abs_offset off_linkpl;
849*d56f51eaSDavid van Moolenbroek
850*d56f51eaSDavid van Moolenbroek /*
851*d56f51eaSDavid van Moolenbroek * "off_linktype" is the offset to information in the link-layer header
852*d56f51eaSDavid van Moolenbroek * giving the packet type. This is an absolute offset from the beginning
853*d56f51eaSDavid van Moolenbroek * of the packet.
854*d56f51eaSDavid van Moolenbroek *
855*d56f51eaSDavid van Moolenbroek * For Ethernet, it's the offset of the Ethernet type field; this
856*d56f51eaSDavid van Moolenbroek * means that it must have a value that skips VLAN tags.
857*d56f51eaSDavid van Moolenbroek *
858*d56f51eaSDavid van Moolenbroek * For link-layer types that always use 802.2 headers, it's the
859*d56f51eaSDavid van Moolenbroek * offset of the LLC header; this means that it must have a value
860*d56f51eaSDavid van Moolenbroek * that skips VLAN tags.
861*d56f51eaSDavid van Moolenbroek *
862*d56f51eaSDavid van Moolenbroek * For PPP, it's the offset of the PPP type field.
863*d56f51eaSDavid van Moolenbroek *
864*d56f51eaSDavid van Moolenbroek * For Cisco HDLC, it's the offset of the CHDLC type field.
865*d56f51eaSDavid van Moolenbroek *
866*d56f51eaSDavid van Moolenbroek * For BSD loopback, it's the offset of the AF_ value.
867*d56f51eaSDavid van Moolenbroek *
868*d56f51eaSDavid van Moolenbroek * For Linux cooked sockets, it's the offset of the type field.
869*d56f51eaSDavid van Moolenbroek *
870*d56f51eaSDavid van Moolenbroek * off_linktype.constant_part is set to -1 for no encapsulation,
871*d56f51eaSDavid van Moolenbroek * in which case, IP is assumed.
872*d56f51eaSDavid van Moolenbroek */
873*d56f51eaSDavid van Moolenbroek static bpf_abs_offset off_linktype;
874*d56f51eaSDavid van Moolenbroek
875*d56f51eaSDavid van Moolenbroek /*
876*d56f51eaSDavid van Moolenbroek * TRUE if the link layer includes an ATM pseudo-header.
877*d56f51eaSDavid van Moolenbroek */
878*d56f51eaSDavid van Moolenbroek static int is_atm = 0;
879*d56f51eaSDavid van Moolenbroek
880*d56f51eaSDavid van Moolenbroek /*
881*d56f51eaSDavid van Moolenbroek * TRUE if "geneve" appeared in the filter; it causes us to generate
882*d56f51eaSDavid van Moolenbroek * code that checks for a Geneve header and assume that later filters
883*d56f51eaSDavid van Moolenbroek * apply to the encapsulated payload.
884*d56f51eaSDavid van Moolenbroek */
885*d56f51eaSDavid van Moolenbroek static int is_geneve = 0;
886*d56f51eaSDavid van Moolenbroek
887*d56f51eaSDavid van Moolenbroek /*
888*d56f51eaSDavid van Moolenbroek * These are offsets for the ATM pseudo-header.
889*d56f51eaSDavid van Moolenbroek */
890*d56f51eaSDavid van Moolenbroek static u_int off_vpi;
891*d56f51eaSDavid van Moolenbroek static u_int off_vci;
892*d56f51eaSDavid van Moolenbroek static u_int off_proto;
893*d56f51eaSDavid van Moolenbroek
894*d56f51eaSDavid van Moolenbroek /*
895*d56f51eaSDavid van Moolenbroek * These are offsets for the MTP2 fields.
896*d56f51eaSDavid van Moolenbroek */
897*d56f51eaSDavid van Moolenbroek static u_int off_li;
898*d56f51eaSDavid van Moolenbroek static u_int off_li_hsl;
899*d56f51eaSDavid van Moolenbroek
900*d56f51eaSDavid van Moolenbroek /*
901*d56f51eaSDavid van Moolenbroek * These are offsets for the MTP3 fields.
902*d56f51eaSDavid van Moolenbroek */
903*d56f51eaSDavid van Moolenbroek static u_int off_sio;
904*d56f51eaSDavid van Moolenbroek static u_int off_opc;
905*d56f51eaSDavid van Moolenbroek static u_int off_dpc;
906*d56f51eaSDavid van Moolenbroek static u_int off_sls;
907*d56f51eaSDavid van Moolenbroek
908*d56f51eaSDavid van Moolenbroek /*
909*d56f51eaSDavid van Moolenbroek * This is the offset of the first byte after the ATM pseudo_header,
910*d56f51eaSDavid van Moolenbroek * or -1 if there is no ATM pseudo-header.
911*d56f51eaSDavid van Moolenbroek */
912*d56f51eaSDavid van Moolenbroek static u_int off_payload;
913*d56f51eaSDavid van Moolenbroek
914*d56f51eaSDavid van Moolenbroek /*
915*d56f51eaSDavid van Moolenbroek * These are offsets to the beginning of the network-layer header.
916*d56f51eaSDavid van Moolenbroek * They are relative to the beginning of the link-layer payload (i.e.,
917*d56f51eaSDavid van Moolenbroek * they don't include off_linkhdr.constant_part or off_linkpl.constant_part).
918*d56f51eaSDavid van Moolenbroek *
919*d56f51eaSDavid van Moolenbroek * If the link layer never uses 802.2 LLC:
920*d56f51eaSDavid van Moolenbroek *
921*d56f51eaSDavid van Moolenbroek * "off_nl" and "off_nl_nosnap" are the same.
922*d56f51eaSDavid van Moolenbroek *
923*d56f51eaSDavid van Moolenbroek * If the link layer always uses 802.2 LLC:
924*d56f51eaSDavid van Moolenbroek *
925*d56f51eaSDavid van Moolenbroek * "off_nl" is the offset if there's a SNAP header following
926*d56f51eaSDavid van Moolenbroek * the 802.2 header;
927*d56f51eaSDavid van Moolenbroek *
928*d56f51eaSDavid van Moolenbroek * "off_nl_nosnap" is the offset if there's no SNAP header.
929*d56f51eaSDavid van Moolenbroek *
930*d56f51eaSDavid van Moolenbroek * If the link layer is Ethernet:
931*d56f51eaSDavid van Moolenbroek *
932*d56f51eaSDavid van Moolenbroek * "off_nl" is the offset if the packet is an Ethernet II packet
933*d56f51eaSDavid van Moolenbroek * (we assume no 802.3+802.2+SNAP);
934*d56f51eaSDavid van Moolenbroek *
935*d56f51eaSDavid van Moolenbroek * "off_nl_nosnap" is the offset if the packet is an 802.3 packet
936*d56f51eaSDavid van Moolenbroek * with an 802.2 header following it.
937*d56f51eaSDavid van Moolenbroek */
938*d56f51eaSDavid van Moolenbroek static u_int off_nl;
939*d56f51eaSDavid van Moolenbroek static u_int off_nl_nosnap;
940*d56f51eaSDavid van Moolenbroek
941*d56f51eaSDavid van Moolenbroek static int linktype;
942*d56f51eaSDavid van Moolenbroek static int prevlinktype;
943*d56f51eaSDavid van Moolenbroek static int outermostlinktype;
944*d56f51eaSDavid van Moolenbroek
945*d56f51eaSDavid van Moolenbroek static void
init_linktype(p)946*d56f51eaSDavid van Moolenbroek init_linktype(p)
947*d56f51eaSDavid van Moolenbroek pcap_t *p;
948*d56f51eaSDavid van Moolenbroek {
949*d56f51eaSDavid van Moolenbroek pcap_fddipad = p->fddipad;
950*d56f51eaSDavid van Moolenbroek
951*d56f51eaSDavid van Moolenbroek /*
952*d56f51eaSDavid van Moolenbroek * We start out with only one link-layer header.
953*d56f51eaSDavid van Moolenbroek */
954*d56f51eaSDavid van Moolenbroek outermostlinktype = pcap_datalink(p);
955*d56f51eaSDavid van Moolenbroek off_outermostlinkhdr.constant_part = 0;
956*d56f51eaSDavid van Moolenbroek off_outermostlinkhdr.is_variable = 0;
957*d56f51eaSDavid van Moolenbroek off_outermostlinkhdr.reg = -1;
958*d56f51eaSDavid van Moolenbroek
959*d56f51eaSDavid van Moolenbroek prevlinktype = outermostlinktype;
960*d56f51eaSDavid van Moolenbroek off_prevlinkhdr.constant_part = 0;
961*d56f51eaSDavid van Moolenbroek off_prevlinkhdr.is_variable = 0;
962*d56f51eaSDavid van Moolenbroek off_prevlinkhdr.reg = -1;
963*d56f51eaSDavid van Moolenbroek
964*d56f51eaSDavid van Moolenbroek linktype = outermostlinktype;
965*d56f51eaSDavid van Moolenbroek off_linkhdr.constant_part = 0;
966*d56f51eaSDavid van Moolenbroek off_linkhdr.is_variable = 0;
967*d56f51eaSDavid van Moolenbroek off_linkhdr.reg = -1;
968*d56f51eaSDavid van Moolenbroek
969*d56f51eaSDavid van Moolenbroek /*
970*d56f51eaSDavid van Moolenbroek * XXX
971*d56f51eaSDavid van Moolenbroek */
972*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 0;
973*d56f51eaSDavid van Moolenbroek off_linkpl.is_variable = 0;
974*d56f51eaSDavid van Moolenbroek off_linkpl.reg = -1;
975*d56f51eaSDavid van Moolenbroek
976*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 0;
977*d56f51eaSDavid van Moolenbroek off_linktype.is_variable = 0;
978*d56f51eaSDavid van Moolenbroek off_linktype.reg = -1;
979*d56f51eaSDavid van Moolenbroek
980*d56f51eaSDavid van Moolenbroek /*
981*d56f51eaSDavid van Moolenbroek * Assume it's not raw ATM with a pseudo-header, for now.
982*d56f51eaSDavid van Moolenbroek */
983*d56f51eaSDavid van Moolenbroek is_atm = 0;
984*d56f51eaSDavid van Moolenbroek off_vpi = -1;
985*d56f51eaSDavid van Moolenbroek off_vci = -1;
986*d56f51eaSDavid van Moolenbroek off_proto = -1;
987*d56f51eaSDavid van Moolenbroek off_payload = -1;
988*d56f51eaSDavid van Moolenbroek
989*d56f51eaSDavid van Moolenbroek /*
990*d56f51eaSDavid van Moolenbroek * And not Geneve.
991*d56f51eaSDavid van Moolenbroek */
992*d56f51eaSDavid van Moolenbroek is_geneve = 0;
993*d56f51eaSDavid van Moolenbroek
994*d56f51eaSDavid van Moolenbroek /*
995*d56f51eaSDavid van Moolenbroek * And assume we're not doing SS7.
996*d56f51eaSDavid van Moolenbroek */
997*d56f51eaSDavid van Moolenbroek off_li = -1;
998*d56f51eaSDavid van Moolenbroek off_li_hsl = -1;
999*d56f51eaSDavid van Moolenbroek off_sio = -1;
1000*d56f51eaSDavid van Moolenbroek off_opc = -1;
1001*d56f51eaSDavid van Moolenbroek off_dpc = -1;
1002*d56f51eaSDavid van Moolenbroek off_sls = -1;
1003*d56f51eaSDavid van Moolenbroek
1004*d56f51eaSDavid van Moolenbroek label_stack_depth = 0;
1005*d56f51eaSDavid van Moolenbroek vlan_stack_depth = 0;
1006*d56f51eaSDavid van Moolenbroek
1007*d56f51eaSDavid van Moolenbroek switch (linktype) {
1008*d56f51eaSDavid van Moolenbroek
1009*d56f51eaSDavid van Moolenbroek case DLT_ARCNET:
1010*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 2;
1011*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 6;
1012*d56f51eaSDavid van Moolenbroek off_nl = 0; /* XXX in reality, variable! */
1013*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* no 802.2 LLC */
1014*d56f51eaSDavid van Moolenbroek break;
1015*d56f51eaSDavid van Moolenbroek
1016*d56f51eaSDavid van Moolenbroek case DLT_ARCNET_LINUX:
1017*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 4;
1018*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 8;
1019*d56f51eaSDavid van Moolenbroek off_nl = 0; /* XXX in reality, variable! */
1020*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* no 802.2 LLC */
1021*d56f51eaSDavid van Moolenbroek break;
1022*d56f51eaSDavid van Moolenbroek
1023*d56f51eaSDavid van Moolenbroek case DLT_EN10MB:
1024*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 12;
1025*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 14; /* Ethernet header length */
1026*d56f51eaSDavid van Moolenbroek off_nl = 0; /* Ethernet II */
1027*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 3; /* 802.3+802.2 */
1028*d56f51eaSDavid van Moolenbroek break;
1029*d56f51eaSDavid van Moolenbroek
1030*d56f51eaSDavid van Moolenbroek case DLT_SLIP:
1031*d56f51eaSDavid van Moolenbroek /*
1032*d56f51eaSDavid van Moolenbroek * SLIP doesn't have a link level type. The 16 byte
1033*d56f51eaSDavid van Moolenbroek * header is hacked into our SLIP driver.
1034*d56f51eaSDavid van Moolenbroek */
1035*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = -1;
1036*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 16;
1037*d56f51eaSDavid van Moolenbroek off_nl = 0;
1038*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* no 802.2 LLC */
1039*d56f51eaSDavid van Moolenbroek break;
1040*d56f51eaSDavid van Moolenbroek
1041*d56f51eaSDavid van Moolenbroek case DLT_SLIP_BSDOS:
1042*d56f51eaSDavid van Moolenbroek /* XXX this may be the same as the DLT_PPP_BSDOS case */
1043*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = -1;
1044*d56f51eaSDavid van Moolenbroek /* XXX end */
1045*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 24;
1046*d56f51eaSDavid van Moolenbroek off_nl = 0;
1047*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* no 802.2 LLC */
1048*d56f51eaSDavid van Moolenbroek break;
1049*d56f51eaSDavid van Moolenbroek
1050*d56f51eaSDavid van Moolenbroek case DLT_NULL:
1051*d56f51eaSDavid van Moolenbroek case DLT_LOOP:
1052*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 0;
1053*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 4;
1054*d56f51eaSDavid van Moolenbroek off_nl = 0;
1055*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* no 802.2 LLC */
1056*d56f51eaSDavid van Moolenbroek break;
1057*d56f51eaSDavid van Moolenbroek
1058*d56f51eaSDavid van Moolenbroek case DLT_ENC:
1059*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 0;
1060*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 12;
1061*d56f51eaSDavid van Moolenbroek off_nl = 0;
1062*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* no 802.2 LLC */
1063*d56f51eaSDavid van Moolenbroek break;
1064*d56f51eaSDavid van Moolenbroek
1065*d56f51eaSDavid van Moolenbroek case DLT_PPP:
1066*d56f51eaSDavid van Moolenbroek case DLT_PPP_PPPD:
1067*d56f51eaSDavid van Moolenbroek case DLT_C_HDLC: /* BSD/OS Cisco HDLC */
1068*d56f51eaSDavid van Moolenbroek case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */
1069*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 2; /* skip HDLC-like framing */
1070*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 4; /* skip HDLC-like framing and protocol field */
1071*d56f51eaSDavid van Moolenbroek off_nl = 0;
1072*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* no 802.2 LLC */
1073*d56f51eaSDavid van Moolenbroek break;
1074*d56f51eaSDavid van Moolenbroek
1075*d56f51eaSDavid van Moolenbroek case DLT_PPP_ETHER:
1076*d56f51eaSDavid van Moolenbroek /*
1077*d56f51eaSDavid van Moolenbroek * This does no include the Ethernet header, and
1078*d56f51eaSDavid van Moolenbroek * only covers session state.
1079*d56f51eaSDavid van Moolenbroek */
1080*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 6;
1081*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 8;
1082*d56f51eaSDavid van Moolenbroek off_nl = 0;
1083*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* no 802.2 LLC */
1084*d56f51eaSDavid van Moolenbroek break;
1085*d56f51eaSDavid van Moolenbroek
1086*d56f51eaSDavid van Moolenbroek case DLT_PPP_BSDOS:
1087*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 5;
1088*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 24;
1089*d56f51eaSDavid van Moolenbroek off_nl = 0;
1090*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* no 802.2 LLC */
1091*d56f51eaSDavid van Moolenbroek break;
1092*d56f51eaSDavid van Moolenbroek
1093*d56f51eaSDavid van Moolenbroek case DLT_FDDI:
1094*d56f51eaSDavid van Moolenbroek /*
1095*d56f51eaSDavid van Moolenbroek * FDDI doesn't really have a link-level type field.
1096*d56f51eaSDavid van Moolenbroek * We set "off_linktype" to the offset of the LLC header.
1097*d56f51eaSDavid van Moolenbroek *
1098*d56f51eaSDavid van Moolenbroek * To check for Ethernet types, we assume that SSAP = SNAP
1099*d56f51eaSDavid van Moolenbroek * is being used and pick out the encapsulated Ethernet type.
1100*d56f51eaSDavid van Moolenbroek * XXX - should we generate code to check for SNAP?
1101*d56f51eaSDavid van Moolenbroek */
1102*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 13;
1103*d56f51eaSDavid van Moolenbroek off_linktype.constant_part += pcap_fddipad;
1104*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 13; /* FDDI MAC header length */
1105*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part += pcap_fddipad;
1106*d56f51eaSDavid van Moolenbroek off_nl = 8; /* 802.2+SNAP */
1107*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 3; /* 802.2 */
1108*d56f51eaSDavid van Moolenbroek break;
1109*d56f51eaSDavid van Moolenbroek
1110*d56f51eaSDavid van Moolenbroek case DLT_IEEE802:
1111*d56f51eaSDavid van Moolenbroek /*
1112*d56f51eaSDavid van Moolenbroek * Token Ring doesn't really have a link-level type field.
1113*d56f51eaSDavid van Moolenbroek * We set "off_linktype" to the offset of the LLC header.
1114*d56f51eaSDavid van Moolenbroek *
1115*d56f51eaSDavid van Moolenbroek * To check for Ethernet types, we assume that SSAP = SNAP
1116*d56f51eaSDavid van Moolenbroek * is being used and pick out the encapsulated Ethernet type.
1117*d56f51eaSDavid van Moolenbroek * XXX - should we generate code to check for SNAP?
1118*d56f51eaSDavid van Moolenbroek *
1119*d56f51eaSDavid van Moolenbroek * XXX - the header is actually variable-length.
1120*d56f51eaSDavid van Moolenbroek * Some various Linux patched versions gave 38
1121*d56f51eaSDavid van Moolenbroek * as "off_linktype" and 40 as "off_nl"; however,
1122*d56f51eaSDavid van Moolenbroek * if a token ring packet has *no* routing
1123*d56f51eaSDavid van Moolenbroek * information, i.e. is not source-routed, the correct
1124*d56f51eaSDavid van Moolenbroek * values are 20 and 22, as they are in the vanilla code.
1125*d56f51eaSDavid van Moolenbroek *
1126*d56f51eaSDavid van Moolenbroek * A packet is source-routed iff the uppermost bit
1127*d56f51eaSDavid van Moolenbroek * of the first byte of the source address, at an
1128*d56f51eaSDavid van Moolenbroek * offset of 8, has the uppermost bit set. If the
1129*d56f51eaSDavid van Moolenbroek * packet is source-routed, the total number of bytes
1130*d56f51eaSDavid van Moolenbroek * of routing information is 2 plus bits 0x1F00 of
1131*d56f51eaSDavid van Moolenbroek * the 16-bit value at an offset of 14 (shifted right
1132*d56f51eaSDavid van Moolenbroek * 8 - figure out which byte that is).
1133*d56f51eaSDavid van Moolenbroek */
1134*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 14;
1135*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 14; /* Token Ring MAC header length */
1136*d56f51eaSDavid van Moolenbroek off_nl = 8; /* 802.2+SNAP */
1137*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 3; /* 802.2 */
1138*d56f51eaSDavid van Moolenbroek break;
1139*d56f51eaSDavid van Moolenbroek
1140*d56f51eaSDavid van Moolenbroek case DLT_PRISM_HEADER:
1141*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO_AVS:
1142*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO:
1143*d56f51eaSDavid van Moolenbroek off_linkhdr.is_variable = 1;
1144*d56f51eaSDavid van Moolenbroek /* Fall through, 802.11 doesn't have a variable link
1145*d56f51eaSDavid van Moolenbroek * prefix but is otherwise the same. */
1146*d56f51eaSDavid van Moolenbroek
1147*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11:
1148*d56f51eaSDavid van Moolenbroek /*
1149*d56f51eaSDavid van Moolenbroek * 802.11 doesn't really have a link-level type field.
1150*d56f51eaSDavid van Moolenbroek * We set "off_linktype.constant_part" to the offset of
1151*d56f51eaSDavid van Moolenbroek * the LLC header.
1152*d56f51eaSDavid van Moolenbroek *
1153*d56f51eaSDavid van Moolenbroek * To check for Ethernet types, we assume that SSAP = SNAP
1154*d56f51eaSDavid van Moolenbroek * is being used and pick out the encapsulated Ethernet type.
1155*d56f51eaSDavid van Moolenbroek * XXX - should we generate code to check for SNAP?
1156*d56f51eaSDavid van Moolenbroek *
1157*d56f51eaSDavid van Moolenbroek * We also handle variable-length radio headers here.
1158*d56f51eaSDavid van Moolenbroek * The Prism header is in theory variable-length, but in
1159*d56f51eaSDavid van Moolenbroek * practice it's always 144 bytes long. However, some
1160*d56f51eaSDavid van Moolenbroek * drivers on Linux use ARPHRD_IEEE80211_PRISM, but
1161*d56f51eaSDavid van Moolenbroek * sometimes or always supply an AVS header, so we
1162*d56f51eaSDavid van Moolenbroek * have to check whether the radio header is a Prism
1163*d56f51eaSDavid van Moolenbroek * header or an AVS header, so, in practice, it's
1164*d56f51eaSDavid van Moolenbroek * variable-length.
1165*d56f51eaSDavid van Moolenbroek */
1166*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 24;
1167*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 0; /* link-layer header is variable-length */
1168*d56f51eaSDavid van Moolenbroek off_linkpl.is_variable = 1;
1169*d56f51eaSDavid van Moolenbroek off_nl = 8; /* 802.2+SNAP */
1170*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 3; /* 802.2 */
1171*d56f51eaSDavid van Moolenbroek break;
1172*d56f51eaSDavid van Moolenbroek
1173*d56f51eaSDavid van Moolenbroek case DLT_PPI:
1174*d56f51eaSDavid van Moolenbroek /*
1175*d56f51eaSDavid van Moolenbroek * At the moment we treat PPI the same way that we treat
1176*d56f51eaSDavid van Moolenbroek * normal Radiotap encoded packets. The difference is in
1177*d56f51eaSDavid van Moolenbroek * the function that generates the code at the beginning
1178*d56f51eaSDavid van Moolenbroek * to compute the header length. Since this code generator
1179*d56f51eaSDavid van Moolenbroek * of PPI supports bare 802.11 encapsulation only (i.e.
1180*d56f51eaSDavid van Moolenbroek * the encapsulated DLT should be DLT_IEEE802_11) we
1181*d56f51eaSDavid van Moolenbroek * generate code to check for this too.
1182*d56f51eaSDavid van Moolenbroek */
1183*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 24;
1184*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 0; /* link-layer header is variable-length */
1185*d56f51eaSDavid van Moolenbroek off_linkpl.is_variable = 1;
1186*d56f51eaSDavid van Moolenbroek off_linkhdr.is_variable = 1;
1187*d56f51eaSDavid van Moolenbroek off_nl = 8; /* 802.2+SNAP */
1188*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 3; /* 802.2 */
1189*d56f51eaSDavid van Moolenbroek break;
1190*d56f51eaSDavid van Moolenbroek
1191*d56f51eaSDavid van Moolenbroek case DLT_ATM_RFC1483:
1192*d56f51eaSDavid van Moolenbroek case DLT_ATM_CLIP: /* Linux ATM defines this */
1193*d56f51eaSDavid van Moolenbroek /*
1194*d56f51eaSDavid van Moolenbroek * assume routed, non-ISO PDUs
1195*d56f51eaSDavid van Moolenbroek * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00)
1196*d56f51eaSDavid van Moolenbroek *
1197*d56f51eaSDavid van Moolenbroek * XXX - what about ISO PDUs, e.g. CLNP, ISIS, ESIS,
1198*d56f51eaSDavid van Moolenbroek * or PPP with the PPP NLPID (e.g., PPPoA)? The
1199*d56f51eaSDavid van Moolenbroek * latter would presumably be treated the way PPPoE
1200*d56f51eaSDavid van Moolenbroek * should be, so you can do "pppoe and udp port 2049"
1201*d56f51eaSDavid van Moolenbroek * or "pppoa and tcp port 80" and have it check for
1202*d56f51eaSDavid van Moolenbroek * PPPo{A,E} and a PPP protocol of IP and....
1203*d56f51eaSDavid van Moolenbroek */
1204*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 0;
1205*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 0; /* packet begins with LLC header */
1206*d56f51eaSDavid van Moolenbroek off_nl = 8; /* 802.2+SNAP */
1207*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 3; /* 802.2 */
1208*d56f51eaSDavid van Moolenbroek break;
1209*d56f51eaSDavid van Moolenbroek
1210*d56f51eaSDavid van Moolenbroek case DLT_SUNATM:
1211*d56f51eaSDavid van Moolenbroek /*
1212*d56f51eaSDavid van Moolenbroek * Full Frontal ATM; you get AALn PDUs with an ATM
1213*d56f51eaSDavid van Moolenbroek * pseudo-header.
1214*d56f51eaSDavid van Moolenbroek */
1215*d56f51eaSDavid van Moolenbroek is_atm = 1;
1216*d56f51eaSDavid van Moolenbroek off_vpi = SUNATM_VPI_POS;
1217*d56f51eaSDavid van Moolenbroek off_vci = SUNATM_VCI_POS;
1218*d56f51eaSDavid van Moolenbroek off_proto = PROTO_POS;
1219*d56f51eaSDavid van Moolenbroek off_payload = SUNATM_PKT_BEGIN_POS;
1220*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = off_payload;
1221*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = off_payload; /* if LLC-encapsulated */
1222*d56f51eaSDavid van Moolenbroek off_nl = 8; /* 802.2+SNAP */
1223*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 3; /* 802.2 */
1224*d56f51eaSDavid van Moolenbroek break;
1225*d56f51eaSDavid van Moolenbroek
1226*d56f51eaSDavid van Moolenbroek case DLT_RAW:
1227*d56f51eaSDavid van Moolenbroek case DLT_IPV4:
1228*d56f51eaSDavid van Moolenbroek case DLT_IPV6:
1229*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = -1;
1230*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 0;
1231*d56f51eaSDavid van Moolenbroek off_nl = 0;
1232*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* no 802.2 LLC */
1233*d56f51eaSDavid van Moolenbroek break;
1234*d56f51eaSDavid van Moolenbroek
1235*d56f51eaSDavid van Moolenbroek case DLT_LINUX_SLL: /* fake header for Linux cooked socket */
1236*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 14;
1237*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 16;
1238*d56f51eaSDavid van Moolenbroek off_nl = 0;
1239*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* no 802.2 LLC */
1240*d56f51eaSDavid van Moolenbroek break;
1241*d56f51eaSDavid van Moolenbroek
1242*d56f51eaSDavid van Moolenbroek case DLT_LTALK:
1243*d56f51eaSDavid van Moolenbroek /*
1244*d56f51eaSDavid van Moolenbroek * LocalTalk does have a 1-byte type field in the LLAP header,
1245*d56f51eaSDavid van Moolenbroek * but really it just indicates whether there is a "short" or
1246*d56f51eaSDavid van Moolenbroek * "long" DDP packet following.
1247*d56f51eaSDavid van Moolenbroek */
1248*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = -1;
1249*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 0;
1250*d56f51eaSDavid van Moolenbroek off_nl = 0;
1251*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* no 802.2 LLC */
1252*d56f51eaSDavid van Moolenbroek break;
1253*d56f51eaSDavid van Moolenbroek
1254*d56f51eaSDavid van Moolenbroek case DLT_IP_OVER_FC:
1255*d56f51eaSDavid van Moolenbroek /*
1256*d56f51eaSDavid van Moolenbroek * RFC 2625 IP-over-Fibre-Channel doesn't really have a
1257*d56f51eaSDavid van Moolenbroek * link-level type field. We set "off_linktype" to the
1258*d56f51eaSDavid van Moolenbroek * offset of the LLC header.
1259*d56f51eaSDavid van Moolenbroek *
1260*d56f51eaSDavid van Moolenbroek * To check for Ethernet types, we assume that SSAP = SNAP
1261*d56f51eaSDavid van Moolenbroek * is being used and pick out the encapsulated Ethernet type.
1262*d56f51eaSDavid van Moolenbroek * XXX - should we generate code to check for SNAP? RFC
1263*d56f51eaSDavid van Moolenbroek * 2625 says SNAP should be used.
1264*d56f51eaSDavid van Moolenbroek */
1265*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 16;
1266*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 16;
1267*d56f51eaSDavid van Moolenbroek off_nl = 8; /* 802.2+SNAP */
1268*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 3; /* 802.2 */
1269*d56f51eaSDavid van Moolenbroek break;
1270*d56f51eaSDavid van Moolenbroek
1271*d56f51eaSDavid van Moolenbroek case DLT_FRELAY:
1272*d56f51eaSDavid van Moolenbroek /*
1273*d56f51eaSDavid van Moolenbroek * XXX - we should set this to handle SNAP-encapsulated
1274*d56f51eaSDavid van Moolenbroek * frames (NLPID of 0x80).
1275*d56f51eaSDavid van Moolenbroek */
1276*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = -1;
1277*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 0;
1278*d56f51eaSDavid van Moolenbroek off_nl = 0;
1279*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* no 802.2 LLC */
1280*d56f51eaSDavid van Moolenbroek break;
1281*d56f51eaSDavid van Moolenbroek
1282*d56f51eaSDavid van Moolenbroek /*
1283*d56f51eaSDavid van Moolenbroek * the only BPF-interesting FRF.16 frames are non-control frames;
1284*d56f51eaSDavid van Moolenbroek * Frame Relay has a variable length link-layer
1285*d56f51eaSDavid van Moolenbroek * so lets start with offset 4 for now and increments later on (FIXME);
1286*d56f51eaSDavid van Moolenbroek */
1287*d56f51eaSDavid van Moolenbroek case DLT_MFR:
1288*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = -1;
1289*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 0;
1290*d56f51eaSDavid van Moolenbroek off_nl = 4;
1291*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* XXX - for now -> no 802.2 LLC */
1292*d56f51eaSDavid van Moolenbroek break;
1293*d56f51eaSDavid van Moolenbroek
1294*d56f51eaSDavid van Moolenbroek case DLT_APPLE_IP_OVER_IEEE1394:
1295*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 16;
1296*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 18;
1297*d56f51eaSDavid van Moolenbroek off_nl = 0;
1298*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* no 802.2 LLC */
1299*d56f51eaSDavid van Moolenbroek break;
1300*d56f51eaSDavid van Moolenbroek
1301*d56f51eaSDavid van Moolenbroek case DLT_SYMANTEC_FIREWALL:
1302*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 6;
1303*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 44;
1304*d56f51eaSDavid van Moolenbroek off_nl = 0; /* Ethernet II */
1305*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* XXX - what does it do with 802.3 packets? */
1306*d56f51eaSDavid van Moolenbroek break;
1307*d56f51eaSDavid van Moolenbroek
1308*d56f51eaSDavid van Moolenbroek #ifdef HAVE_NET_PFVAR_H
1309*d56f51eaSDavid van Moolenbroek case DLT_PFLOG:
1310*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 0;
1311*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = PFLOG_HDRLEN;
1312*d56f51eaSDavid van Moolenbroek off_nl = 0;
1313*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* no 802.2 LLC */
1314*d56f51eaSDavid van Moolenbroek break;
1315*d56f51eaSDavid van Moolenbroek #endif
1316*d56f51eaSDavid van Moolenbroek
1317*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_MFR:
1318*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_MLFR:
1319*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_MLPPP:
1320*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_PPP:
1321*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_CHDLC:
1322*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_FRELAY:
1323*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 4;
1324*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 4;
1325*d56f51eaSDavid van Moolenbroek off_nl = 0;
1326*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1; /* no 802.2 LLC */
1327*d56f51eaSDavid van Moolenbroek break;
1328*d56f51eaSDavid van Moolenbroek
1329*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ATM1:
1330*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 4; /* in reality variable between 4-8 */
1331*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 4; /* in reality variable between 4-8 */
1332*d56f51eaSDavid van Moolenbroek off_nl = 0;
1333*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 10;
1334*d56f51eaSDavid van Moolenbroek break;
1335*d56f51eaSDavid van Moolenbroek
1336*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ATM2:
1337*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 8; /* in reality variable between 8-12 */
1338*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 8; /* in reality variable between 8-12 */
1339*d56f51eaSDavid van Moolenbroek off_nl = 0;
1340*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 10;
1341*d56f51eaSDavid van Moolenbroek break;
1342*d56f51eaSDavid van Moolenbroek
1343*d56f51eaSDavid van Moolenbroek /* frames captured on a Juniper PPPoE service PIC
1344*d56f51eaSDavid van Moolenbroek * contain raw ethernet frames */
1345*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_PPPOE:
1346*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ETHER:
1347*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 14;
1348*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 16;
1349*d56f51eaSDavid van Moolenbroek off_nl = 18; /* Ethernet II */
1350*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 21; /* 802.3+802.2 */
1351*d56f51eaSDavid van Moolenbroek break;
1352*d56f51eaSDavid van Moolenbroek
1353*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_PPPOE_ATM:
1354*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 4;
1355*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 6;
1356*d56f51eaSDavid van Moolenbroek off_nl = 0;
1357*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1; /* no 802.2 LLC */
1358*d56f51eaSDavid van Moolenbroek break;
1359*d56f51eaSDavid van Moolenbroek
1360*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_GGSN:
1361*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 6;
1362*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 12;
1363*d56f51eaSDavid van Moolenbroek off_nl = 0;
1364*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1; /* no 802.2 LLC */
1365*d56f51eaSDavid van Moolenbroek break;
1366*d56f51eaSDavid van Moolenbroek
1367*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ES:
1368*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 6;
1369*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = -1; /* not really a network layer but raw IP addresses */
1370*d56f51eaSDavid van Moolenbroek off_nl = -1; /* not really a network layer but raw IP addresses */
1371*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1; /* no 802.2 LLC */
1372*d56f51eaSDavid van Moolenbroek break;
1373*d56f51eaSDavid van Moolenbroek
1374*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_MONITOR:
1375*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 12;
1376*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 12;
1377*d56f51eaSDavid van Moolenbroek off_nl = 0; /* raw IP/IP6 header */
1378*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1; /* no 802.2 LLC */
1379*d56f51eaSDavid van Moolenbroek break;
1380*d56f51eaSDavid van Moolenbroek
1381*d56f51eaSDavid van Moolenbroek case DLT_BACNET_MS_TP:
1382*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = -1;
1383*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = -1;
1384*d56f51eaSDavid van Moolenbroek off_nl = -1;
1385*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1;
1386*d56f51eaSDavid van Moolenbroek break;
1387*d56f51eaSDavid van Moolenbroek
1388*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_SERVICES:
1389*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 12;
1390*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = -1; /* L3 proto location dep. on cookie type */
1391*d56f51eaSDavid van Moolenbroek off_nl = -1; /* L3 proto location dep. on cookie type */
1392*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1; /* no 802.2 LLC */
1393*d56f51eaSDavid van Moolenbroek break;
1394*d56f51eaSDavid van Moolenbroek
1395*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_VP:
1396*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 18;
1397*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = -1;
1398*d56f51eaSDavid van Moolenbroek off_nl = -1;
1399*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1;
1400*d56f51eaSDavid van Moolenbroek break;
1401*d56f51eaSDavid van Moolenbroek
1402*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ST:
1403*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 18;
1404*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = -1;
1405*d56f51eaSDavid van Moolenbroek off_nl = -1;
1406*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1;
1407*d56f51eaSDavid van Moolenbroek break;
1408*d56f51eaSDavid van Moolenbroek
1409*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ISM:
1410*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 8;
1411*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = -1;
1412*d56f51eaSDavid van Moolenbroek off_nl = -1;
1413*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1;
1414*d56f51eaSDavid van Moolenbroek break;
1415*d56f51eaSDavid van Moolenbroek
1416*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_VS:
1417*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_SRX_E2E:
1418*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_FIBRECHANNEL:
1419*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ATM_CEMIC:
1420*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 8;
1421*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = -1;
1422*d56f51eaSDavid van Moolenbroek off_nl = -1;
1423*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1;
1424*d56f51eaSDavid van Moolenbroek break;
1425*d56f51eaSDavid van Moolenbroek
1426*d56f51eaSDavid van Moolenbroek case DLT_MTP2:
1427*d56f51eaSDavid van Moolenbroek off_li = 2;
1428*d56f51eaSDavid van Moolenbroek off_li_hsl = 4;
1429*d56f51eaSDavid van Moolenbroek off_sio = 3;
1430*d56f51eaSDavid van Moolenbroek off_opc = 4;
1431*d56f51eaSDavid van Moolenbroek off_dpc = 4;
1432*d56f51eaSDavid van Moolenbroek off_sls = 7;
1433*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = -1;
1434*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = -1;
1435*d56f51eaSDavid van Moolenbroek off_nl = -1;
1436*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1;
1437*d56f51eaSDavid van Moolenbroek break;
1438*d56f51eaSDavid van Moolenbroek
1439*d56f51eaSDavid van Moolenbroek case DLT_MTP2_WITH_PHDR:
1440*d56f51eaSDavid van Moolenbroek off_li = 6;
1441*d56f51eaSDavid van Moolenbroek off_li_hsl = 8;
1442*d56f51eaSDavid van Moolenbroek off_sio = 7;
1443*d56f51eaSDavid van Moolenbroek off_opc = 8;
1444*d56f51eaSDavid van Moolenbroek off_dpc = 8;
1445*d56f51eaSDavid van Moolenbroek off_sls = 11;
1446*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = -1;
1447*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = -1;
1448*d56f51eaSDavid van Moolenbroek off_nl = -1;
1449*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1;
1450*d56f51eaSDavid van Moolenbroek break;
1451*d56f51eaSDavid van Moolenbroek
1452*d56f51eaSDavid van Moolenbroek case DLT_ERF:
1453*d56f51eaSDavid van Moolenbroek off_li = 22;
1454*d56f51eaSDavid van Moolenbroek off_li_hsl = 24;
1455*d56f51eaSDavid van Moolenbroek off_sio = 23;
1456*d56f51eaSDavid van Moolenbroek off_opc = 24;
1457*d56f51eaSDavid van Moolenbroek off_dpc = 24;
1458*d56f51eaSDavid van Moolenbroek off_sls = 27;
1459*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = -1;
1460*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = -1;
1461*d56f51eaSDavid van Moolenbroek off_nl = -1;
1462*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1;
1463*d56f51eaSDavid van Moolenbroek break;
1464*d56f51eaSDavid van Moolenbroek
1465*d56f51eaSDavid van Moolenbroek case DLT_PFSYNC:
1466*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = -1;
1467*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 4;
1468*d56f51eaSDavid van Moolenbroek off_nl = 0;
1469*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0;
1470*d56f51eaSDavid van Moolenbroek break;
1471*d56f51eaSDavid van Moolenbroek
1472*d56f51eaSDavid van Moolenbroek case DLT_AX25_KISS:
1473*d56f51eaSDavid van Moolenbroek /*
1474*d56f51eaSDavid van Moolenbroek * Currently, only raw "link[N:M]" filtering is supported.
1475*d56f51eaSDavid van Moolenbroek */
1476*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = -1; /* variable, min 15, max 71 steps of 7 */
1477*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = -1;
1478*d56f51eaSDavid van Moolenbroek off_nl = -1; /* variable, min 16, max 71 steps of 7 */
1479*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1; /* no 802.2 LLC */
1480*d56f51eaSDavid van Moolenbroek break;
1481*d56f51eaSDavid van Moolenbroek
1482*d56f51eaSDavid van Moolenbroek case DLT_IPNET:
1483*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 1;
1484*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 24; /* ipnet header length */
1485*d56f51eaSDavid van Moolenbroek off_nl = 0;
1486*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1;
1487*d56f51eaSDavid van Moolenbroek break;
1488*d56f51eaSDavid van Moolenbroek
1489*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER:
1490*d56f51eaSDavid van Moolenbroek off_linkhdr.constant_part = 4; /* Ethernet header is past 4-byte pseudo-header */
1491*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = off_linkhdr.constant_part + 12;
1492*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = off_linkhdr.constant_part + 14; /* pseudo-header+Ethernet header length */
1493*d56f51eaSDavid van Moolenbroek off_nl = 0; /* Ethernet II */
1494*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 3; /* 802.3+802.2 */
1495*d56f51eaSDavid van Moolenbroek break;
1496*d56f51eaSDavid van Moolenbroek
1497*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER_TRANSPARENT:
1498*d56f51eaSDavid van Moolenbroek off_linkhdr.constant_part = 12; /* MAC header is past 4-byte pseudo-header, preamble, and SFD */
1499*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = off_linkhdr.constant_part + 12;
1500*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = off_linkhdr.constant_part + 14; /* pseudo-header+preamble+SFD+Ethernet header length */
1501*d56f51eaSDavid van Moolenbroek off_nl = 0; /* Ethernet II */
1502*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 3; /* 802.3+802.2 */
1503*d56f51eaSDavid van Moolenbroek break;
1504*d56f51eaSDavid van Moolenbroek
1505*d56f51eaSDavid van Moolenbroek default:
1506*d56f51eaSDavid van Moolenbroek /*
1507*d56f51eaSDavid van Moolenbroek * For values in the range in which we've assigned new
1508*d56f51eaSDavid van Moolenbroek * DLT_ values, only raw "link[N:M]" filtering is supported.
1509*d56f51eaSDavid van Moolenbroek */
1510*d56f51eaSDavid van Moolenbroek if (linktype >= DLT_MATCHING_MIN &&
1511*d56f51eaSDavid van Moolenbroek linktype <= DLT_MATCHING_MAX) {
1512*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = -1;
1513*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = -1;
1514*d56f51eaSDavid van Moolenbroek off_nl = -1;
1515*d56f51eaSDavid van Moolenbroek off_nl_nosnap = -1;
1516*d56f51eaSDavid van Moolenbroek } else {
1517*d56f51eaSDavid van Moolenbroek bpf_error("unknown data link type %d", linktype);
1518*d56f51eaSDavid van Moolenbroek }
1519*d56f51eaSDavid van Moolenbroek break;
1520*d56f51eaSDavid van Moolenbroek }
1521*d56f51eaSDavid van Moolenbroek
1522*d56f51eaSDavid van Moolenbroek off_outermostlinkhdr = off_prevlinkhdr = off_linkhdr;
1523*d56f51eaSDavid van Moolenbroek }
1524*d56f51eaSDavid van Moolenbroek
1525*d56f51eaSDavid van Moolenbroek /*
1526*d56f51eaSDavid van Moolenbroek * Load a value relative to the specified absolute offset.
1527*d56f51eaSDavid van Moolenbroek */
1528*d56f51eaSDavid van Moolenbroek static struct slist *
gen_load_absoffsetrel(bpf_abs_offset * abs_offset,u_int offset,u_int size)1529*d56f51eaSDavid van Moolenbroek gen_load_absoffsetrel(bpf_abs_offset *abs_offset, u_int offset, u_int size)
1530*d56f51eaSDavid van Moolenbroek {
1531*d56f51eaSDavid van Moolenbroek struct slist *s, *s2;
1532*d56f51eaSDavid van Moolenbroek
1533*d56f51eaSDavid van Moolenbroek s = gen_abs_offset_varpart(abs_offset);
1534*d56f51eaSDavid van Moolenbroek
1535*d56f51eaSDavid van Moolenbroek /*
1536*d56f51eaSDavid van Moolenbroek * If "s" is non-null, it has code to arrange that the X register
1537*d56f51eaSDavid van Moolenbroek * contains the variable part of the absolute offset, so we
1538*d56f51eaSDavid van Moolenbroek * generate a load relative to that, with an offset of
1539*d56f51eaSDavid van Moolenbroek * abs_offset->constant_part + offset.
1540*d56f51eaSDavid van Moolenbroek *
1541*d56f51eaSDavid van Moolenbroek * Otherwise, we can do an absolute load with an offset of
1542*d56f51eaSDavid van Moolenbroek * abs_offset->constant_part + offset.
1543*d56f51eaSDavid van Moolenbroek */
1544*d56f51eaSDavid van Moolenbroek if (s != NULL) {
1545*d56f51eaSDavid van Moolenbroek /*
1546*d56f51eaSDavid van Moolenbroek * "s" points to a list of statements that puts the
1547*d56f51eaSDavid van Moolenbroek * variable part of the absolute offset into the X register.
1548*d56f51eaSDavid van Moolenbroek * Do an indirect load, to use the X register as an offset.
1549*d56f51eaSDavid van Moolenbroek */
1550*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_LD|BPF_IND|size);
1551*d56f51eaSDavid van Moolenbroek s2->s.k = abs_offset->constant_part + offset;
1552*d56f51eaSDavid van Moolenbroek sappend(s, s2);
1553*d56f51eaSDavid van Moolenbroek } else {
1554*d56f51eaSDavid van Moolenbroek /*
1555*d56f51eaSDavid van Moolenbroek * There is no variable part of the absolute offset, so
1556*d56f51eaSDavid van Moolenbroek * just do an absolute load.
1557*d56f51eaSDavid van Moolenbroek */
1558*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_LD|BPF_ABS|size);
1559*d56f51eaSDavid van Moolenbroek s->s.k = abs_offset->constant_part + offset;
1560*d56f51eaSDavid van Moolenbroek }
1561*d56f51eaSDavid van Moolenbroek return s;
1562*d56f51eaSDavid van Moolenbroek }
1563*d56f51eaSDavid van Moolenbroek
1564*d56f51eaSDavid van Moolenbroek /*
1565*d56f51eaSDavid van Moolenbroek * Load a value relative to the beginning of the specified header.
1566*d56f51eaSDavid van Moolenbroek */
1567*d56f51eaSDavid van Moolenbroek static struct slist *
gen_load_a(offrel,offset,size)1568*d56f51eaSDavid van Moolenbroek gen_load_a(offrel, offset, size)
1569*d56f51eaSDavid van Moolenbroek enum e_offrel offrel;
1570*d56f51eaSDavid van Moolenbroek u_int offset, size;
1571*d56f51eaSDavid van Moolenbroek {
1572*d56f51eaSDavid van Moolenbroek struct slist *s, *s2;
1573*d56f51eaSDavid van Moolenbroek
1574*d56f51eaSDavid van Moolenbroek switch (offrel) {
1575*d56f51eaSDavid van Moolenbroek
1576*d56f51eaSDavid van Moolenbroek case OR_PACKET:
1577*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_LD|BPF_ABS|size);
1578*d56f51eaSDavid van Moolenbroek s->s.k = offset;
1579*d56f51eaSDavid van Moolenbroek break;
1580*d56f51eaSDavid van Moolenbroek
1581*d56f51eaSDavid van Moolenbroek case OR_LINKHDR:
1582*d56f51eaSDavid van Moolenbroek s = gen_load_absoffsetrel(&off_linkhdr, offset, size);
1583*d56f51eaSDavid van Moolenbroek break;
1584*d56f51eaSDavid van Moolenbroek
1585*d56f51eaSDavid van Moolenbroek case OR_PREVLINKHDR:
1586*d56f51eaSDavid van Moolenbroek s = gen_load_absoffsetrel(&off_prevlinkhdr, offset, size);
1587*d56f51eaSDavid van Moolenbroek break;
1588*d56f51eaSDavid van Moolenbroek
1589*d56f51eaSDavid van Moolenbroek case OR_LLC:
1590*d56f51eaSDavid van Moolenbroek s = gen_load_absoffsetrel(&off_linkpl, offset, size);
1591*d56f51eaSDavid van Moolenbroek break;
1592*d56f51eaSDavid van Moolenbroek
1593*d56f51eaSDavid van Moolenbroek case OR_PREVMPLSHDR:
1594*d56f51eaSDavid van Moolenbroek s = gen_load_absoffsetrel(&off_linkpl, off_nl - 4 + offset, size);
1595*d56f51eaSDavid van Moolenbroek break;
1596*d56f51eaSDavid van Moolenbroek
1597*d56f51eaSDavid van Moolenbroek case OR_LINKPL:
1598*d56f51eaSDavid van Moolenbroek s = gen_load_absoffsetrel(&off_linkpl, off_nl + offset, size);
1599*d56f51eaSDavid van Moolenbroek break;
1600*d56f51eaSDavid van Moolenbroek
1601*d56f51eaSDavid van Moolenbroek case OR_LINKPL_NOSNAP:
1602*d56f51eaSDavid van Moolenbroek s = gen_load_absoffsetrel(&off_linkpl, off_nl_nosnap + offset, size);
1603*d56f51eaSDavid van Moolenbroek break;
1604*d56f51eaSDavid van Moolenbroek
1605*d56f51eaSDavid van Moolenbroek case OR_LINKTYPE:
1606*d56f51eaSDavid van Moolenbroek s = gen_load_absoffsetrel(&off_linktype, offset, size);
1607*d56f51eaSDavid van Moolenbroek break;
1608*d56f51eaSDavid van Moolenbroek
1609*d56f51eaSDavid van Moolenbroek case OR_TRAN_IPV4:
1610*d56f51eaSDavid van Moolenbroek /*
1611*d56f51eaSDavid van Moolenbroek * Load the X register with the length of the IPv4 header
1612*d56f51eaSDavid van Moolenbroek * (plus the offset of the link-layer header, if it's
1613*d56f51eaSDavid van Moolenbroek * preceded by a variable-length header such as a radio
1614*d56f51eaSDavid van Moolenbroek * header), in bytes.
1615*d56f51eaSDavid van Moolenbroek */
1616*d56f51eaSDavid van Moolenbroek s = gen_loadx_iphdrlen();
1617*d56f51eaSDavid van Moolenbroek
1618*d56f51eaSDavid van Moolenbroek /*
1619*d56f51eaSDavid van Moolenbroek * Load the item at {offset of the link-layer payload} +
1620*d56f51eaSDavid van Moolenbroek * {offset, relative to the start of the link-layer
1621*d56f51eaSDavid van Moolenbroek * paylod, of the IPv4 header} + {length of the IPv4 header} +
1622*d56f51eaSDavid van Moolenbroek * {specified offset}.
1623*d56f51eaSDavid van Moolenbroek *
1624*d56f51eaSDavid van Moolenbroek * If the offset of the link-layer payload is variable,
1625*d56f51eaSDavid van Moolenbroek * the variable part of that offset is included in the
1626*d56f51eaSDavid van Moolenbroek * value in the X register, and we include the constant
1627*d56f51eaSDavid van Moolenbroek * part in the offset of the load.
1628*d56f51eaSDavid van Moolenbroek */
1629*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_LD|BPF_IND|size);
1630*d56f51eaSDavid van Moolenbroek s2->s.k = off_linkpl.constant_part + off_nl + offset;
1631*d56f51eaSDavid van Moolenbroek sappend(s, s2);
1632*d56f51eaSDavid van Moolenbroek break;
1633*d56f51eaSDavid van Moolenbroek
1634*d56f51eaSDavid van Moolenbroek case OR_TRAN_IPV6:
1635*d56f51eaSDavid van Moolenbroek s = gen_load_absoffsetrel(&off_linkpl, off_nl + 40 + offset, size);
1636*d56f51eaSDavid van Moolenbroek break;
1637*d56f51eaSDavid van Moolenbroek
1638*d56f51eaSDavid van Moolenbroek default:
1639*d56f51eaSDavid van Moolenbroek abort();
1640*d56f51eaSDavid van Moolenbroek return NULL;
1641*d56f51eaSDavid van Moolenbroek }
1642*d56f51eaSDavid van Moolenbroek return s;
1643*d56f51eaSDavid van Moolenbroek }
1644*d56f51eaSDavid van Moolenbroek
1645*d56f51eaSDavid van Moolenbroek /*
1646*d56f51eaSDavid van Moolenbroek * Generate code to load into the X register the sum of the length of
1647*d56f51eaSDavid van Moolenbroek * the IPv4 header and the variable part of the offset of the link-layer
1648*d56f51eaSDavid van Moolenbroek * payload.
1649*d56f51eaSDavid van Moolenbroek */
1650*d56f51eaSDavid van Moolenbroek static struct slist *
gen_loadx_iphdrlen()1651*d56f51eaSDavid van Moolenbroek gen_loadx_iphdrlen()
1652*d56f51eaSDavid van Moolenbroek {
1653*d56f51eaSDavid van Moolenbroek struct slist *s, *s2;
1654*d56f51eaSDavid van Moolenbroek
1655*d56f51eaSDavid van Moolenbroek s = gen_abs_offset_varpart(&off_linkpl);
1656*d56f51eaSDavid van Moolenbroek if (s != NULL) {
1657*d56f51eaSDavid van Moolenbroek /*
1658*d56f51eaSDavid van Moolenbroek * The offset of the link-layer payload has a variable
1659*d56f51eaSDavid van Moolenbroek * part. "s" points to a list of statements that put
1660*d56f51eaSDavid van Moolenbroek * the variable part of that offset into the X register.
1661*d56f51eaSDavid van Moolenbroek *
1662*d56f51eaSDavid van Moolenbroek * The 4*([k]&0xf) addressing mode can't be used, as we
1663*d56f51eaSDavid van Moolenbroek * don't have a constant offset, so we have to load the
1664*d56f51eaSDavid van Moolenbroek * value in question into the A register and add to it
1665*d56f51eaSDavid van Moolenbroek * the value from the X register.
1666*d56f51eaSDavid van Moolenbroek */
1667*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
1668*d56f51eaSDavid van Moolenbroek s2->s.k = off_linkpl.constant_part + off_nl;
1669*d56f51eaSDavid van Moolenbroek sappend(s, s2);
1670*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
1671*d56f51eaSDavid van Moolenbroek s2->s.k = 0xf;
1672*d56f51eaSDavid van Moolenbroek sappend(s, s2);
1673*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
1674*d56f51eaSDavid van Moolenbroek s2->s.k = 2;
1675*d56f51eaSDavid van Moolenbroek sappend(s, s2);
1676*d56f51eaSDavid van Moolenbroek
1677*d56f51eaSDavid van Moolenbroek /*
1678*d56f51eaSDavid van Moolenbroek * The A register now contains the length of the IP header.
1679*d56f51eaSDavid van Moolenbroek * We need to add to it the variable part of the offset of
1680*d56f51eaSDavid van Moolenbroek * the link-layer payload, which is still in the X
1681*d56f51eaSDavid van Moolenbroek * register, and move the result into the X register.
1682*d56f51eaSDavid van Moolenbroek */
1683*d56f51eaSDavid van Moolenbroek sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
1684*d56f51eaSDavid van Moolenbroek sappend(s, new_stmt(BPF_MISC|BPF_TAX));
1685*d56f51eaSDavid van Moolenbroek } else {
1686*d56f51eaSDavid van Moolenbroek /*
1687*d56f51eaSDavid van Moolenbroek * The offset of the link-layer payload is a constant,
1688*d56f51eaSDavid van Moolenbroek * so no code was generated to load the (non-existent)
1689*d56f51eaSDavid van Moolenbroek * variable part of that offset.
1690*d56f51eaSDavid van Moolenbroek *
1691*d56f51eaSDavid van Moolenbroek * This means we can use the 4*([k]&0xf) addressing
1692*d56f51eaSDavid van Moolenbroek * mode. Load the length of the IPv4 header, which
1693*d56f51eaSDavid van Moolenbroek * is at an offset of off_nl from the beginning of
1694*d56f51eaSDavid van Moolenbroek * the link-layer payload, and thus at an offset of
1695*d56f51eaSDavid van Moolenbroek * off_linkpl.constant_part + off_nl from the beginning
1696*d56f51eaSDavid van Moolenbroek * of the raw packet data, using that addressing mode.
1697*d56f51eaSDavid van Moolenbroek */
1698*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
1699*d56f51eaSDavid van Moolenbroek s->s.k = off_linkpl.constant_part + off_nl;
1700*d56f51eaSDavid van Moolenbroek }
1701*d56f51eaSDavid van Moolenbroek return s;
1702*d56f51eaSDavid van Moolenbroek }
1703*d56f51eaSDavid van Moolenbroek
1704*d56f51eaSDavid van Moolenbroek static struct block *
gen_uncond(rsense)1705*d56f51eaSDavid van Moolenbroek gen_uncond(rsense)
1706*d56f51eaSDavid van Moolenbroek int rsense;
1707*d56f51eaSDavid van Moolenbroek {
1708*d56f51eaSDavid van Moolenbroek struct block *b;
1709*d56f51eaSDavid van Moolenbroek struct slist *s;
1710*d56f51eaSDavid van Moolenbroek
1711*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_LD|BPF_IMM);
1712*d56f51eaSDavid van Moolenbroek s->s.k = !rsense;
1713*d56f51eaSDavid van Moolenbroek b = new_block(JMP(BPF_JEQ));
1714*d56f51eaSDavid van Moolenbroek b->stmts = s;
1715*d56f51eaSDavid van Moolenbroek
1716*d56f51eaSDavid van Moolenbroek return b;
1717*d56f51eaSDavid van Moolenbroek }
1718*d56f51eaSDavid van Moolenbroek
1719*d56f51eaSDavid van Moolenbroek static inline struct block *
gen_true()1720*d56f51eaSDavid van Moolenbroek gen_true()
1721*d56f51eaSDavid van Moolenbroek {
1722*d56f51eaSDavid van Moolenbroek return gen_uncond(1);
1723*d56f51eaSDavid van Moolenbroek }
1724*d56f51eaSDavid van Moolenbroek
1725*d56f51eaSDavid van Moolenbroek static inline struct block *
gen_false()1726*d56f51eaSDavid van Moolenbroek gen_false()
1727*d56f51eaSDavid van Moolenbroek {
1728*d56f51eaSDavid van Moolenbroek return gen_uncond(0);
1729*d56f51eaSDavid van Moolenbroek }
1730*d56f51eaSDavid van Moolenbroek
1731*d56f51eaSDavid van Moolenbroek /*
1732*d56f51eaSDavid van Moolenbroek * Byte-swap a 32-bit number.
1733*d56f51eaSDavid van Moolenbroek * ("htonl()" or "ntohl()" won't work - we want to byte-swap even on
1734*d56f51eaSDavid van Moolenbroek * big-endian platforms.)
1735*d56f51eaSDavid van Moolenbroek */
1736*d56f51eaSDavid van Moolenbroek #define SWAPLONG(y) \
1737*d56f51eaSDavid van Moolenbroek ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
1738*d56f51eaSDavid van Moolenbroek
1739*d56f51eaSDavid van Moolenbroek /*
1740*d56f51eaSDavid van Moolenbroek * Generate code to match a particular packet type.
1741*d56f51eaSDavid van Moolenbroek *
1742*d56f51eaSDavid van Moolenbroek * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
1743*d56f51eaSDavid van Moolenbroek * value, if <= ETHERMTU. We use that to determine whether to
1744*d56f51eaSDavid van Moolenbroek * match the type/length field or to check the type/length field for
1745*d56f51eaSDavid van Moolenbroek * a value <= ETHERMTU to see whether it's a type field and then do
1746*d56f51eaSDavid van Moolenbroek * the appropriate test.
1747*d56f51eaSDavid van Moolenbroek */
1748*d56f51eaSDavid van Moolenbroek static struct block *
gen_ether_linktype(proto)1749*d56f51eaSDavid van Moolenbroek gen_ether_linktype(proto)
1750*d56f51eaSDavid van Moolenbroek register int proto;
1751*d56f51eaSDavid van Moolenbroek {
1752*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
1753*d56f51eaSDavid van Moolenbroek
1754*d56f51eaSDavid van Moolenbroek switch (proto) {
1755*d56f51eaSDavid van Moolenbroek
1756*d56f51eaSDavid van Moolenbroek case LLCSAP_ISONS:
1757*d56f51eaSDavid van Moolenbroek case LLCSAP_IP:
1758*d56f51eaSDavid van Moolenbroek case LLCSAP_NETBEUI:
1759*d56f51eaSDavid van Moolenbroek /*
1760*d56f51eaSDavid van Moolenbroek * OSI protocols and NetBEUI always use 802.2 encapsulation,
1761*d56f51eaSDavid van Moolenbroek * so we check the DSAP and SSAP.
1762*d56f51eaSDavid van Moolenbroek *
1763*d56f51eaSDavid van Moolenbroek * LLCSAP_IP checks for IP-over-802.2, rather
1764*d56f51eaSDavid van Moolenbroek * than IP-over-Ethernet or IP-over-SNAP.
1765*d56f51eaSDavid van Moolenbroek *
1766*d56f51eaSDavid van Moolenbroek * XXX - should we check both the DSAP and the
1767*d56f51eaSDavid van Moolenbroek * SSAP, like this, or should we check just the
1768*d56f51eaSDavid van Moolenbroek * DSAP, as we do for other types <= ETHERMTU
1769*d56f51eaSDavid van Moolenbroek * (i.e., other SAP values)?
1770*d56f51eaSDavid van Moolenbroek */
1771*d56f51eaSDavid van Moolenbroek b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
1772*d56f51eaSDavid van Moolenbroek gen_not(b0);
1773*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32)
1774*d56f51eaSDavid van Moolenbroek ((proto << 8) | proto));
1775*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
1776*d56f51eaSDavid van Moolenbroek return b1;
1777*d56f51eaSDavid van Moolenbroek
1778*d56f51eaSDavid van Moolenbroek case LLCSAP_IPX:
1779*d56f51eaSDavid van Moolenbroek /*
1780*d56f51eaSDavid van Moolenbroek * Check for;
1781*d56f51eaSDavid van Moolenbroek *
1782*d56f51eaSDavid van Moolenbroek * Ethernet_II frames, which are Ethernet
1783*d56f51eaSDavid van Moolenbroek * frames with a frame type of ETHERTYPE_IPX;
1784*d56f51eaSDavid van Moolenbroek *
1785*d56f51eaSDavid van Moolenbroek * Ethernet_802.3 frames, which are 802.3
1786*d56f51eaSDavid van Moolenbroek * frames (i.e., the type/length field is
1787*d56f51eaSDavid van Moolenbroek * a length field, <= ETHERMTU, rather than
1788*d56f51eaSDavid van Moolenbroek * a type field) with the first two bytes
1789*d56f51eaSDavid van Moolenbroek * after the Ethernet/802.3 header being
1790*d56f51eaSDavid van Moolenbroek * 0xFFFF;
1791*d56f51eaSDavid van Moolenbroek *
1792*d56f51eaSDavid van Moolenbroek * Ethernet_802.2 frames, which are 802.3
1793*d56f51eaSDavid van Moolenbroek * frames with an 802.2 LLC header and
1794*d56f51eaSDavid van Moolenbroek * with the IPX LSAP as the DSAP in the LLC
1795*d56f51eaSDavid van Moolenbroek * header;
1796*d56f51eaSDavid van Moolenbroek *
1797*d56f51eaSDavid van Moolenbroek * Ethernet_SNAP frames, which are 802.3
1798*d56f51eaSDavid van Moolenbroek * frames with an LLC header and a SNAP
1799*d56f51eaSDavid van Moolenbroek * header and with an OUI of 0x000000
1800*d56f51eaSDavid van Moolenbroek * (encapsulated Ethernet) and a protocol
1801*d56f51eaSDavid van Moolenbroek * ID of ETHERTYPE_IPX in the SNAP header.
1802*d56f51eaSDavid van Moolenbroek *
1803*d56f51eaSDavid van Moolenbroek * XXX - should we generate the same code both
1804*d56f51eaSDavid van Moolenbroek * for tests for LLCSAP_IPX and for ETHERTYPE_IPX?
1805*d56f51eaSDavid van Moolenbroek */
1806*d56f51eaSDavid van Moolenbroek
1807*d56f51eaSDavid van Moolenbroek /*
1808*d56f51eaSDavid van Moolenbroek * This generates code to check both for the
1809*d56f51eaSDavid van Moolenbroek * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3.
1810*d56f51eaSDavid van Moolenbroek */
1811*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
1812*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
1813*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
1814*d56f51eaSDavid van Moolenbroek
1815*d56f51eaSDavid van Moolenbroek /*
1816*d56f51eaSDavid van Moolenbroek * Now we add code to check for SNAP frames with
1817*d56f51eaSDavid van Moolenbroek * ETHERTYPE_IPX, i.e. Ethernet_SNAP.
1818*d56f51eaSDavid van Moolenbroek */
1819*d56f51eaSDavid van Moolenbroek b0 = gen_snap(0x000000, ETHERTYPE_IPX);
1820*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
1821*d56f51eaSDavid van Moolenbroek
1822*d56f51eaSDavid van Moolenbroek /*
1823*d56f51eaSDavid van Moolenbroek * Now we generate code to check for 802.3
1824*d56f51eaSDavid van Moolenbroek * frames in general.
1825*d56f51eaSDavid van Moolenbroek */
1826*d56f51eaSDavid van Moolenbroek b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
1827*d56f51eaSDavid van Moolenbroek gen_not(b0);
1828*d56f51eaSDavid van Moolenbroek
1829*d56f51eaSDavid van Moolenbroek /*
1830*d56f51eaSDavid van Moolenbroek * Now add the check for 802.3 frames before the
1831*d56f51eaSDavid van Moolenbroek * check for Ethernet_802.2 and Ethernet_802.3,
1832*d56f51eaSDavid van Moolenbroek * as those checks should only be done on 802.3
1833*d56f51eaSDavid van Moolenbroek * frames, not on Ethernet frames.
1834*d56f51eaSDavid van Moolenbroek */
1835*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
1836*d56f51eaSDavid van Moolenbroek
1837*d56f51eaSDavid van Moolenbroek /*
1838*d56f51eaSDavid van Moolenbroek * Now add the check for Ethernet_II frames, and
1839*d56f51eaSDavid van Moolenbroek * do that before checking for the other frame
1840*d56f51eaSDavid van Moolenbroek * types.
1841*d56f51eaSDavid van Moolenbroek */
1842*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
1843*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
1844*d56f51eaSDavid van Moolenbroek return b1;
1845*d56f51eaSDavid van Moolenbroek
1846*d56f51eaSDavid van Moolenbroek case ETHERTYPE_ATALK:
1847*d56f51eaSDavid van Moolenbroek case ETHERTYPE_AARP:
1848*d56f51eaSDavid van Moolenbroek /*
1849*d56f51eaSDavid van Moolenbroek * EtherTalk (AppleTalk protocols on Ethernet link
1850*d56f51eaSDavid van Moolenbroek * layer) may use 802.2 encapsulation.
1851*d56f51eaSDavid van Moolenbroek */
1852*d56f51eaSDavid van Moolenbroek
1853*d56f51eaSDavid van Moolenbroek /*
1854*d56f51eaSDavid van Moolenbroek * Check for 802.2 encapsulation (EtherTalk phase 2?);
1855*d56f51eaSDavid van Moolenbroek * we check for an Ethernet type field less than
1856*d56f51eaSDavid van Moolenbroek * 1500, which means it's an 802.3 length field.
1857*d56f51eaSDavid van Moolenbroek */
1858*d56f51eaSDavid van Moolenbroek b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
1859*d56f51eaSDavid van Moolenbroek gen_not(b0);
1860*d56f51eaSDavid van Moolenbroek
1861*d56f51eaSDavid van Moolenbroek /*
1862*d56f51eaSDavid van Moolenbroek * 802.2-encapsulated ETHERTYPE_ATALK packets are
1863*d56f51eaSDavid van Moolenbroek * SNAP packets with an organization code of
1864*d56f51eaSDavid van Moolenbroek * 0x080007 (Apple, for Appletalk) and a protocol
1865*d56f51eaSDavid van Moolenbroek * type of ETHERTYPE_ATALK (Appletalk).
1866*d56f51eaSDavid van Moolenbroek *
1867*d56f51eaSDavid van Moolenbroek * 802.2-encapsulated ETHERTYPE_AARP packets are
1868*d56f51eaSDavid van Moolenbroek * SNAP packets with an organization code of
1869*d56f51eaSDavid van Moolenbroek * 0x000000 (encapsulated Ethernet) and a protocol
1870*d56f51eaSDavid van Moolenbroek * type of ETHERTYPE_AARP (Appletalk ARP).
1871*d56f51eaSDavid van Moolenbroek */
1872*d56f51eaSDavid van Moolenbroek if (proto == ETHERTYPE_ATALK)
1873*d56f51eaSDavid van Moolenbroek b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
1874*d56f51eaSDavid van Moolenbroek else /* proto == ETHERTYPE_AARP */
1875*d56f51eaSDavid van Moolenbroek b1 = gen_snap(0x000000, ETHERTYPE_AARP);
1876*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
1877*d56f51eaSDavid van Moolenbroek
1878*d56f51eaSDavid van Moolenbroek /*
1879*d56f51eaSDavid van Moolenbroek * Check for Ethernet encapsulation (Ethertalk
1880*d56f51eaSDavid van Moolenbroek * phase 1?); we just check for the Ethernet
1881*d56f51eaSDavid van Moolenbroek * protocol type.
1882*d56f51eaSDavid van Moolenbroek */
1883*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
1884*d56f51eaSDavid van Moolenbroek
1885*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
1886*d56f51eaSDavid van Moolenbroek return b1;
1887*d56f51eaSDavid van Moolenbroek
1888*d56f51eaSDavid van Moolenbroek default:
1889*d56f51eaSDavid van Moolenbroek if (proto <= ETHERMTU) {
1890*d56f51eaSDavid van Moolenbroek /*
1891*d56f51eaSDavid van Moolenbroek * This is an LLC SAP value, so the frames
1892*d56f51eaSDavid van Moolenbroek * that match would be 802.2 frames.
1893*d56f51eaSDavid van Moolenbroek * Check that the frame is an 802.2 frame
1894*d56f51eaSDavid van Moolenbroek * (i.e., that the length/type field is
1895*d56f51eaSDavid van Moolenbroek * a length field, <= ETHERMTU) and
1896*d56f51eaSDavid van Moolenbroek * then check the DSAP.
1897*d56f51eaSDavid van Moolenbroek */
1898*d56f51eaSDavid van Moolenbroek b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
1899*d56f51eaSDavid van Moolenbroek gen_not(b0);
1900*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LINKTYPE, 2, BPF_B, (bpf_int32)proto);
1901*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
1902*d56f51eaSDavid van Moolenbroek return b1;
1903*d56f51eaSDavid van Moolenbroek } else {
1904*d56f51eaSDavid van Moolenbroek /*
1905*d56f51eaSDavid van Moolenbroek * This is an Ethernet type, so compare
1906*d56f51eaSDavid van Moolenbroek * the length/type field with it (if
1907*d56f51eaSDavid van Moolenbroek * the frame is an 802.2 frame, the length
1908*d56f51eaSDavid van Moolenbroek * field will be <= ETHERMTU, and, as
1909*d56f51eaSDavid van Moolenbroek * "proto" is > ETHERMTU, this test
1910*d56f51eaSDavid van Moolenbroek * will fail and the frame won't match,
1911*d56f51eaSDavid van Moolenbroek * which is what we want).
1912*d56f51eaSDavid van Moolenbroek */
1913*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_LINKTYPE, 0, BPF_H,
1914*d56f51eaSDavid van Moolenbroek (bpf_int32)proto);
1915*d56f51eaSDavid van Moolenbroek }
1916*d56f51eaSDavid van Moolenbroek }
1917*d56f51eaSDavid van Moolenbroek }
1918*d56f51eaSDavid van Moolenbroek
1919*d56f51eaSDavid van Moolenbroek /*
1920*d56f51eaSDavid van Moolenbroek * "proto" is an Ethernet type value and for IPNET, if it is not IPv4
1921*d56f51eaSDavid van Moolenbroek * or IPv6 then we have an error.
1922*d56f51eaSDavid van Moolenbroek */
1923*d56f51eaSDavid van Moolenbroek static struct block *
gen_ipnet_linktype(proto)1924*d56f51eaSDavid van Moolenbroek gen_ipnet_linktype(proto)
1925*d56f51eaSDavid van Moolenbroek register int proto;
1926*d56f51eaSDavid van Moolenbroek {
1927*d56f51eaSDavid van Moolenbroek switch (proto) {
1928*d56f51eaSDavid van Moolenbroek
1929*d56f51eaSDavid van Moolenbroek case ETHERTYPE_IP:
1930*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_LINKTYPE, 0, BPF_B, (bpf_int32)IPH_AF_INET);
1931*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
1932*d56f51eaSDavid van Moolenbroek
1933*d56f51eaSDavid van Moolenbroek case ETHERTYPE_IPV6:
1934*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_LINKTYPE, 0, BPF_B,
1935*d56f51eaSDavid van Moolenbroek (bpf_int32)IPH_AF_INET6);
1936*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
1937*d56f51eaSDavid van Moolenbroek
1938*d56f51eaSDavid van Moolenbroek default:
1939*d56f51eaSDavid van Moolenbroek break;
1940*d56f51eaSDavid van Moolenbroek }
1941*d56f51eaSDavid van Moolenbroek
1942*d56f51eaSDavid van Moolenbroek return gen_false();
1943*d56f51eaSDavid van Moolenbroek }
1944*d56f51eaSDavid van Moolenbroek
1945*d56f51eaSDavid van Moolenbroek /*
1946*d56f51eaSDavid van Moolenbroek * Generate code to match a particular packet type.
1947*d56f51eaSDavid van Moolenbroek *
1948*d56f51eaSDavid van Moolenbroek * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
1949*d56f51eaSDavid van Moolenbroek * value, if <= ETHERMTU. We use that to determine whether to
1950*d56f51eaSDavid van Moolenbroek * match the type field or to check the type field for the special
1951*d56f51eaSDavid van Moolenbroek * LINUX_SLL_P_802_2 value and then do the appropriate test.
1952*d56f51eaSDavid van Moolenbroek */
1953*d56f51eaSDavid van Moolenbroek static struct block *
gen_linux_sll_linktype(proto)1954*d56f51eaSDavid van Moolenbroek gen_linux_sll_linktype(proto)
1955*d56f51eaSDavid van Moolenbroek register int proto;
1956*d56f51eaSDavid van Moolenbroek {
1957*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
1958*d56f51eaSDavid van Moolenbroek
1959*d56f51eaSDavid van Moolenbroek switch (proto) {
1960*d56f51eaSDavid van Moolenbroek
1961*d56f51eaSDavid van Moolenbroek case LLCSAP_ISONS:
1962*d56f51eaSDavid van Moolenbroek case LLCSAP_IP:
1963*d56f51eaSDavid van Moolenbroek case LLCSAP_NETBEUI:
1964*d56f51eaSDavid van Moolenbroek /*
1965*d56f51eaSDavid van Moolenbroek * OSI protocols and NetBEUI always use 802.2 encapsulation,
1966*d56f51eaSDavid van Moolenbroek * so we check the DSAP and SSAP.
1967*d56f51eaSDavid van Moolenbroek *
1968*d56f51eaSDavid van Moolenbroek * LLCSAP_IP checks for IP-over-802.2, rather
1969*d56f51eaSDavid van Moolenbroek * than IP-over-Ethernet or IP-over-SNAP.
1970*d56f51eaSDavid van Moolenbroek *
1971*d56f51eaSDavid van Moolenbroek * XXX - should we check both the DSAP and the
1972*d56f51eaSDavid van Moolenbroek * SSAP, like this, or should we check just the
1973*d56f51eaSDavid van Moolenbroek * DSAP, as we do for other types <= ETHERMTU
1974*d56f51eaSDavid van Moolenbroek * (i.e., other SAP values)?
1975*d56f51eaSDavid van Moolenbroek */
1976*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
1977*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32)
1978*d56f51eaSDavid van Moolenbroek ((proto << 8) | proto));
1979*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
1980*d56f51eaSDavid van Moolenbroek return b1;
1981*d56f51eaSDavid van Moolenbroek
1982*d56f51eaSDavid van Moolenbroek case LLCSAP_IPX:
1983*d56f51eaSDavid van Moolenbroek /*
1984*d56f51eaSDavid van Moolenbroek * Ethernet_II frames, which are Ethernet
1985*d56f51eaSDavid van Moolenbroek * frames with a frame type of ETHERTYPE_IPX;
1986*d56f51eaSDavid van Moolenbroek *
1987*d56f51eaSDavid van Moolenbroek * Ethernet_802.3 frames, which have a frame
1988*d56f51eaSDavid van Moolenbroek * type of LINUX_SLL_P_802_3;
1989*d56f51eaSDavid van Moolenbroek *
1990*d56f51eaSDavid van Moolenbroek * Ethernet_802.2 frames, which are 802.3
1991*d56f51eaSDavid van Moolenbroek * frames with an 802.2 LLC header (i.e, have
1992*d56f51eaSDavid van Moolenbroek * a frame type of LINUX_SLL_P_802_2) and
1993*d56f51eaSDavid van Moolenbroek * with the IPX LSAP as the DSAP in the LLC
1994*d56f51eaSDavid van Moolenbroek * header;
1995*d56f51eaSDavid van Moolenbroek *
1996*d56f51eaSDavid van Moolenbroek * Ethernet_SNAP frames, which are 802.3
1997*d56f51eaSDavid van Moolenbroek * frames with an LLC header and a SNAP
1998*d56f51eaSDavid van Moolenbroek * header and with an OUI of 0x000000
1999*d56f51eaSDavid van Moolenbroek * (encapsulated Ethernet) and a protocol
2000*d56f51eaSDavid van Moolenbroek * ID of ETHERTYPE_IPX in the SNAP header.
2001*d56f51eaSDavid van Moolenbroek *
2002*d56f51eaSDavid van Moolenbroek * First, do the checks on LINUX_SLL_P_802_2
2003*d56f51eaSDavid van Moolenbroek * frames; generate the check for either
2004*d56f51eaSDavid van Moolenbroek * Ethernet_802.2 or Ethernet_SNAP frames, and
2005*d56f51eaSDavid van Moolenbroek * then put a check for LINUX_SLL_P_802_2 frames
2006*d56f51eaSDavid van Moolenbroek * before it.
2007*d56f51eaSDavid van Moolenbroek */
2008*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
2009*d56f51eaSDavid van Moolenbroek b1 = gen_snap(0x000000, ETHERTYPE_IPX);
2010*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
2011*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
2012*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
2013*d56f51eaSDavid van Moolenbroek
2014*d56f51eaSDavid van Moolenbroek /*
2015*d56f51eaSDavid van Moolenbroek * Now check for 802.3 frames and OR that with
2016*d56f51eaSDavid van Moolenbroek * the previous test.
2017*d56f51eaSDavid van Moolenbroek */
2018*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_3);
2019*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
2020*d56f51eaSDavid van Moolenbroek
2021*d56f51eaSDavid van Moolenbroek /*
2022*d56f51eaSDavid van Moolenbroek * Now add the check for Ethernet_II frames, and
2023*d56f51eaSDavid van Moolenbroek * do that before checking for the other frame
2024*d56f51eaSDavid van Moolenbroek * types.
2025*d56f51eaSDavid van Moolenbroek */
2026*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
2027*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
2028*d56f51eaSDavid van Moolenbroek return b1;
2029*d56f51eaSDavid van Moolenbroek
2030*d56f51eaSDavid van Moolenbroek case ETHERTYPE_ATALK:
2031*d56f51eaSDavid van Moolenbroek case ETHERTYPE_AARP:
2032*d56f51eaSDavid van Moolenbroek /*
2033*d56f51eaSDavid van Moolenbroek * EtherTalk (AppleTalk protocols on Ethernet link
2034*d56f51eaSDavid van Moolenbroek * layer) may use 802.2 encapsulation.
2035*d56f51eaSDavid van Moolenbroek */
2036*d56f51eaSDavid van Moolenbroek
2037*d56f51eaSDavid van Moolenbroek /*
2038*d56f51eaSDavid van Moolenbroek * Check for 802.2 encapsulation (EtherTalk phase 2?);
2039*d56f51eaSDavid van Moolenbroek * we check for the 802.2 protocol type in the
2040*d56f51eaSDavid van Moolenbroek * "Ethernet type" field.
2041*d56f51eaSDavid van Moolenbroek */
2042*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
2043*d56f51eaSDavid van Moolenbroek
2044*d56f51eaSDavid van Moolenbroek /*
2045*d56f51eaSDavid van Moolenbroek * 802.2-encapsulated ETHERTYPE_ATALK packets are
2046*d56f51eaSDavid van Moolenbroek * SNAP packets with an organization code of
2047*d56f51eaSDavid van Moolenbroek * 0x080007 (Apple, for Appletalk) and a protocol
2048*d56f51eaSDavid van Moolenbroek * type of ETHERTYPE_ATALK (Appletalk).
2049*d56f51eaSDavid van Moolenbroek *
2050*d56f51eaSDavid van Moolenbroek * 802.2-encapsulated ETHERTYPE_AARP packets are
2051*d56f51eaSDavid van Moolenbroek * SNAP packets with an organization code of
2052*d56f51eaSDavid van Moolenbroek * 0x000000 (encapsulated Ethernet) and a protocol
2053*d56f51eaSDavid van Moolenbroek * type of ETHERTYPE_AARP (Appletalk ARP).
2054*d56f51eaSDavid van Moolenbroek */
2055*d56f51eaSDavid van Moolenbroek if (proto == ETHERTYPE_ATALK)
2056*d56f51eaSDavid van Moolenbroek b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
2057*d56f51eaSDavid van Moolenbroek else /* proto == ETHERTYPE_AARP */
2058*d56f51eaSDavid van Moolenbroek b1 = gen_snap(0x000000, ETHERTYPE_AARP);
2059*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
2060*d56f51eaSDavid van Moolenbroek
2061*d56f51eaSDavid van Moolenbroek /*
2062*d56f51eaSDavid van Moolenbroek * Check for Ethernet encapsulation (Ethertalk
2063*d56f51eaSDavid van Moolenbroek * phase 1?); we just check for the Ethernet
2064*d56f51eaSDavid van Moolenbroek * protocol type.
2065*d56f51eaSDavid van Moolenbroek */
2066*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
2067*d56f51eaSDavid van Moolenbroek
2068*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
2069*d56f51eaSDavid van Moolenbroek return b1;
2070*d56f51eaSDavid van Moolenbroek
2071*d56f51eaSDavid van Moolenbroek default:
2072*d56f51eaSDavid van Moolenbroek if (proto <= ETHERMTU) {
2073*d56f51eaSDavid van Moolenbroek /*
2074*d56f51eaSDavid van Moolenbroek * This is an LLC SAP value, so the frames
2075*d56f51eaSDavid van Moolenbroek * that match would be 802.2 frames.
2076*d56f51eaSDavid van Moolenbroek * Check for the 802.2 protocol type
2077*d56f51eaSDavid van Moolenbroek * in the "Ethernet type" field, and
2078*d56f51eaSDavid van Moolenbroek * then check the DSAP.
2079*d56f51eaSDavid van Moolenbroek */
2080*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
2081*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LINKHDR, off_linkpl.constant_part, BPF_B,
2082*d56f51eaSDavid van Moolenbroek (bpf_int32)proto);
2083*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
2084*d56f51eaSDavid van Moolenbroek return b1;
2085*d56f51eaSDavid van Moolenbroek } else {
2086*d56f51eaSDavid van Moolenbroek /*
2087*d56f51eaSDavid van Moolenbroek * This is an Ethernet type, so compare
2088*d56f51eaSDavid van Moolenbroek * the length/type field with it (if
2089*d56f51eaSDavid van Moolenbroek * the frame is an 802.2 frame, the length
2090*d56f51eaSDavid van Moolenbroek * field will be <= ETHERMTU, and, as
2091*d56f51eaSDavid van Moolenbroek * "proto" is > ETHERMTU, this test
2092*d56f51eaSDavid van Moolenbroek * will fail and the frame won't match,
2093*d56f51eaSDavid van Moolenbroek * which is what we want).
2094*d56f51eaSDavid van Moolenbroek */
2095*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
2096*d56f51eaSDavid van Moolenbroek }
2097*d56f51eaSDavid van Moolenbroek }
2098*d56f51eaSDavid van Moolenbroek }
2099*d56f51eaSDavid van Moolenbroek
2100*d56f51eaSDavid van Moolenbroek static struct slist *
gen_load_prism_llprefixlen()2101*d56f51eaSDavid van Moolenbroek gen_load_prism_llprefixlen()
2102*d56f51eaSDavid van Moolenbroek {
2103*d56f51eaSDavid van Moolenbroek struct slist *s1, *s2;
2104*d56f51eaSDavid van Moolenbroek struct slist *sjeq_avs_cookie;
2105*d56f51eaSDavid van Moolenbroek struct slist *sjcommon;
2106*d56f51eaSDavid van Moolenbroek
2107*d56f51eaSDavid van Moolenbroek /*
2108*d56f51eaSDavid van Moolenbroek * This code is not compatible with the optimizer, as
2109*d56f51eaSDavid van Moolenbroek * we are generating jmp instructions within a normal
2110*d56f51eaSDavid van Moolenbroek * slist of instructions
2111*d56f51eaSDavid van Moolenbroek */
2112*d56f51eaSDavid van Moolenbroek no_optimize = 1;
2113*d56f51eaSDavid van Moolenbroek
2114*d56f51eaSDavid van Moolenbroek /*
2115*d56f51eaSDavid van Moolenbroek * Generate code to load the length of the radio header into
2116*d56f51eaSDavid van Moolenbroek * the register assigned to hold that length, if one has been
2117*d56f51eaSDavid van Moolenbroek * assigned. (If one hasn't been assigned, no code we've
2118*d56f51eaSDavid van Moolenbroek * generated uses that prefix, so we don't need to generate any
2119*d56f51eaSDavid van Moolenbroek * code to load it.)
2120*d56f51eaSDavid van Moolenbroek *
2121*d56f51eaSDavid van Moolenbroek * Some Linux drivers use ARPHRD_IEEE80211_PRISM but sometimes
2122*d56f51eaSDavid van Moolenbroek * or always use the AVS header rather than the Prism header.
2123*d56f51eaSDavid van Moolenbroek * We load a 4-byte big-endian value at the beginning of the
2124*d56f51eaSDavid van Moolenbroek * raw packet data, and see whether, when masked with 0xFFFFF000,
2125*d56f51eaSDavid van Moolenbroek * it's equal to 0x80211000. If so, that indicates that it's
2126*d56f51eaSDavid van Moolenbroek * an AVS header (the masked-out bits are the version number).
2127*d56f51eaSDavid van Moolenbroek * Otherwise, it's a Prism header.
2128*d56f51eaSDavid van Moolenbroek *
2129*d56f51eaSDavid van Moolenbroek * XXX - the Prism header is also, in theory, variable-length,
2130*d56f51eaSDavid van Moolenbroek * but no known software generates headers that aren't 144
2131*d56f51eaSDavid van Moolenbroek * bytes long.
2132*d56f51eaSDavid van Moolenbroek */
2133*d56f51eaSDavid van Moolenbroek if (off_linkhdr.reg != -1) {
2134*d56f51eaSDavid van Moolenbroek /*
2135*d56f51eaSDavid van Moolenbroek * Load the cookie.
2136*d56f51eaSDavid van Moolenbroek */
2137*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
2138*d56f51eaSDavid van Moolenbroek s1->s.k = 0;
2139*d56f51eaSDavid van Moolenbroek
2140*d56f51eaSDavid van Moolenbroek /*
2141*d56f51eaSDavid van Moolenbroek * AND it with 0xFFFFF000.
2142*d56f51eaSDavid van Moolenbroek */
2143*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
2144*d56f51eaSDavid van Moolenbroek s2->s.k = 0xFFFFF000;
2145*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2146*d56f51eaSDavid van Moolenbroek
2147*d56f51eaSDavid van Moolenbroek /*
2148*d56f51eaSDavid van Moolenbroek * Compare with 0x80211000.
2149*d56f51eaSDavid van Moolenbroek */
2150*d56f51eaSDavid van Moolenbroek sjeq_avs_cookie = new_stmt(JMP(BPF_JEQ));
2151*d56f51eaSDavid van Moolenbroek sjeq_avs_cookie->s.k = 0x80211000;
2152*d56f51eaSDavid van Moolenbroek sappend(s1, sjeq_avs_cookie);
2153*d56f51eaSDavid van Moolenbroek
2154*d56f51eaSDavid van Moolenbroek /*
2155*d56f51eaSDavid van Moolenbroek * If it's AVS:
2156*d56f51eaSDavid van Moolenbroek *
2157*d56f51eaSDavid van Moolenbroek * The 4 bytes at an offset of 4 from the beginning of
2158*d56f51eaSDavid van Moolenbroek * the AVS header are the length of the AVS header.
2159*d56f51eaSDavid van Moolenbroek * That field is big-endian.
2160*d56f51eaSDavid van Moolenbroek */
2161*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
2162*d56f51eaSDavid van Moolenbroek s2->s.k = 4;
2163*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2164*d56f51eaSDavid van Moolenbroek sjeq_avs_cookie->s.jt = s2;
2165*d56f51eaSDavid van Moolenbroek
2166*d56f51eaSDavid van Moolenbroek /*
2167*d56f51eaSDavid van Moolenbroek * Now jump to the code to allocate a register
2168*d56f51eaSDavid van Moolenbroek * into which to save the header length and
2169*d56f51eaSDavid van Moolenbroek * store the length there. (The "jump always"
2170*d56f51eaSDavid van Moolenbroek * instruction needs to have the k field set;
2171*d56f51eaSDavid van Moolenbroek * it's added to the PC, so, as we're jumping
2172*d56f51eaSDavid van Moolenbroek * over a single instruction, it should be 1.)
2173*d56f51eaSDavid van Moolenbroek */
2174*d56f51eaSDavid van Moolenbroek sjcommon = new_stmt(JMP(BPF_JA));
2175*d56f51eaSDavid van Moolenbroek sjcommon->s.k = 1;
2176*d56f51eaSDavid van Moolenbroek sappend(s1, sjcommon);
2177*d56f51eaSDavid van Moolenbroek
2178*d56f51eaSDavid van Moolenbroek /*
2179*d56f51eaSDavid van Moolenbroek * Now for the code that handles the Prism header.
2180*d56f51eaSDavid van Moolenbroek * Just load the length of the Prism header (144)
2181*d56f51eaSDavid van Moolenbroek * into the A register. Have the test for an AVS
2182*d56f51eaSDavid van Moolenbroek * header branch here if we don't have an AVS header.
2183*d56f51eaSDavid van Moolenbroek */
2184*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_LD|BPF_W|BPF_IMM);
2185*d56f51eaSDavid van Moolenbroek s2->s.k = 144;
2186*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2187*d56f51eaSDavid van Moolenbroek sjeq_avs_cookie->s.jf = s2;
2188*d56f51eaSDavid van Moolenbroek
2189*d56f51eaSDavid van Moolenbroek /*
2190*d56f51eaSDavid van Moolenbroek * Now allocate a register to hold that value and store
2191*d56f51eaSDavid van Moolenbroek * it. The code for the AVS header will jump here after
2192*d56f51eaSDavid van Moolenbroek * loading the length of the AVS header.
2193*d56f51eaSDavid van Moolenbroek */
2194*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ST);
2195*d56f51eaSDavid van Moolenbroek s2->s.k = off_linkhdr.reg;
2196*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2197*d56f51eaSDavid van Moolenbroek sjcommon->s.jf = s2;
2198*d56f51eaSDavid van Moolenbroek
2199*d56f51eaSDavid van Moolenbroek /*
2200*d56f51eaSDavid van Moolenbroek * Now move it into the X register.
2201*d56f51eaSDavid van Moolenbroek */
2202*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_MISC|BPF_TAX);
2203*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2204*d56f51eaSDavid van Moolenbroek
2205*d56f51eaSDavid van Moolenbroek return (s1);
2206*d56f51eaSDavid van Moolenbroek } else
2207*d56f51eaSDavid van Moolenbroek return (NULL);
2208*d56f51eaSDavid van Moolenbroek }
2209*d56f51eaSDavid van Moolenbroek
2210*d56f51eaSDavid van Moolenbroek static struct slist *
gen_load_avs_llprefixlen()2211*d56f51eaSDavid van Moolenbroek gen_load_avs_llprefixlen()
2212*d56f51eaSDavid van Moolenbroek {
2213*d56f51eaSDavid van Moolenbroek struct slist *s1, *s2;
2214*d56f51eaSDavid van Moolenbroek
2215*d56f51eaSDavid van Moolenbroek /*
2216*d56f51eaSDavid van Moolenbroek * Generate code to load the length of the AVS header into
2217*d56f51eaSDavid van Moolenbroek * the register assigned to hold that length, if one has been
2218*d56f51eaSDavid van Moolenbroek * assigned. (If one hasn't been assigned, no code we've
2219*d56f51eaSDavid van Moolenbroek * generated uses that prefix, so we don't need to generate any
2220*d56f51eaSDavid van Moolenbroek * code to load it.)
2221*d56f51eaSDavid van Moolenbroek */
2222*d56f51eaSDavid van Moolenbroek if (off_linkhdr.reg != -1) {
2223*d56f51eaSDavid van Moolenbroek /*
2224*d56f51eaSDavid van Moolenbroek * The 4 bytes at an offset of 4 from the beginning of
2225*d56f51eaSDavid van Moolenbroek * the AVS header are the length of the AVS header.
2226*d56f51eaSDavid van Moolenbroek * That field is big-endian.
2227*d56f51eaSDavid van Moolenbroek */
2228*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
2229*d56f51eaSDavid van Moolenbroek s1->s.k = 4;
2230*d56f51eaSDavid van Moolenbroek
2231*d56f51eaSDavid van Moolenbroek /*
2232*d56f51eaSDavid van Moolenbroek * Now allocate a register to hold that value and store
2233*d56f51eaSDavid van Moolenbroek * it.
2234*d56f51eaSDavid van Moolenbroek */
2235*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ST);
2236*d56f51eaSDavid van Moolenbroek s2->s.k = off_linkhdr.reg;
2237*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2238*d56f51eaSDavid van Moolenbroek
2239*d56f51eaSDavid van Moolenbroek /*
2240*d56f51eaSDavid van Moolenbroek * Now move it into the X register.
2241*d56f51eaSDavid van Moolenbroek */
2242*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_MISC|BPF_TAX);
2243*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2244*d56f51eaSDavid van Moolenbroek
2245*d56f51eaSDavid van Moolenbroek return (s1);
2246*d56f51eaSDavid van Moolenbroek } else
2247*d56f51eaSDavid van Moolenbroek return (NULL);
2248*d56f51eaSDavid van Moolenbroek }
2249*d56f51eaSDavid van Moolenbroek
2250*d56f51eaSDavid van Moolenbroek static struct slist *
gen_load_radiotap_llprefixlen()2251*d56f51eaSDavid van Moolenbroek gen_load_radiotap_llprefixlen()
2252*d56f51eaSDavid van Moolenbroek {
2253*d56f51eaSDavid van Moolenbroek struct slist *s1, *s2;
2254*d56f51eaSDavid van Moolenbroek
2255*d56f51eaSDavid van Moolenbroek /*
2256*d56f51eaSDavid van Moolenbroek * Generate code to load the length of the radiotap header into
2257*d56f51eaSDavid van Moolenbroek * the register assigned to hold that length, if one has been
2258*d56f51eaSDavid van Moolenbroek * assigned. (If one hasn't been assigned, no code we've
2259*d56f51eaSDavid van Moolenbroek * generated uses that prefix, so we don't need to generate any
2260*d56f51eaSDavid van Moolenbroek * code to load it.)
2261*d56f51eaSDavid van Moolenbroek */
2262*d56f51eaSDavid van Moolenbroek if (off_linkhdr.reg != -1) {
2263*d56f51eaSDavid van Moolenbroek /*
2264*d56f51eaSDavid van Moolenbroek * The 2 bytes at offsets of 2 and 3 from the beginning
2265*d56f51eaSDavid van Moolenbroek * of the radiotap header are the length of the radiotap
2266*d56f51eaSDavid van Moolenbroek * header; unfortunately, it's little-endian, so we have
2267*d56f51eaSDavid van Moolenbroek * to load it a byte at a time and construct the value.
2268*d56f51eaSDavid van Moolenbroek */
2269*d56f51eaSDavid van Moolenbroek
2270*d56f51eaSDavid van Moolenbroek /*
2271*d56f51eaSDavid van Moolenbroek * Load the high-order byte, at an offset of 3, shift it
2272*d56f51eaSDavid van Moolenbroek * left a byte, and put the result in the X register.
2273*d56f51eaSDavid van Moolenbroek */
2274*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
2275*d56f51eaSDavid van Moolenbroek s1->s.k = 3;
2276*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
2277*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2278*d56f51eaSDavid van Moolenbroek s2->s.k = 8;
2279*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_MISC|BPF_TAX);
2280*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2281*d56f51eaSDavid van Moolenbroek
2282*d56f51eaSDavid van Moolenbroek /*
2283*d56f51eaSDavid van Moolenbroek * Load the next byte, at an offset of 2, and OR the
2284*d56f51eaSDavid van Moolenbroek * value from the X register into it.
2285*d56f51eaSDavid van Moolenbroek */
2286*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
2287*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2288*d56f51eaSDavid van Moolenbroek s2->s.k = 2;
2289*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X);
2290*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2291*d56f51eaSDavid van Moolenbroek
2292*d56f51eaSDavid van Moolenbroek /*
2293*d56f51eaSDavid van Moolenbroek * Now allocate a register to hold that value and store
2294*d56f51eaSDavid van Moolenbroek * it.
2295*d56f51eaSDavid van Moolenbroek */
2296*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ST);
2297*d56f51eaSDavid van Moolenbroek s2->s.k = off_linkhdr.reg;
2298*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2299*d56f51eaSDavid van Moolenbroek
2300*d56f51eaSDavid van Moolenbroek /*
2301*d56f51eaSDavid van Moolenbroek * Now move it into the X register.
2302*d56f51eaSDavid van Moolenbroek */
2303*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_MISC|BPF_TAX);
2304*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2305*d56f51eaSDavid van Moolenbroek
2306*d56f51eaSDavid van Moolenbroek return (s1);
2307*d56f51eaSDavid van Moolenbroek } else
2308*d56f51eaSDavid van Moolenbroek return (NULL);
2309*d56f51eaSDavid van Moolenbroek }
2310*d56f51eaSDavid van Moolenbroek
2311*d56f51eaSDavid van Moolenbroek /*
2312*d56f51eaSDavid van Moolenbroek * At the moment we treat PPI as normal Radiotap encoded
2313*d56f51eaSDavid van Moolenbroek * packets. The difference is in the function that generates
2314*d56f51eaSDavid van Moolenbroek * the code at the beginning to compute the header length.
2315*d56f51eaSDavid van Moolenbroek * Since this code generator of PPI supports bare 802.11
2316*d56f51eaSDavid van Moolenbroek * encapsulation only (i.e. the encapsulated DLT should be
2317*d56f51eaSDavid van Moolenbroek * DLT_IEEE802_11) we generate code to check for this too;
2318*d56f51eaSDavid van Moolenbroek * that's done in finish_parse().
2319*d56f51eaSDavid van Moolenbroek */
2320*d56f51eaSDavid van Moolenbroek static struct slist *
gen_load_ppi_llprefixlen()2321*d56f51eaSDavid van Moolenbroek gen_load_ppi_llprefixlen()
2322*d56f51eaSDavid van Moolenbroek {
2323*d56f51eaSDavid van Moolenbroek struct slist *s1, *s2;
2324*d56f51eaSDavid van Moolenbroek
2325*d56f51eaSDavid van Moolenbroek /*
2326*d56f51eaSDavid van Moolenbroek * Generate code to load the length of the radiotap header
2327*d56f51eaSDavid van Moolenbroek * into the register assigned to hold that length, if one has
2328*d56f51eaSDavid van Moolenbroek * been assigned.
2329*d56f51eaSDavid van Moolenbroek */
2330*d56f51eaSDavid van Moolenbroek if (off_linkhdr.reg != -1) {
2331*d56f51eaSDavid van Moolenbroek /*
2332*d56f51eaSDavid van Moolenbroek * The 2 bytes at offsets of 2 and 3 from the beginning
2333*d56f51eaSDavid van Moolenbroek * of the radiotap header are the length of the radiotap
2334*d56f51eaSDavid van Moolenbroek * header; unfortunately, it's little-endian, so we have
2335*d56f51eaSDavid van Moolenbroek * to load it a byte at a time and construct the value.
2336*d56f51eaSDavid van Moolenbroek */
2337*d56f51eaSDavid van Moolenbroek
2338*d56f51eaSDavid van Moolenbroek /*
2339*d56f51eaSDavid van Moolenbroek * Load the high-order byte, at an offset of 3, shift it
2340*d56f51eaSDavid van Moolenbroek * left a byte, and put the result in the X register.
2341*d56f51eaSDavid van Moolenbroek */
2342*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
2343*d56f51eaSDavid van Moolenbroek s1->s.k = 3;
2344*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
2345*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2346*d56f51eaSDavid van Moolenbroek s2->s.k = 8;
2347*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_MISC|BPF_TAX);
2348*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2349*d56f51eaSDavid van Moolenbroek
2350*d56f51eaSDavid van Moolenbroek /*
2351*d56f51eaSDavid van Moolenbroek * Load the next byte, at an offset of 2, and OR the
2352*d56f51eaSDavid van Moolenbroek * value from the X register into it.
2353*d56f51eaSDavid van Moolenbroek */
2354*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
2355*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2356*d56f51eaSDavid van Moolenbroek s2->s.k = 2;
2357*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X);
2358*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2359*d56f51eaSDavid van Moolenbroek
2360*d56f51eaSDavid van Moolenbroek /*
2361*d56f51eaSDavid van Moolenbroek * Now allocate a register to hold that value and store
2362*d56f51eaSDavid van Moolenbroek * it.
2363*d56f51eaSDavid van Moolenbroek */
2364*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ST);
2365*d56f51eaSDavid van Moolenbroek s2->s.k = off_linkhdr.reg;
2366*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2367*d56f51eaSDavid van Moolenbroek
2368*d56f51eaSDavid van Moolenbroek /*
2369*d56f51eaSDavid van Moolenbroek * Now move it into the X register.
2370*d56f51eaSDavid van Moolenbroek */
2371*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_MISC|BPF_TAX);
2372*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
2373*d56f51eaSDavid van Moolenbroek
2374*d56f51eaSDavid van Moolenbroek return (s1);
2375*d56f51eaSDavid van Moolenbroek } else
2376*d56f51eaSDavid van Moolenbroek return (NULL);
2377*d56f51eaSDavid van Moolenbroek }
2378*d56f51eaSDavid van Moolenbroek
2379*d56f51eaSDavid van Moolenbroek /*
2380*d56f51eaSDavid van Moolenbroek * Load a value relative to the beginning of the link-layer header after the 802.11
2381*d56f51eaSDavid van Moolenbroek * header, i.e. LLC_SNAP.
2382*d56f51eaSDavid van Moolenbroek * The link-layer header doesn't necessarily begin at the beginning
2383*d56f51eaSDavid van Moolenbroek * of the packet data; there might be a variable-length prefix containing
2384*d56f51eaSDavid van Moolenbroek * radio information.
2385*d56f51eaSDavid van Moolenbroek */
2386*d56f51eaSDavid van Moolenbroek static struct slist *
gen_load_802_11_header_len(struct slist * s,struct slist * snext)2387*d56f51eaSDavid van Moolenbroek gen_load_802_11_header_len(struct slist *s, struct slist *snext)
2388*d56f51eaSDavid van Moolenbroek {
2389*d56f51eaSDavid van Moolenbroek struct slist *s2;
2390*d56f51eaSDavid van Moolenbroek struct slist *sjset_data_frame_1;
2391*d56f51eaSDavid van Moolenbroek struct slist *sjset_data_frame_2;
2392*d56f51eaSDavid van Moolenbroek struct slist *sjset_qos;
2393*d56f51eaSDavid van Moolenbroek struct slist *sjset_radiotap_flags;
2394*d56f51eaSDavid van Moolenbroek struct slist *sjset_radiotap_tsft;
2395*d56f51eaSDavid van Moolenbroek struct slist *sjset_tsft_datapad, *sjset_notsft_datapad;
2396*d56f51eaSDavid van Moolenbroek struct slist *s_roundup;
2397*d56f51eaSDavid van Moolenbroek
2398*d56f51eaSDavid van Moolenbroek if (off_linkpl.reg == -1) {
2399*d56f51eaSDavid van Moolenbroek /*
2400*d56f51eaSDavid van Moolenbroek * No register has been assigned to the offset of
2401*d56f51eaSDavid van Moolenbroek * the link-layer payload, which means nobody needs
2402*d56f51eaSDavid van Moolenbroek * it; don't bother computing it - just return
2403*d56f51eaSDavid van Moolenbroek * what we already have.
2404*d56f51eaSDavid van Moolenbroek */
2405*d56f51eaSDavid van Moolenbroek return (s);
2406*d56f51eaSDavid van Moolenbroek }
2407*d56f51eaSDavid van Moolenbroek
2408*d56f51eaSDavid van Moolenbroek /*
2409*d56f51eaSDavid van Moolenbroek * This code is not compatible with the optimizer, as
2410*d56f51eaSDavid van Moolenbroek * we are generating jmp instructions within a normal
2411*d56f51eaSDavid van Moolenbroek * slist of instructions
2412*d56f51eaSDavid van Moolenbroek */
2413*d56f51eaSDavid van Moolenbroek no_optimize = 1;
2414*d56f51eaSDavid van Moolenbroek
2415*d56f51eaSDavid van Moolenbroek /*
2416*d56f51eaSDavid van Moolenbroek * If "s" is non-null, it has code to arrange that the X register
2417*d56f51eaSDavid van Moolenbroek * contains the length of the prefix preceding the link-layer
2418*d56f51eaSDavid van Moolenbroek * header.
2419*d56f51eaSDavid van Moolenbroek *
2420*d56f51eaSDavid van Moolenbroek * Otherwise, the length of the prefix preceding the link-layer
2421*d56f51eaSDavid van Moolenbroek * header is "off_outermostlinkhdr.constant_part".
2422*d56f51eaSDavid van Moolenbroek */
2423*d56f51eaSDavid van Moolenbroek if (s == NULL) {
2424*d56f51eaSDavid van Moolenbroek /*
2425*d56f51eaSDavid van Moolenbroek * There is no variable-length header preceding the
2426*d56f51eaSDavid van Moolenbroek * link-layer header.
2427*d56f51eaSDavid van Moolenbroek *
2428*d56f51eaSDavid van Moolenbroek * Load the length of the fixed-length prefix preceding
2429*d56f51eaSDavid van Moolenbroek * the link-layer header (if any) into the X register,
2430*d56f51eaSDavid van Moolenbroek * and store it in the off_linkpl.reg register.
2431*d56f51eaSDavid van Moolenbroek * That length is off_outermostlinkhdr.constant_part.
2432*d56f51eaSDavid van Moolenbroek */
2433*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_LDX|BPF_IMM);
2434*d56f51eaSDavid van Moolenbroek s->s.k = off_outermostlinkhdr.constant_part;
2435*d56f51eaSDavid van Moolenbroek }
2436*d56f51eaSDavid van Moolenbroek
2437*d56f51eaSDavid van Moolenbroek /*
2438*d56f51eaSDavid van Moolenbroek * The X register contains the offset of the beginning of the
2439*d56f51eaSDavid van Moolenbroek * link-layer header; add 24, which is the minimum length
2440*d56f51eaSDavid van Moolenbroek * of the MAC header for a data frame, to that, and store it
2441*d56f51eaSDavid van Moolenbroek * in off_linkpl.reg, and then load the Frame Control field,
2442*d56f51eaSDavid van Moolenbroek * which is at the offset in the X register, with an indexed load.
2443*d56f51eaSDavid van Moolenbroek */
2444*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_MISC|BPF_TXA);
2445*d56f51eaSDavid van Moolenbroek sappend(s, s2);
2446*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
2447*d56f51eaSDavid van Moolenbroek s2->s.k = 24;
2448*d56f51eaSDavid van Moolenbroek sappend(s, s2);
2449*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ST);
2450*d56f51eaSDavid van Moolenbroek s2->s.k = off_linkpl.reg;
2451*d56f51eaSDavid van Moolenbroek sappend(s, s2);
2452*d56f51eaSDavid van Moolenbroek
2453*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
2454*d56f51eaSDavid van Moolenbroek s2->s.k = 0;
2455*d56f51eaSDavid van Moolenbroek sappend(s, s2);
2456*d56f51eaSDavid van Moolenbroek
2457*d56f51eaSDavid van Moolenbroek /*
2458*d56f51eaSDavid van Moolenbroek * Check the Frame Control field to see if this is a data frame;
2459*d56f51eaSDavid van Moolenbroek * a data frame has the 0x08 bit (b3) in that field set and the
2460*d56f51eaSDavid van Moolenbroek * 0x04 bit (b2) clear.
2461*d56f51eaSDavid van Moolenbroek */
2462*d56f51eaSDavid van Moolenbroek sjset_data_frame_1 = new_stmt(JMP(BPF_JSET));
2463*d56f51eaSDavid van Moolenbroek sjset_data_frame_1->s.k = 0x08;
2464*d56f51eaSDavid van Moolenbroek sappend(s, sjset_data_frame_1);
2465*d56f51eaSDavid van Moolenbroek
2466*d56f51eaSDavid van Moolenbroek /*
2467*d56f51eaSDavid van Moolenbroek * If b3 is set, test b2, otherwise go to the first statement of
2468*d56f51eaSDavid van Moolenbroek * the rest of the program.
2469*d56f51eaSDavid van Moolenbroek */
2470*d56f51eaSDavid van Moolenbroek sjset_data_frame_1->s.jt = sjset_data_frame_2 = new_stmt(JMP(BPF_JSET));
2471*d56f51eaSDavid van Moolenbroek sjset_data_frame_2->s.k = 0x04;
2472*d56f51eaSDavid van Moolenbroek sappend(s, sjset_data_frame_2);
2473*d56f51eaSDavid van Moolenbroek sjset_data_frame_1->s.jf = snext;
2474*d56f51eaSDavid van Moolenbroek
2475*d56f51eaSDavid van Moolenbroek /*
2476*d56f51eaSDavid van Moolenbroek * If b2 is not set, this is a data frame; test the QoS bit.
2477*d56f51eaSDavid van Moolenbroek * Otherwise, go to the first statement of the rest of the
2478*d56f51eaSDavid van Moolenbroek * program.
2479*d56f51eaSDavid van Moolenbroek */
2480*d56f51eaSDavid van Moolenbroek sjset_data_frame_2->s.jt = snext;
2481*d56f51eaSDavid van Moolenbroek sjset_data_frame_2->s.jf = sjset_qos = new_stmt(JMP(BPF_JSET));
2482*d56f51eaSDavid van Moolenbroek sjset_qos->s.k = 0x80; /* QoS bit */
2483*d56f51eaSDavid van Moolenbroek sappend(s, sjset_qos);
2484*d56f51eaSDavid van Moolenbroek
2485*d56f51eaSDavid van Moolenbroek /*
2486*d56f51eaSDavid van Moolenbroek * If it's set, add 2 to off_linkpl.reg, to skip the QoS
2487*d56f51eaSDavid van Moolenbroek * field.
2488*d56f51eaSDavid van Moolenbroek * Otherwise, go to the first statement of the rest of the
2489*d56f51eaSDavid van Moolenbroek * program.
2490*d56f51eaSDavid van Moolenbroek */
2491*d56f51eaSDavid van Moolenbroek sjset_qos->s.jt = s2 = new_stmt(BPF_LD|BPF_MEM);
2492*d56f51eaSDavid van Moolenbroek s2->s.k = off_linkpl.reg;
2493*d56f51eaSDavid van Moolenbroek sappend(s, s2);
2494*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
2495*d56f51eaSDavid van Moolenbroek s2->s.k = 2;
2496*d56f51eaSDavid van Moolenbroek sappend(s, s2);
2497*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ST);
2498*d56f51eaSDavid van Moolenbroek s2->s.k = off_linkpl.reg;
2499*d56f51eaSDavid van Moolenbroek sappend(s, s2);
2500*d56f51eaSDavid van Moolenbroek
2501*d56f51eaSDavid van Moolenbroek /*
2502*d56f51eaSDavid van Moolenbroek * If we have a radiotap header, look at it to see whether
2503*d56f51eaSDavid van Moolenbroek * there's Atheros padding between the MAC-layer header
2504*d56f51eaSDavid van Moolenbroek * and the payload.
2505*d56f51eaSDavid van Moolenbroek *
2506*d56f51eaSDavid van Moolenbroek * Note: all of the fields in the radiotap header are
2507*d56f51eaSDavid van Moolenbroek * little-endian, so we byte-swap all of the values
2508*d56f51eaSDavid van Moolenbroek * we test against, as they will be loaded as big-endian
2509*d56f51eaSDavid van Moolenbroek * values.
2510*d56f51eaSDavid van Moolenbroek */
2511*d56f51eaSDavid van Moolenbroek if (linktype == DLT_IEEE802_11_RADIO) {
2512*d56f51eaSDavid van Moolenbroek /*
2513*d56f51eaSDavid van Moolenbroek * Is the IEEE80211_RADIOTAP_FLAGS bit (0x0000002) set
2514*d56f51eaSDavid van Moolenbroek * in the presence flag?
2515*d56f51eaSDavid van Moolenbroek */
2516*d56f51eaSDavid van Moolenbroek sjset_qos->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_W);
2517*d56f51eaSDavid van Moolenbroek s2->s.k = 4;
2518*d56f51eaSDavid van Moolenbroek sappend(s, s2);
2519*d56f51eaSDavid van Moolenbroek
2520*d56f51eaSDavid van Moolenbroek sjset_radiotap_flags = new_stmt(JMP(BPF_JSET));
2521*d56f51eaSDavid van Moolenbroek sjset_radiotap_flags->s.k = SWAPLONG(0x00000002);
2522*d56f51eaSDavid van Moolenbroek sappend(s, sjset_radiotap_flags);
2523*d56f51eaSDavid van Moolenbroek
2524*d56f51eaSDavid van Moolenbroek /*
2525*d56f51eaSDavid van Moolenbroek * If not, skip all of this.
2526*d56f51eaSDavid van Moolenbroek */
2527*d56f51eaSDavid van Moolenbroek sjset_radiotap_flags->s.jf = snext;
2528*d56f51eaSDavid van Moolenbroek
2529*d56f51eaSDavid van Moolenbroek /*
2530*d56f51eaSDavid van Moolenbroek * Otherwise, is the IEEE80211_RADIOTAP_TSFT bit set?
2531*d56f51eaSDavid van Moolenbroek */
2532*d56f51eaSDavid van Moolenbroek sjset_radiotap_tsft = sjset_radiotap_flags->s.jt =
2533*d56f51eaSDavid van Moolenbroek new_stmt(JMP(BPF_JSET));
2534*d56f51eaSDavid van Moolenbroek sjset_radiotap_tsft->s.k = SWAPLONG(0x00000001);
2535*d56f51eaSDavid van Moolenbroek sappend(s, sjset_radiotap_tsft);
2536*d56f51eaSDavid van Moolenbroek
2537*d56f51eaSDavid van Moolenbroek /*
2538*d56f51eaSDavid van Moolenbroek * If IEEE80211_RADIOTAP_TSFT is set, the flags field is
2539*d56f51eaSDavid van Moolenbroek * at an offset of 16 from the beginning of the raw packet
2540*d56f51eaSDavid van Moolenbroek * data (8 bytes for the radiotap header and 8 bytes for
2541*d56f51eaSDavid van Moolenbroek * the TSFT field).
2542*d56f51eaSDavid van Moolenbroek *
2543*d56f51eaSDavid van Moolenbroek * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
2544*d56f51eaSDavid van Moolenbroek * is set.
2545*d56f51eaSDavid van Moolenbroek */
2546*d56f51eaSDavid van Moolenbroek sjset_radiotap_tsft->s.jt = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
2547*d56f51eaSDavid van Moolenbroek s2->s.k = 16;
2548*d56f51eaSDavid van Moolenbroek sappend(s, s2);
2549*d56f51eaSDavid van Moolenbroek
2550*d56f51eaSDavid van Moolenbroek sjset_tsft_datapad = new_stmt(JMP(BPF_JSET));
2551*d56f51eaSDavid van Moolenbroek sjset_tsft_datapad->s.k = 0x20;
2552*d56f51eaSDavid van Moolenbroek sappend(s, sjset_tsft_datapad);
2553*d56f51eaSDavid van Moolenbroek
2554*d56f51eaSDavid van Moolenbroek /*
2555*d56f51eaSDavid van Moolenbroek * If IEEE80211_RADIOTAP_TSFT is not set, the flags field is
2556*d56f51eaSDavid van Moolenbroek * at an offset of 8 from the beginning of the raw packet
2557*d56f51eaSDavid van Moolenbroek * data (8 bytes for the radiotap header).
2558*d56f51eaSDavid van Moolenbroek *
2559*d56f51eaSDavid van Moolenbroek * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
2560*d56f51eaSDavid van Moolenbroek * is set.
2561*d56f51eaSDavid van Moolenbroek */
2562*d56f51eaSDavid van Moolenbroek sjset_radiotap_tsft->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
2563*d56f51eaSDavid van Moolenbroek s2->s.k = 8;
2564*d56f51eaSDavid van Moolenbroek sappend(s, s2);
2565*d56f51eaSDavid van Moolenbroek
2566*d56f51eaSDavid van Moolenbroek sjset_notsft_datapad = new_stmt(JMP(BPF_JSET));
2567*d56f51eaSDavid van Moolenbroek sjset_notsft_datapad->s.k = 0x20;
2568*d56f51eaSDavid van Moolenbroek sappend(s, sjset_notsft_datapad);
2569*d56f51eaSDavid van Moolenbroek
2570*d56f51eaSDavid van Moolenbroek /*
2571*d56f51eaSDavid van Moolenbroek * In either case, if IEEE80211_RADIOTAP_F_DATAPAD is
2572*d56f51eaSDavid van Moolenbroek * set, round the length of the 802.11 header to
2573*d56f51eaSDavid van Moolenbroek * a multiple of 4. Do that by adding 3 and then
2574*d56f51eaSDavid van Moolenbroek * dividing by and multiplying by 4, which we do by
2575*d56f51eaSDavid van Moolenbroek * ANDing with ~3.
2576*d56f51eaSDavid van Moolenbroek */
2577*d56f51eaSDavid van Moolenbroek s_roundup = new_stmt(BPF_LD|BPF_MEM);
2578*d56f51eaSDavid van Moolenbroek s_roundup->s.k = off_linkpl.reg;
2579*d56f51eaSDavid van Moolenbroek sappend(s, s_roundup);
2580*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
2581*d56f51eaSDavid van Moolenbroek s2->s.k = 3;
2582*d56f51eaSDavid van Moolenbroek sappend(s, s2);
2583*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ALU|BPF_AND|BPF_IMM);
2584*d56f51eaSDavid van Moolenbroek s2->s.k = ~3;
2585*d56f51eaSDavid van Moolenbroek sappend(s, s2);
2586*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ST);
2587*d56f51eaSDavid van Moolenbroek s2->s.k = off_linkpl.reg;
2588*d56f51eaSDavid van Moolenbroek sappend(s, s2);
2589*d56f51eaSDavid van Moolenbroek
2590*d56f51eaSDavid van Moolenbroek sjset_tsft_datapad->s.jt = s_roundup;
2591*d56f51eaSDavid van Moolenbroek sjset_tsft_datapad->s.jf = snext;
2592*d56f51eaSDavid van Moolenbroek sjset_notsft_datapad->s.jt = s_roundup;
2593*d56f51eaSDavid van Moolenbroek sjset_notsft_datapad->s.jf = snext;
2594*d56f51eaSDavid van Moolenbroek } else
2595*d56f51eaSDavid van Moolenbroek sjset_qos->s.jf = snext;
2596*d56f51eaSDavid van Moolenbroek
2597*d56f51eaSDavid van Moolenbroek return s;
2598*d56f51eaSDavid van Moolenbroek }
2599*d56f51eaSDavid van Moolenbroek
2600*d56f51eaSDavid van Moolenbroek static void
insert_compute_vloffsets(b)2601*d56f51eaSDavid van Moolenbroek insert_compute_vloffsets(b)
2602*d56f51eaSDavid van Moolenbroek struct block *b;
2603*d56f51eaSDavid van Moolenbroek {
2604*d56f51eaSDavid van Moolenbroek struct slist *s;
2605*d56f51eaSDavid van Moolenbroek
2606*d56f51eaSDavid van Moolenbroek /* There is an implicit dependency between the link
2607*d56f51eaSDavid van Moolenbroek * payload and link header since the payload computation
2608*d56f51eaSDavid van Moolenbroek * includes the variable part of the header. Therefore,
2609*d56f51eaSDavid van Moolenbroek * if nobody else has allocated a register for the link
2610*d56f51eaSDavid van Moolenbroek * header and we need it, do it now. */
2611*d56f51eaSDavid van Moolenbroek if (off_linkpl.reg != -1 && off_linkhdr.is_variable &&
2612*d56f51eaSDavid van Moolenbroek off_linkhdr.reg == -1)
2613*d56f51eaSDavid van Moolenbroek off_linkhdr.reg = alloc_reg();
2614*d56f51eaSDavid van Moolenbroek
2615*d56f51eaSDavid van Moolenbroek /*
2616*d56f51eaSDavid van Moolenbroek * For link-layer types that have a variable-length header
2617*d56f51eaSDavid van Moolenbroek * preceding the link-layer header, generate code to load
2618*d56f51eaSDavid van Moolenbroek * the offset of the link-layer header into the register
2619*d56f51eaSDavid van Moolenbroek * assigned to that offset, if any.
2620*d56f51eaSDavid van Moolenbroek *
2621*d56f51eaSDavid van Moolenbroek * XXX - this, and the next switch statement, won't handle
2622*d56f51eaSDavid van Moolenbroek * encapsulation of 802.11 or 802.11+radio information in
2623*d56f51eaSDavid van Moolenbroek * some other protocol stack. That's significantly more
2624*d56f51eaSDavid van Moolenbroek * complicated.
2625*d56f51eaSDavid van Moolenbroek */
2626*d56f51eaSDavid van Moolenbroek switch (outermostlinktype) {
2627*d56f51eaSDavid van Moolenbroek
2628*d56f51eaSDavid van Moolenbroek case DLT_PRISM_HEADER:
2629*d56f51eaSDavid van Moolenbroek s = gen_load_prism_llprefixlen();
2630*d56f51eaSDavid van Moolenbroek break;
2631*d56f51eaSDavid van Moolenbroek
2632*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO_AVS:
2633*d56f51eaSDavid van Moolenbroek s = gen_load_avs_llprefixlen();
2634*d56f51eaSDavid van Moolenbroek break;
2635*d56f51eaSDavid van Moolenbroek
2636*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO:
2637*d56f51eaSDavid van Moolenbroek s = gen_load_radiotap_llprefixlen();
2638*d56f51eaSDavid van Moolenbroek break;
2639*d56f51eaSDavid van Moolenbroek
2640*d56f51eaSDavid van Moolenbroek case DLT_PPI:
2641*d56f51eaSDavid van Moolenbroek s = gen_load_ppi_llprefixlen();
2642*d56f51eaSDavid van Moolenbroek break;
2643*d56f51eaSDavid van Moolenbroek
2644*d56f51eaSDavid van Moolenbroek default:
2645*d56f51eaSDavid van Moolenbroek s = NULL;
2646*d56f51eaSDavid van Moolenbroek break;
2647*d56f51eaSDavid van Moolenbroek }
2648*d56f51eaSDavid van Moolenbroek
2649*d56f51eaSDavid van Moolenbroek /*
2650*d56f51eaSDavid van Moolenbroek * For link-layer types that have a variable-length link-layer
2651*d56f51eaSDavid van Moolenbroek * header, generate code to load the offset of the link-layer
2652*d56f51eaSDavid van Moolenbroek * payload into the register assigned to that offset, if any.
2653*d56f51eaSDavid van Moolenbroek */
2654*d56f51eaSDavid van Moolenbroek switch (outermostlinktype) {
2655*d56f51eaSDavid van Moolenbroek
2656*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11:
2657*d56f51eaSDavid van Moolenbroek case DLT_PRISM_HEADER:
2658*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO_AVS:
2659*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO:
2660*d56f51eaSDavid van Moolenbroek case DLT_PPI:
2661*d56f51eaSDavid van Moolenbroek s = gen_load_802_11_header_len(s, b->stmts);
2662*d56f51eaSDavid van Moolenbroek break;
2663*d56f51eaSDavid van Moolenbroek }
2664*d56f51eaSDavid van Moolenbroek
2665*d56f51eaSDavid van Moolenbroek /*
2666*d56f51eaSDavid van Moolenbroek * If we have any offset-loading code, append all the
2667*d56f51eaSDavid van Moolenbroek * existing statements in the block to those statements,
2668*d56f51eaSDavid van Moolenbroek * and make the resulting list the list of statements
2669*d56f51eaSDavid van Moolenbroek * for the block.
2670*d56f51eaSDavid van Moolenbroek */
2671*d56f51eaSDavid van Moolenbroek if (s != NULL) {
2672*d56f51eaSDavid van Moolenbroek sappend(s, b->stmts);
2673*d56f51eaSDavid van Moolenbroek b->stmts = s;
2674*d56f51eaSDavid van Moolenbroek }
2675*d56f51eaSDavid van Moolenbroek }
2676*d56f51eaSDavid van Moolenbroek
2677*d56f51eaSDavid van Moolenbroek static struct block *
gen_ppi_dlt_check(void)2678*d56f51eaSDavid van Moolenbroek gen_ppi_dlt_check(void)
2679*d56f51eaSDavid van Moolenbroek {
2680*d56f51eaSDavid van Moolenbroek struct slist *s_load_dlt;
2681*d56f51eaSDavid van Moolenbroek struct block *b;
2682*d56f51eaSDavid van Moolenbroek
2683*d56f51eaSDavid van Moolenbroek if (linktype == DLT_PPI)
2684*d56f51eaSDavid van Moolenbroek {
2685*d56f51eaSDavid van Moolenbroek /* Create the statements that check for the DLT
2686*d56f51eaSDavid van Moolenbroek */
2687*d56f51eaSDavid van Moolenbroek s_load_dlt = new_stmt(BPF_LD|BPF_W|BPF_ABS);
2688*d56f51eaSDavid van Moolenbroek s_load_dlt->s.k = 4;
2689*d56f51eaSDavid van Moolenbroek
2690*d56f51eaSDavid van Moolenbroek b = new_block(JMP(BPF_JEQ));
2691*d56f51eaSDavid van Moolenbroek
2692*d56f51eaSDavid van Moolenbroek b->stmts = s_load_dlt;
2693*d56f51eaSDavid van Moolenbroek b->s.k = SWAPLONG(DLT_IEEE802_11);
2694*d56f51eaSDavid van Moolenbroek }
2695*d56f51eaSDavid van Moolenbroek else
2696*d56f51eaSDavid van Moolenbroek {
2697*d56f51eaSDavid van Moolenbroek b = NULL;
2698*d56f51eaSDavid van Moolenbroek }
2699*d56f51eaSDavid van Moolenbroek
2700*d56f51eaSDavid van Moolenbroek return b;
2701*d56f51eaSDavid van Moolenbroek }
2702*d56f51eaSDavid van Moolenbroek
2703*d56f51eaSDavid van Moolenbroek /*
2704*d56f51eaSDavid van Moolenbroek * Take an absolute offset, and:
2705*d56f51eaSDavid van Moolenbroek *
2706*d56f51eaSDavid van Moolenbroek * if it has no variable part, return NULL;
2707*d56f51eaSDavid van Moolenbroek *
2708*d56f51eaSDavid van Moolenbroek * if it has a variable part, generate code to load the register
2709*d56f51eaSDavid van Moolenbroek * containing that variable part into the X register, returning
2710*d56f51eaSDavid van Moolenbroek * a pointer to that code - if no register for that offset has
2711*d56f51eaSDavid van Moolenbroek * been allocated, allocate it first.
2712*d56f51eaSDavid van Moolenbroek *
2713*d56f51eaSDavid van Moolenbroek * (The code to set that register will be generated later, but will
2714*d56f51eaSDavid van Moolenbroek * be placed earlier in the code sequence.)
2715*d56f51eaSDavid van Moolenbroek */
2716*d56f51eaSDavid van Moolenbroek static struct slist *
gen_abs_offset_varpart(bpf_abs_offset * off)2717*d56f51eaSDavid van Moolenbroek gen_abs_offset_varpart(bpf_abs_offset *off)
2718*d56f51eaSDavid van Moolenbroek {
2719*d56f51eaSDavid van Moolenbroek struct slist *s;
2720*d56f51eaSDavid van Moolenbroek
2721*d56f51eaSDavid van Moolenbroek if (off->is_variable) {
2722*d56f51eaSDavid van Moolenbroek if (off->reg == -1) {
2723*d56f51eaSDavid van Moolenbroek /*
2724*d56f51eaSDavid van Moolenbroek * We haven't yet assigned a register for the
2725*d56f51eaSDavid van Moolenbroek * variable part of the offset of the link-layer
2726*d56f51eaSDavid van Moolenbroek * header; allocate one.
2727*d56f51eaSDavid van Moolenbroek */
2728*d56f51eaSDavid van Moolenbroek off->reg = alloc_reg();
2729*d56f51eaSDavid van Moolenbroek }
2730*d56f51eaSDavid van Moolenbroek
2731*d56f51eaSDavid van Moolenbroek /*
2732*d56f51eaSDavid van Moolenbroek * Load the register containing the variable part of the
2733*d56f51eaSDavid van Moolenbroek * offset of the link-layer header into the X register.
2734*d56f51eaSDavid van Moolenbroek */
2735*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_LDX|BPF_MEM);
2736*d56f51eaSDavid van Moolenbroek s->s.k = off->reg;
2737*d56f51eaSDavid van Moolenbroek return s;
2738*d56f51eaSDavid van Moolenbroek } else {
2739*d56f51eaSDavid van Moolenbroek /*
2740*d56f51eaSDavid van Moolenbroek * That offset isn't variable, there's no variable part,
2741*d56f51eaSDavid van Moolenbroek * so we don't need to generate any code.
2742*d56f51eaSDavid van Moolenbroek */
2743*d56f51eaSDavid van Moolenbroek return NULL;
2744*d56f51eaSDavid van Moolenbroek }
2745*d56f51eaSDavid van Moolenbroek }
2746*d56f51eaSDavid van Moolenbroek
2747*d56f51eaSDavid van Moolenbroek /*
2748*d56f51eaSDavid van Moolenbroek * Map an Ethernet type to the equivalent PPP type.
2749*d56f51eaSDavid van Moolenbroek */
2750*d56f51eaSDavid van Moolenbroek static int
ethertype_to_ppptype(proto)2751*d56f51eaSDavid van Moolenbroek ethertype_to_ppptype(proto)
2752*d56f51eaSDavid van Moolenbroek int proto;
2753*d56f51eaSDavid van Moolenbroek {
2754*d56f51eaSDavid van Moolenbroek switch (proto) {
2755*d56f51eaSDavid van Moolenbroek
2756*d56f51eaSDavid van Moolenbroek case ETHERTYPE_IP:
2757*d56f51eaSDavid van Moolenbroek proto = PPP_IP;
2758*d56f51eaSDavid van Moolenbroek break;
2759*d56f51eaSDavid van Moolenbroek
2760*d56f51eaSDavid van Moolenbroek case ETHERTYPE_IPV6:
2761*d56f51eaSDavid van Moolenbroek proto = PPP_IPV6;
2762*d56f51eaSDavid van Moolenbroek break;
2763*d56f51eaSDavid van Moolenbroek
2764*d56f51eaSDavid van Moolenbroek case ETHERTYPE_DN:
2765*d56f51eaSDavid van Moolenbroek proto = PPP_DECNET;
2766*d56f51eaSDavid van Moolenbroek break;
2767*d56f51eaSDavid van Moolenbroek
2768*d56f51eaSDavid van Moolenbroek case ETHERTYPE_ATALK:
2769*d56f51eaSDavid van Moolenbroek proto = PPP_APPLE;
2770*d56f51eaSDavid van Moolenbroek break;
2771*d56f51eaSDavid van Moolenbroek
2772*d56f51eaSDavid van Moolenbroek case ETHERTYPE_NS:
2773*d56f51eaSDavid van Moolenbroek proto = PPP_NS;
2774*d56f51eaSDavid van Moolenbroek break;
2775*d56f51eaSDavid van Moolenbroek
2776*d56f51eaSDavid van Moolenbroek case LLCSAP_ISONS:
2777*d56f51eaSDavid van Moolenbroek proto = PPP_OSI;
2778*d56f51eaSDavid van Moolenbroek break;
2779*d56f51eaSDavid van Moolenbroek
2780*d56f51eaSDavid van Moolenbroek case LLCSAP_8021D:
2781*d56f51eaSDavid van Moolenbroek /*
2782*d56f51eaSDavid van Moolenbroek * I'm assuming the "Bridging PDU"s that go
2783*d56f51eaSDavid van Moolenbroek * over PPP are Spanning Tree Protocol
2784*d56f51eaSDavid van Moolenbroek * Bridging PDUs.
2785*d56f51eaSDavid van Moolenbroek */
2786*d56f51eaSDavid van Moolenbroek proto = PPP_BRPDU;
2787*d56f51eaSDavid van Moolenbroek break;
2788*d56f51eaSDavid van Moolenbroek
2789*d56f51eaSDavid van Moolenbroek case LLCSAP_IPX:
2790*d56f51eaSDavid van Moolenbroek proto = PPP_IPX;
2791*d56f51eaSDavid van Moolenbroek break;
2792*d56f51eaSDavid van Moolenbroek }
2793*d56f51eaSDavid van Moolenbroek return (proto);
2794*d56f51eaSDavid van Moolenbroek }
2795*d56f51eaSDavid van Moolenbroek
2796*d56f51eaSDavid van Moolenbroek /*
2797*d56f51eaSDavid van Moolenbroek * Generate any tests that, for encapsulation of a link-layer packet
2798*d56f51eaSDavid van Moolenbroek * inside another protocol stack, need to be done to check for those
2799*d56f51eaSDavid van Moolenbroek * link-layer packets (and that haven't already been done by a check
2800*d56f51eaSDavid van Moolenbroek * for that encapsulation).
2801*d56f51eaSDavid van Moolenbroek */
2802*d56f51eaSDavid van Moolenbroek static struct block *
gen_prevlinkhdr_check(void)2803*d56f51eaSDavid van Moolenbroek gen_prevlinkhdr_check(void)
2804*d56f51eaSDavid van Moolenbroek {
2805*d56f51eaSDavid van Moolenbroek struct block *b0;
2806*d56f51eaSDavid van Moolenbroek
2807*d56f51eaSDavid van Moolenbroek if (is_geneve)
2808*d56f51eaSDavid van Moolenbroek return gen_geneve_ll_check();
2809*d56f51eaSDavid van Moolenbroek
2810*d56f51eaSDavid van Moolenbroek switch (prevlinktype) {
2811*d56f51eaSDavid van Moolenbroek
2812*d56f51eaSDavid van Moolenbroek case DLT_SUNATM:
2813*d56f51eaSDavid van Moolenbroek /*
2814*d56f51eaSDavid van Moolenbroek * This is LANE-encapsulated Ethernet; check that the LANE
2815*d56f51eaSDavid van Moolenbroek * packet doesn't begin with an LE Control marker, i.e.
2816*d56f51eaSDavid van Moolenbroek * that it's data, not a control message.
2817*d56f51eaSDavid van Moolenbroek *
2818*d56f51eaSDavid van Moolenbroek * (We've already generated a test for LANE.)
2819*d56f51eaSDavid van Moolenbroek */
2820*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_PREVLINKHDR, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
2821*d56f51eaSDavid van Moolenbroek gen_not(b0);
2822*d56f51eaSDavid van Moolenbroek return b0;
2823*d56f51eaSDavid van Moolenbroek
2824*d56f51eaSDavid van Moolenbroek default:
2825*d56f51eaSDavid van Moolenbroek /*
2826*d56f51eaSDavid van Moolenbroek * No such tests are necessary.
2827*d56f51eaSDavid van Moolenbroek */
2828*d56f51eaSDavid van Moolenbroek return NULL;
2829*d56f51eaSDavid van Moolenbroek }
2830*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
2831*d56f51eaSDavid van Moolenbroek }
2832*d56f51eaSDavid van Moolenbroek
2833*d56f51eaSDavid van Moolenbroek /*
2834*d56f51eaSDavid van Moolenbroek * Generate code to match a particular packet type by matching the
2835*d56f51eaSDavid van Moolenbroek * link-layer type field or fields in the 802.2 LLC header.
2836*d56f51eaSDavid van Moolenbroek *
2837*d56f51eaSDavid van Moolenbroek * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
2838*d56f51eaSDavid van Moolenbroek * value, if <= ETHERMTU.
2839*d56f51eaSDavid van Moolenbroek */
2840*d56f51eaSDavid van Moolenbroek static struct block *
gen_linktype(proto)2841*d56f51eaSDavid van Moolenbroek gen_linktype(proto)
2842*d56f51eaSDavid van Moolenbroek register int proto;
2843*d56f51eaSDavid van Moolenbroek {
2844*d56f51eaSDavid van Moolenbroek struct block *b0, *b1, *b2;
2845*d56f51eaSDavid van Moolenbroek const char *description;
2846*d56f51eaSDavid van Moolenbroek
2847*d56f51eaSDavid van Moolenbroek /* are we checking MPLS-encapsulated packets? */
2848*d56f51eaSDavid van Moolenbroek if (label_stack_depth > 0) {
2849*d56f51eaSDavid van Moolenbroek switch (proto) {
2850*d56f51eaSDavid van Moolenbroek case ETHERTYPE_IP:
2851*d56f51eaSDavid van Moolenbroek case PPP_IP:
2852*d56f51eaSDavid van Moolenbroek /* FIXME add other L3 proto IDs */
2853*d56f51eaSDavid van Moolenbroek return gen_mpls_linktype(Q_IP);
2854*d56f51eaSDavid van Moolenbroek
2855*d56f51eaSDavid van Moolenbroek case ETHERTYPE_IPV6:
2856*d56f51eaSDavid van Moolenbroek case PPP_IPV6:
2857*d56f51eaSDavid van Moolenbroek /* FIXME add other L3 proto IDs */
2858*d56f51eaSDavid van Moolenbroek return gen_mpls_linktype(Q_IPV6);
2859*d56f51eaSDavid van Moolenbroek
2860*d56f51eaSDavid van Moolenbroek default:
2861*d56f51eaSDavid van Moolenbroek bpf_error("unsupported protocol over mpls");
2862*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
2863*d56f51eaSDavid van Moolenbroek }
2864*d56f51eaSDavid van Moolenbroek }
2865*d56f51eaSDavid van Moolenbroek
2866*d56f51eaSDavid van Moolenbroek switch (linktype) {
2867*d56f51eaSDavid van Moolenbroek
2868*d56f51eaSDavid van Moolenbroek case DLT_EN10MB:
2869*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER:
2870*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER_TRANSPARENT:
2871*d56f51eaSDavid van Moolenbroek /* Geneve has an EtherType regardless of whether there is an
2872*d56f51eaSDavid van Moolenbroek * L2 header. */
2873*d56f51eaSDavid van Moolenbroek if (!is_geneve)
2874*d56f51eaSDavid van Moolenbroek b0 = gen_prevlinkhdr_check();
2875*d56f51eaSDavid van Moolenbroek else
2876*d56f51eaSDavid van Moolenbroek b0 = NULL;
2877*d56f51eaSDavid van Moolenbroek
2878*d56f51eaSDavid van Moolenbroek b1 = gen_ether_linktype(proto);
2879*d56f51eaSDavid van Moolenbroek if (b0 != NULL)
2880*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
2881*d56f51eaSDavid van Moolenbroek return b1;
2882*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
2883*d56f51eaSDavid van Moolenbroek break;
2884*d56f51eaSDavid van Moolenbroek
2885*d56f51eaSDavid van Moolenbroek case DLT_C_HDLC:
2886*d56f51eaSDavid van Moolenbroek switch (proto) {
2887*d56f51eaSDavid van Moolenbroek
2888*d56f51eaSDavid van Moolenbroek case LLCSAP_ISONS:
2889*d56f51eaSDavid van Moolenbroek proto = (proto << 8 | LLCSAP_ISONS);
2890*d56f51eaSDavid van Moolenbroek /* fall through */
2891*d56f51eaSDavid van Moolenbroek
2892*d56f51eaSDavid van Moolenbroek default:
2893*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
2894*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
2895*d56f51eaSDavid van Moolenbroek break;
2896*d56f51eaSDavid van Moolenbroek }
2897*d56f51eaSDavid van Moolenbroek break;
2898*d56f51eaSDavid van Moolenbroek
2899*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11:
2900*d56f51eaSDavid van Moolenbroek case DLT_PRISM_HEADER:
2901*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO_AVS:
2902*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO:
2903*d56f51eaSDavid van Moolenbroek case DLT_PPI:
2904*d56f51eaSDavid van Moolenbroek /*
2905*d56f51eaSDavid van Moolenbroek * Check that we have a data frame.
2906*d56f51eaSDavid van Moolenbroek */
2907*d56f51eaSDavid van Moolenbroek b0 = gen_check_802_11_data_frame();
2908*d56f51eaSDavid van Moolenbroek
2909*d56f51eaSDavid van Moolenbroek /*
2910*d56f51eaSDavid van Moolenbroek * Now check for the specified link-layer type.
2911*d56f51eaSDavid van Moolenbroek */
2912*d56f51eaSDavid van Moolenbroek b1 = gen_llc_linktype(proto);
2913*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
2914*d56f51eaSDavid van Moolenbroek return b1;
2915*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
2916*d56f51eaSDavid van Moolenbroek break;
2917*d56f51eaSDavid van Moolenbroek
2918*d56f51eaSDavid van Moolenbroek case DLT_FDDI:
2919*d56f51eaSDavid van Moolenbroek /*
2920*d56f51eaSDavid van Moolenbroek * XXX - check for LLC frames.
2921*d56f51eaSDavid van Moolenbroek */
2922*d56f51eaSDavid van Moolenbroek return gen_llc_linktype(proto);
2923*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
2924*d56f51eaSDavid van Moolenbroek break;
2925*d56f51eaSDavid van Moolenbroek
2926*d56f51eaSDavid van Moolenbroek case DLT_IEEE802:
2927*d56f51eaSDavid van Moolenbroek /*
2928*d56f51eaSDavid van Moolenbroek * XXX - check for LLC PDUs, as per IEEE 802.5.
2929*d56f51eaSDavid van Moolenbroek */
2930*d56f51eaSDavid van Moolenbroek return gen_llc_linktype(proto);
2931*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
2932*d56f51eaSDavid van Moolenbroek break;
2933*d56f51eaSDavid van Moolenbroek
2934*d56f51eaSDavid van Moolenbroek case DLT_ATM_RFC1483:
2935*d56f51eaSDavid van Moolenbroek case DLT_ATM_CLIP:
2936*d56f51eaSDavid van Moolenbroek case DLT_IP_OVER_FC:
2937*d56f51eaSDavid van Moolenbroek return gen_llc_linktype(proto);
2938*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
2939*d56f51eaSDavid van Moolenbroek break;
2940*d56f51eaSDavid van Moolenbroek
2941*d56f51eaSDavid van Moolenbroek case DLT_SUNATM:
2942*d56f51eaSDavid van Moolenbroek /*
2943*d56f51eaSDavid van Moolenbroek * Check for an LLC-encapsulated version of this protocol;
2944*d56f51eaSDavid van Moolenbroek * if we were checking for LANE, linktype would no longer
2945*d56f51eaSDavid van Moolenbroek * be DLT_SUNATM.
2946*d56f51eaSDavid van Moolenbroek *
2947*d56f51eaSDavid van Moolenbroek * Check for LLC encapsulation and then check the protocol.
2948*d56f51eaSDavid van Moolenbroek */
2949*d56f51eaSDavid van Moolenbroek b0 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
2950*d56f51eaSDavid van Moolenbroek b1 = gen_llc_linktype(proto);
2951*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
2952*d56f51eaSDavid van Moolenbroek return b1;
2953*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
2954*d56f51eaSDavid van Moolenbroek break;
2955*d56f51eaSDavid van Moolenbroek
2956*d56f51eaSDavid van Moolenbroek case DLT_LINUX_SLL:
2957*d56f51eaSDavid van Moolenbroek return gen_linux_sll_linktype(proto);
2958*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
2959*d56f51eaSDavid van Moolenbroek break;
2960*d56f51eaSDavid van Moolenbroek
2961*d56f51eaSDavid van Moolenbroek case DLT_SLIP:
2962*d56f51eaSDavid van Moolenbroek case DLT_SLIP_BSDOS:
2963*d56f51eaSDavid van Moolenbroek case DLT_RAW:
2964*d56f51eaSDavid van Moolenbroek /*
2965*d56f51eaSDavid van Moolenbroek * These types don't provide any type field; packets
2966*d56f51eaSDavid van Moolenbroek * are always IPv4 or IPv6.
2967*d56f51eaSDavid van Moolenbroek *
2968*d56f51eaSDavid van Moolenbroek * XXX - for IPv4, check for a version number of 4, and,
2969*d56f51eaSDavid van Moolenbroek * for IPv6, check for a version number of 6?
2970*d56f51eaSDavid van Moolenbroek */
2971*d56f51eaSDavid van Moolenbroek switch (proto) {
2972*d56f51eaSDavid van Moolenbroek
2973*d56f51eaSDavid van Moolenbroek case ETHERTYPE_IP:
2974*d56f51eaSDavid van Moolenbroek /* Check for a version number of 4. */
2975*d56f51eaSDavid van Moolenbroek return gen_mcmp(OR_LINKHDR, 0, BPF_B, 0x40, 0xF0);
2976*d56f51eaSDavid van Moolenbroek
2977*d56f51eaSDavid van Moolenbroek case ETHERTYPE_IPV6:
2978*d56f51eaSDavid van Moolenbroek /* Check for a version number of 6. */
2979*d56f51eaSDavid van Moolenbroek return gen_mcmp(OR_LINKHDR, 0, BPF_B, 0x60, 0xF0);
2980*d56f51eaSDavid van Moolenbroek
2981*d56f51eaSDavid van Moolenbroek default:
2982*d56f51eaSDavid van Moolenbroek return gen_false(); /* always false */
2983*d56f51eaSDavid van Moolenbroek }
2984*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
2985*d56f51eaSDavid van Moolenbroek break;
2986*d56f51eaSDavid van Moolenbroek
2987*d56f51eaSDavid van Moolenbroek case DLT_IPV4:
2988*d56f51eaSDavid van Moolenbroek /*
2989*d56f51eaSDavid van Moolenbroek * Raw IPv4, so no type field.
2990*d56f51eaSDavid van Moolenbroek */
2991*d56f51eaSDavid van Moolenbroek if (proto == ETHERTYPE_IP)
2992*d56f51eaSDavid van Moolenbroek return gen_true(); /* always true */
2993*d56f51eaSDavid van Moolenbroek
2994*d56f51eaSDavid van Moolenbroek /* Checking for something other than IPv4; always false */
2995*d56f51eaSDavid van Moolenbroek return gen_false();
2996*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
2997*d56f51eaSDavid van Moolenbroek break;
2998*d56f51eaSDavid van Moolenbroek
2999*d56f51eaSDavid van Moolenbroek case DLT_IPV6:
3000*d56f51eaSDavid van Moolenbroek /*
3001*d56f51eaSDavid van Moolenbroek * Raw IPv6, so no type field.
3002*d56f51eaSDavid van Moolenbroek */
3003*d56f51eaSDavid van Moolenbroek if (proto == ETHERTYPE_IPV6)
3004*d56f51eaSDavid van Moolenbroek return gen_true(); /* always true */
3005*d56f51eaSDavid van Moolenbroek
3006*d56f51eaSDavid van Moolenbroek /* Checking for something other than IPv6; always false */
3007*d56f51eaSDavid van Moolenbroek return gen_false();
3008*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
3009*d56f51eaSDavid van Moolenbroek break;
3010*d56f51eaSDavid van Moolenbroek
3011*d56f51eaSDavid van Moolenbroek case DLT_PPP:
3012*d56f51eaSDavid van Moolenbroek case DLT_PPP_PPPD:
3013*d56f51eaSDavid van Moolenbroek case DLT_PPP_SERIAL:
3014*d56f51eaSDavid van Moolenbroek case DLT_PPP_ETHER:
3015*d56f51eaSDavid van Moolenbroek /*
3016*d56f51eaSDavid van Moolenbroek * We use Ethernet protocol types inside libpcap;
3017*d56f51eaSDavid van Moolenbroek * map them to the corresponding PPP protocol types.
3018*d56f51eaSDavid van Moolenbroek */
3019*d56f51eaSDavid van Moolenbroek proto = ethertype_to_ppptype(proto);
3020*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
3021*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
3022*d56f51eaSDavid van Moolenbroek break;
3023*d56f51eaSDavid van Moolenbroek
3024*d56f51eaSDavid van Moolenbroek case DLT_PPP_BSDOS:
3025*d56f51eaSDavid van Moolenbroek /*
3026*d56f51eaSDavid van Moolenbroek * We use Ethernet protocol types inside libpcap;
3027*d56f51eaSDavid van Moolenbroek * map them to the corresponding PPP protocol types.
3028*d56f51eaSDavid van Moolenbroek */
3029*d56f51eaSDavid van Moolenbroek switch (proto) {
3030*d56f51eaSDavid van Moolenbroek
3031*d56f51eaSDavid van Moolenbroek case ETHERTYPE_IP:
3032*d56f51eaSDavid van Moolenbroek /*
3033*d56f51eaSDavid van Moolenbroek * Also check for Van Jacobson-compressed IP.
3034*d56f51eaSDavid van Moolenbroek * XXX - do this for other forms of PPP?
3035*d56f51eaSDavid van Moolenbroek */
3036*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, PPP_IP);
3037*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LINKTYPE, 0, BPF_H, PPP_VJC);
3038*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
3039*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKTYPE, 0, BPF_H, PPP_VJNC);
3040*d56f51eaSDavid van Moolenbroek gen_or(b1, b0);
3041*d56f51eaSDavid van Moolenbroek return b0;
3042*d56f51eaSDavid van Moolenbroek
3043*d56f51eaSDavid van Moolenbroek default:
3044*d56f51eaSDavid van Moolenbroek proto = ethertype_to_ppptype(proto);
3045*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_LINKTYPE, 0, BPF_H,
3046*d56f51eaSDavid van Moolenbroek (bpf_int32)proto);
3047*d56f51eaSDavid van Moolenbroek }
3048*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
3049*d56f51eaSDavid van Moolenbroek break;
3050*d56f51eaSDavid van Moolenbroek
3051*d56f51eaSDavid van Moolenbroek case DLT_NULL:
3052*d56f51eaSDavid van Moolenbroek case DLT_LOOP:
3053*d56f51eaSDavid van Moolenbroek case DLT_ENC:
3054*d56f51eaSDavid van Moolenbroek /*
3055*d56f51eaSDavid van Moolenbroek * For DLT_NULL, the link-layer header is a 32-bit
3056*d56f51eaSDavid van Moolenbroek * word containing an AF_ value in *host* byte order,
3057*d56f51eaSDavid van Moolenbroek * and for DLT_ENC, the link-layer header begins
3058*d56f51eaSDavid van Moolenbroek * with a 32-bit work containing an AF_ value in
3059*d56f51eaSDavid van Moolenbroek * host byte order.
3060*d56f51eaSDavid van Moolenbroek *
3061*d56f51eaSDavid van Moolenbroek * In addition, if we're reading a saved capture file,
3062*d56f51eaSDavid van Moolenbroek * the host byte order in the capture may not be the
3063*d56f51eaSDavid van Moolenbroek * same as the host byte order on this machine.
3064*d56f51eaSDavid van Moolenbroek *
3065*d56f51eaSDavid van Moolenbroek * For DLT_LOOP, the link-layer header is a 32-bit
3066*d56f51eaSDavid van Moolenbroek * word containing an AF_ value in *network* byte order.
3067*d56f51eaSDavid van Moolenbroek *
3068*d56f51eaSDavid van Moolenbroek * XXX - AF_ values may, unfortunately, be platform-
3069*d56f51eaSDavid van Moolenbroek * dependent; for example, FreeBSD's AF_INET6 is 24
3070*d56f51eaSDavid van Moolenbroek * whilst NetBSD's and OpenBSD's is 26.
3071*d56f51eaSDavid van Moolenbroek *
3072*d56f51eaSDavid van Moolenbroek * This means that, when reading a capture file, just
3073*d56f51eaSDavid van Moolenbroek * checking for our AF_INET6 value won't work if the
3074*d56f51eaSDavid van Moolenbroek * capture file came from another OS.
3075*d56f51eaSDavid van Moolenbroek */
3076*d56f51eaSDavid van Moolenbroek switch (proto) {
3077*d56f51eaSDavid van Moolenbroek
3078*d56f51eaSDavid van Moolenbroek case ETHERTYPE_IP:
3079*d56f51eaSDavid van Moolenbroek proto = AF_INET;
3080*d56f51eaSDavid van Moolenbroek break;
3081*d56f51eaSDavid van Moolenbroek
3082*d56f51eaSDavid van Moolenbroek #ifdef INET6
3083*d56f51eaSDavid van Moolenbroek case ETHERTYPE_IPV6:
3084*d56f51eaSDavid van Moolenbroek proto = AF_INET6;
3085*d56f51eaSDavid van Moolenbroek break;
3086*d56f51eaSDavid van Moolenbroek #endif
3087*d56f51eaSDavid van Moolenbroek
3088*d56f51eaSDavid van Moolenbroek default:
3089*d56f51eaSDavid van Moolenbroek /*
3090*d56f51eaSDavid van Moolenbroek * Not a type on which we support filtering.
3091*d56f51eaSDavid van Moolenbroek * XXX - support those that have AF_ values
3092*d56f51eaSDavid van Moolenbroek * #defined on this platform, at least?
3093*d56f51eaSDavid van Moolenbroek */
3094*d56f51eaSDavid van Moolenbroek return gen_false();
3095*d56f51eaSDavid van Moolenbroek }
3096*d56f51eaSDavid van Moolenbroek
3097*d56f51eaSDavid van Moolenbroek if (linktype == DLT_NULL || linktype == DLT_ENC) {
3098*d56f51eaSDavid van Moolenbroek /*
3099*d56f51eaSDavid van Moolenbroek * The AF_ value is in host byte order, but
3100*d56f51eaSDavid van Moolenbroek * the BPF interpreter will convert it to
3101*d56f51eaSDavid van Moolenbroek * network byte order.
3102*d56f51eaSDavid van Moolenbroek *
3103*d56f51eaSDavid van Moolenbroek * If this is a save file, and it's from a
3104*d56f51eaSDavid van Moolenbroek * machine with the opposite byte order to
3105*d56f51eaSDavid van Moolenbroek * ours, we byte-swap the AF_ value.
3106*d56f51eaSDavid van Moolenbroek *
3107*d56f51eaSDavid van Moolenbroek * Then we run it through "htonl()", and
3108*d56f51eaSDavid van Moolenbroek * generate code to compare against the result.
3109*d56f51eaSDavid van Moolenbroek */
3110*d56f51eaSDavid van Moolenbroek if (bpf_pcap->rfile != NULL && bpf_pcap->swapped)
3111*d56f51eaSDavid van Moolenbroek proto = SWAPLONG(proto);
3112*d56f51eaSDavid van Moolenbroek proto = htonl(proto);
3113*d56f51eaSDavid van Moolenbroek }
3114*d56f51eaSDavid van Moolenbroek return (gen_cmp(OR_LINKHDR, 0, BPF_W, (bpf_int32)proto));
3115*d56f51eaSDavid van Moolenbroek
3116*d56f51eaSDavid van Moolenbroek #ifdef HAVE_NET_PFVAR_H
3117*d56f51eaSDavid van Moolenbroek case DLT_PFLOG:
3118*d56f51eaSDavid van Moolenbroek /*
3119*d56f51eaSDavid van Moolenbroek * af field is host byte order in contrast to the rest of
3120*d56f51eaSDavid van Moolenbroek * the packet.
3121*d56f51eaSDavid van Moolenbroek */
3122*d56f51eaSDavid van Moolenbroek if (proto == ETHERTYPE_IP)
3123*d56f51eaSDavid van Moolenbroek return (gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, af),
3124*d56f51eaSDavid van Moolenbroek BPF_B, (bpf_int32)AF_INET));
3125*d56f51eaSDavid van Moolenbroek else if (proto == ETHERTYPE_IPV6)
3126*d56f51eaSDavid van Moolenbroek return (gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, af),
3127*d56f51eaSDavid van Moolenbroek BPF_B, (bpf_int32)AF_INET6));
3128*d56f51eaSDavid van Moolenbroek else
3129*d56f51eaSDavid van Moolenbroek return gen_false();
3130*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
3131*d56f51eaSDavid van Moolenbroek break;
3132*d56f51eaSDavid van Moolenbroek #endif /* HAVE_NET_PFVAR_H */
3133*d56f51eaSDavid van Moolenbroek
3134*d56f51eaSDavid van Moolenbroek case DLT_ARCNET:
3135*d56f51eaSDavid van Moolenbroek case DLT_ARCNET_LINUX:
3136*d56f51eaSDavid van Moolenbroek /*
3137*d56f51eaSDavid van Moolenbroek * XXX should we check for first fragment if the protocol
3138*d56f51eaSDavid van Moolenbroek * uses PHDS?
3139*d56f51eaSDavid van Moolenbroek */
3140*d56f51eaSDavid van Moolenbroek switch (proto) {
3141*d56f51eaSDavid van Moolenbroek
3142*d56f51eaSDavid van Moolenbroek default:
3143*d56f51eaSDavid van Moolenbroek return gen_false();
3144*d56f51eaSDavid van Moolenbroek
3145*d56f51eaSDavid van Moolenbroek case ETHERTYPE_IPV6:
3146*d56f51eaSDavid van Moolenbroek return (gen_cmp(OR_LINKTYPE, 0, BPF_B,
3147*d56f51eaSDavid van Moolenbroek (bpf_int32)ARCTYPE_INET6));
3148*d56f51eaSDavid van Moolenbroek
3149*d56f51eaSDavid van Moolenbroek case ETHERTYPE_IP:
3150*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKTYPE, 0, BPF_B,
3151*d56f51eaSDavid van Moolenbroek (bpf_int32)ARCTYPE_IP);
3152*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LINKTYPE, 0, BPF_B,
3153*d56f51eaSDavid van Moolenbroek (bpf_int32)ARCTYPE_IP_OLD);
3154*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
3155*d56f51eaSDavid van Moolenbroek return (b1);
3156*d56f51eaSDavid van Moolenbroek
3157*d56f51eaSDavid van Moolenbroek case ETHERTYPE_ARP:
3158*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKTYPE, 0, BPF_B,
3159*d56f51eaSDavid van Moolenbroek (bpf_int32)ARCTYPE_ARP);
3160*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LINKTYPE, 0, BPF_B,
3161*d56f51eaSDavid van Moolenbroek (bpf_int32)ARCTYPE_ARP_OLD);
3162*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
3163*d56f51eaSDavid van Moolenbroek return (b1);
3164*d56f51eaSDavid van Moolenbroek
3165*d56f51eaSDavid van Moolenbroek case ETHERTYPE_REVARP:
3166*d56f51eaSDavid van Moolenbroek return (gen_cmp(OR_LINKTYPE, 0, BPF_B,
3167*d56f51eaSDavid van Moolenbroek (bpf_int32)ARCTYPE_REVARP));
3168*d56f51eaSDavid van Moolenbroek
3169*d56f51eaSDavid van Moolenbroek case ETHERTYPE_ATALK:
3170*d56f51eaSDavid van Moolenbroek return (gen_cmp(OR_LINKTYPE, 0, BPF_B,
3171*d56f51eaSDavid van Moolenbroek (bpf_int32)ARCTYPE_ATALK));
3172*d56f51eaSDavid van Moolenbroek }
3173*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
3174*d56f51eaSDavid van Moolenbroek break;
3175*d56f51eaSDavid van Moolenbroek
3176*d56f51eaSDavid van Moolenbroek case DLT_LTALK:
3177*d56f51eaSDavid van Moolenbroek switch (proto) {
3178*d56f51eaSDavid van Moolenbroek case ETHERTYPE_ATALK:
3179*d56f51eaSDavid van Moolenbroek return gen_true();
3180*d56f51eaSDavid van Moolenbroek default:
3181*d56f51eaSDavid van Moolenbroek return gen_false();
3182*d56f51eaSDavid van Moolenbroek }
3183*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
3184*d56f51eaSDavid van Moolenbroek break;
3185*d56f51eaSDavid van Moolenbroek
3186*d56f51eaSDavid van Moolenbroek case DLT_FRELAY:
3187*d56f51eaSDavid van Moolenbroek /*
3188*d56f51eaSDavid van Moolenbroek * XXX - assumes a 2-byte Frame Relay header with
3189*d56f51eaSDavid van Moolenbroek * DLCI and flags. What if the address is longer?
3190*d56f51eaSDavid van Moolenbroek */
3191*d56f51eaSDavid van Moolenbroek switch (proto) {
3192*d56f51eaSDavid van Moolenbroek
3193*d56f51eaSDavid van Moolenbroek case ETHERTYPE_IP:
3194*d56f51eaSDavid van Moolenbroek /*
3195*d56f51eaSDavid van Moolenbroek * Check for the special NLPID for IP.
3196*d56f51eaSDavid van Moolenbroek */
3197*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0xcc);
3198*d56f51eaSDavid van Moolenbroek
3199*d56f51eaSDavid van Moolenbroek case ETHERTYPE_IPV6:
3200*d56f51eaSDavid van Moolenbroek /*
3201*d56f51eaSDavid van Moolenbroek * Check for the special NLPID for IPv6.
3202*d56f51eaSDavid van Moolenbroek */
3203*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0x8e);
3204*d56f51eaSDavid van Moolenbroek
3205*d56f51eaSDavid van Moolenbroek case LLCSAP_ISONS:
3206*d56f51eaSDavid van Moolenbroek /*
3207*d56f51eaSDavid van Moolenbroek * Check for several OSI protocols.
3208*d56f51eaSDavid van Moolenbroek *
3209*d56f51eaSDavid van Moolenbroek * Frame Relay packets typically have an OSI
3210*d56f51eaSDavid van Moolenbroek * NLPID at the beginning; we check for each
3211*d56f51eaSDavid van Moolenbroek * of them.
3212*d56f51eaSDavid van Moolenbroek *
3213*d56f51eaSDavid van Moolenbroek * What we check for is the NLPID and a frame
3214*d56f51eaSDavid van Moolenbroek * control field of UI, i.e. 0x03 followed
3215*d56f51eaSDavid van Moolenbroek * by the NLPID.
3216*d56f51eaSDavid van Moolenbroek */
3217*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO8473_CLNP);
3218*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO9542_ESIS);
3219*d56f51eaSDavid van Moolenbroek b2 = gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO10589_ISIS);
3220*d56f51eaSDavid van Moolenbroek gen_or(b1, b2);
3221*d56f51eaSDavid van Moolenbroek gen_or(b0, b2);
3222*d56f51eaSDavid van Moolenbroek return b2;
3223*d56f51eaSDavid van Moolenbroek
3224*d56f51eaSDavid van Moolenbroek default:
3225*d56f51eaSDavid van Moolenbroek return gen_false();
3226*d56f51eaSDavid van Moolenbroek }
3227*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
3228*d56f51eaSDavid van Moolenbroek break;
3229*d56f51eaSDavid van Moolenbroek
3230*d56f51eaSDavid van Moolenbroek case DLT_MFR:
3231*d56f51eaSDavid van Moolenbroek bpf_error("Multi-link Frame Relay link-layer type filtering not implemented");
3232*d56f51eaSDavid van Moolenbroek
3233*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_MFR:
3234*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_MLFR:
3235*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_MLPPP:
3236*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ATM1:
3237*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ATM2:
3238*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_PPPOE:
3239*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_PPPOE_ATM:
3240*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_GGSN:
3241*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ES:
3242*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_MONITOR:
3243*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_SERVICES:
3244*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ETHER:
3245*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_PPP:
3246*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_FRELAY:
3247*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_CHDLC:
3248*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_VP:
3249*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ST:
3250*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ISM:
3251*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_VS:
3252*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_SRX_E2E:
3253*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_FIBRECHANNEL:
3254*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ATM_CEMIC:
3255*d56f51eaSDavid van Moolenbroek
3256*d56f51eaSDavid van Moolenbroek /* just lets verify the magic number for now -
3257*d56f51eaSDavid van Moolenbroek * on ATM we may have up to 6 different encapsulations on the wire
3258*d56f51eaSDavid van Moolenbroek * and need a lot of heuristics to figure out that the payload
3259*d56f51eaSDavid van Moolenbroek * might be;
3260*d56f51eaSDavid van Moolenbroek *
3261*d56f51eaSDavid van Moolenbroek * FIXME encapsulation specific BPF_ filters
3262*d56f51eaSDavid van Moolenbroek */
3263*d56f51eaSDavid van Moolenbroek return gen_mcmp(OR_LINKHDR, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
3264*d56f51eaSDavid van Moolenbroek
3265*d56f51eaSDavid van Moolenbroek case DLT_BACNET_MS_TP:
3266*d56f51eaSDavid van Moolenbroek return gen_mcmp(OR_LINKHDR, 0, BPF_W, 0x55FF0000, 0xffff0000);
3267*d56f51eaSDavid van Moolenbroek
3268*d56f51eaSDavid van Moolenbroek case DLT_IPNET:
3269*d56f51eaSDavid van Moolenbroek return gen_ipnet_linktype(proto);
3270*d56f51eaSDavid van Moolenbroek
3271*d56f51eaSDavid van Moolenbroek case DLT_LINUX_IRDA:
3272*d56f51eaSDavid van Moolenbroek bpf_error("IrDA link-layer type filtering not implemented");
3273*d56f51eaSDavid van Moolenbroek
3274*d56f51eaSDavid van Moolenbroek case DLT_DOCSIS:
3275*d56f51eaSDavid van Moolenbroek bpf_error("DOCSIS link-layer type filtering not implemented");
3276*d56f51eaSDavid van Moolenbroek
3277*d56f51eaSDavid van Moolenbroek case DLT_MTP2:
3278*d56f51eaSDavid van Moolenbroek case DLT_MTP2_WITH_PHDR:
3279*d56f51eaSDavid van Moolenbroek bpf_error("MTP2 link-layer type filtering not implemented");
3280*d56f51eaSDavid van Moolenbroek
3281*d56f51eaSDavid van Moolenbroek case DLT_ERF:
3282*d56f51eaSDavid van Moolenbroek bpf_error("ERF link-layer type filtering not implemented");
3283*d56f51eaSDavid van Moolenbroek
3284*d56f51eaSDavid van Moolenbroek case DLT_PFSYNC:
3285*d56f51eaSDavid van Moolenbroek bpf_error("PFSYNC link-layer type filtering not implemented");
3286*d56f51eaSDavid van Moolenbroek
3287*d56f51eaSDavid van Moolenbroek case DLT_LINUX_LAPD:
3288*d56f51eaSDavid van Moolenbroek bpf_error("LAPD link-layer type filtering not implemented");
3289*d56f51eaSDavid van Moolenbroek
3290*d56f51eaSDavid van Moolenbroek case DLT_USB:
3291*d56f51eaSDavid van Moolenbroek case DLT_USB_LINUX:
3292*d56f51eaSDavid van Moolenbroek case DLT_USB_LINUX_MMAPPED:
3293*d56f51eaSDavid van Moolenbroek bpf_error("USB link-layer type filtering not implemented");
3294*d56f51eaSDavid van Moolenbroek
3295*d56f51eaSDavid van Moolenbroek case DLT_BLUETOOTH_HCI_H4:
3296*d56f51eaSDavid van Moolenbroek case DLT_BLUETOOTH_HCI_H4_WITH_PHDR:
3297*d56f51eaSDavid van Moolenbroek bpf_error("Bluetooth link-layer type filtering not implemented");
3298*d56f51eaSDavid van Moolenbroek
3299*d56f51eaSDavid van Moolenbroek case DLT_CAN20B:
3300*d56f51eaSDavid van Moolenbroek case DLT_CAN_SOCKETCAN:
3301*d56f51eaSDavid van Moolenbroek bpf_error("CAN link-layer type filtering not implemented");
3302*d56f51eaSDavid van Moolenbroek
3303*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_15_4:
3304*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_15_4_LINUX:
3305*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_15_4_NONASK_PHY:
3306*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_15_4_NOFCS:
3307*d56f51eaSDavid van Moolenbroek bpf_error("IEEE 802.15.4 link-layer type filtering not implemented");
3308*d56f51eaSDavid van Moolenbroek
3309*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_16_MAC_CPS_RADIO:
3310*d56f51eaSDavid van Moolenbroek bpf_error("IEEE 802.16 link-layer type filtering not implemented");
3311*d56f51eaSDavid van Moolenbroek
3312*d56f51eaSDavid van Moolenbroek case DLT_SITA:
3313*d56f51eaSDavid van Moolenbroek bpf_error("SITA link-layer type filtering not implemented");
3314*d56f51eaSDavid van Moolenbroek
3315*d56f51eaSDavid van Moolenbroek case DLT_RAIF1:
3316*d56f51eaSDavid van Moolenbroek bpf_error("RAIF1 link-layer type filtering not implemented");
3317*d56f51eaSDavid van Moolenbroek
3318*d56f51eaSDavid van Moolenbroek case DLT_IPMB:
3319*d56f51eaSDavid van Moolenbroek bpf_error("IPMB link-layer type filtering not implemented");
3320*d56f51eaSDavid van Moolenbroek
3321*d56f51eaSDavid van Moolenbroek case DLT_AX25_KISS:
3322*d56f51eaSDavid van Moolenbroek bpf_error("AX.25 link-layer type filtering not implemented");
3323*d56f51eaSDavid van Moolenbroek
3324*d56f51eaSDavid van Moolenbroek case DLT_NFLOG:
3325*d56f51eaSDavid van Moolenbroek /* Using the fixed-size NFLOG header it is possible to tell only
3326*d56f51eaSDavid van Moolenbroek * the address family of the packet, other meaningful data is
3327*d56f51eaSDavid van Moolenbroek * either missing or behind TLVs.
3328*d56f51eaSDavid van Moolenbroek */
3329*d56f51eaSDavid van Moolenbroek bpf_error("NFLOG link-layer type filtering not implemented");
3330*d56f51eaSDavid van Moolenbroek
3331*d56f51eaSDavid van Moolenbroek default:
3332*d56f51eaSDavid van Moolenbroek /*
3333*d56f51eaSDavid van Moolenbroek * Does this link-layer header type have a field
3334*d56f51eaSDavid van Moolenbroek * indicating the type of the next protocol? If
3335*d56f51eaSDavid van Moolenbroek * so, off_linktype.constant_part will be the offset of that
3336*d56f51eaSDavid van Moolenbroek * field in the packet; if not, it will be -1.
3337*d56f51eaSDavid van Moolenbroek */
3338*d56f51eaSDavid van Moolenbroek if (off_linktype.constant_part != (u_int)-1) {
3339*d56f51eaSDavid van Moolenbroek /*
3340*d56f51eaSDavid van Moolenbroek * Yes; assume it's an Ethernet type. (If
3341*d56f51eaSDavid van Moolenbroek * it's not, it needs to be handled specially
3342*d56f51eaSDavid van Moolenbroek * above.)
3343*d56f51eaSDavid van Moolenbroek */
3344*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
3345*d56f51eaSDavid van Moolenbroek } else {
3346*d56f51eaSDavid van Moolenbroek /*
3347*d56f51eaSDavid van Moolenbroek * No; report an error.
3348*d56f51eaSDavid van Moolenbroek */
3349*d56f51eaSDavid van Moolenbroek description = pcap_datalink_val_to_description(linktype);
3350*d56f51eaSDavid van Moolenbroek if (description != NULL) {
3351*d56f51eaSDavid van Moolenbroek bpf_error("%s link-layer type filtering not implemented",
3352*d56f51eaSDavid van Moolenbroek description);
3353*d56f51eaSDavid van Moolenbroek } else {
3354*d56f51eaSDavid van Moolenbroek bpf_error("DLT %u link-layer type filtering not implemented",
3355*d56f51eaSDavid van Moolenbroek linktype);
3356*d56f51eaSDavid van Moolenbroek }
3357*d56f51eaSDavid van Moolenbroek }
3358*d56f51eaSDavid van Moolenbroek break;
3359*d56f51eaSDavid van Moolenbroek }
3360*d56f51eaSDavid van Moolenbroek }
3361*d56f51eaSDavid van Moolenbroek
3362*d56f51eaSDavid van Moolenbroek /*
3363*d56f51eaSDavid van Moolenbroek * Check for an LLC SNAP packet with a given organization code and
3364*d56f51eaSDavid van Moolenbroek * protocol type; we check the entire contents of the 802.2 LLC and
3365*d56f51eaSDavid van Moolenbroek * snap headers, checking for DSAP and SSAP of SNAP and a control
3366*d56f51eaSDavid van Moolenbroek * field of 0x03 in the LLC header, and for the specified organization
3367*d56f51eaSDavid van Moolenbroek * code and protocol type in the SNAP header.
3368*d56f51eaSDavid van Moolenbroek */
3369*d56f51eaSDavid van Moolenbroek static struct block *
gen_snap(orgcode,ptype)3370*d56f51eaSDavid van Moolenbroek gen_snap(orgcode, ptype)
3371*d56f51eaSDavid van Moolenbroek bpf_u_int32 orgcode;
3372*d56f51eaSDavid van Moolenbroek bpf_u_int32 ptype;
3373*d56f51eaSDavid van Moolenbroek {
3374*d56f51eaSDavid van Moolenbroek u_char snapblock[8];
3375*d56f51eaSDavid van Moolenbroek
3376*d56f51eaSDavid van Moolenbroek snapblock[0] = LLCSAP_SNAP; /* DSAP = SNAP */
3377*d56f51eaSDavid van Moolenbroek snapblock[1] = LLCSAP_SNAP; /* SSAP = SNAP */
3378*d56f51eaSDavid van Moolenbroek snapblock[2] = 0x03; /* control = UI */
3379*d56f51eaSDavid van Moolenbroek snapblock[3] = (orgcode >> 16); /* upper 8 bits of organization code */
3380*d56f51eaSDavid van Moolenbroek snapblock[4] = (orgcode >> 8); /* middle 8 bits of organization code */
3381*d56f51eaSDavid van Moolenbroek snapblock[5] = (orgcode >> 0); /* lower 8 bits of organization code */
3382*d56f51eaSDavid van Moolenbroek snapblock[6] = (ptype >> 8); /* upper 8 bits of protocol type */
3383*d56f51eaSDavid van Moolenbroek snapblock[7] = (ptype >> 0); /* lower 8 bits of protocol type */
3384*d56f51eaSDavid van Moolenbroek return gen_bcmp(OR_LLC, 0, 8, snapblock);
3385*d56f51eaSDavid van Moolenbroek }
3386*d56f51eaSDavid van Moolenbroek
3387*d56f51eaSDavid van Moolenbroek /*
3388*d56f51eaSDavid van Moolenbroek * Generate code to match frames with an LLC header.
3389*d56f51eaSDavid van Moolenbroek */
3390*d56f51eaSDavid van Moolenbroek struct block *
gen_llc(void)3391*d56f51eaSDavid van Moolenbroek gen_llc(void)
3392*d56f51eaSDavid van Moolenbroek {
3393*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
3394*d56f51eaSDavid van Moolenbroek
3395*d56f51eaSDavid van Moolenbroek switch (linktype) {
3396*d56f51eaSDavid van Moolenbroek
3397*d56f51eaSDavid van Moolenbroek case DLT_EN10MB:
3398*d56f51eaSDavid van Moolenbroek /*
3399*d56f51eaSDavid van Moolenbroek * We check for an Ethernet type field less than
3400*d56f51eaSDavid van Moolenbroek * 1500, which means it's an 802.3 length field.
3401*d56f51eaSDavid van Moolenbroek */
3402*d56f51eaSDavid van Moolenbroek b0 = gen_cmp_gt(OR_LINKTYPE, 0, BPF_H, ETHERMTU);
3403*d56f51eaSDavid van Moolenbroek gen_not(b0);
3404*d56f51eaSDavid van Moolenbroek
3405*d56f51eaSDavid van Moolenbroek /*
3406*d56f51eaSDavid van Moolenbroek * Now check for the purported DSAP and SSAP not being
3407*d56f51eaSDavid van Moolenbroek * 0xFF, to rule out NetWare-over-802.3.
3408*d56f51eaSDavid van Moolenbroek */
3409*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
3410*d56f51eaSDavid van Moolenbroek gen_not(b1);
3411*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
3412*d56f51eaSDavid van Moolenbroek return b1;
3413*d56f51eaSDavid van Moolenbroek
3414*d56f51eaSDavid van Moolenbroek case DLT_SUNATM:
3415*d56f51eaSDavid van Moolenbroek /*
3416*d56f51eaSDavid van Moolenbroek * We check for LLC traffic.
3417*d56f51eaSDavid van Moolenbroek */
3418*d56f51eaSDavid van Moolenbroek b0 = gen_atmtype_abbrev(A_LLC);
3419*d56f51eaSDavid van Moolenbroek return b0;
3420*d56f51eaSDavid van Moolenbroek
3421*d56f51eaSDavid van Moolenbroek case DLT_IEEE802: /* Token Ring */
3422*d56f51eaSDavid van Moolenbroek /*
3423*d56f51eaSDavid van Moolenbroek * XXX - check for LLC frames.
3424*d56f51eaSDavid van Moolenbroek */
3425*d56f51eaSDavid van Moolenbroek return gen_true();
3426*d56f51eaSDavid van Moolenbroek
3427*d56f51eaSDavid van Moolenbroek case DLT_FDDI:
3428*d56f51eaSDavid van Moolenbroek /*
3429*d56f51eaSDavid van Moolenbroek * XXX - check for LLC frames.
3430*d56f51eaSDavid van Moolenbroek */
3431*d56f51eaSDavid van Moolenbroek return gen_true();
3432*d56f51eaSDavid van Moolenbroek
3433*d56f51eaSDavid van Moolenbroek case DLT_ATM_RFC1483:
3434*d56f51eaSDavid van Moolenbroek /*
3435*d56f51eaSDavid van Moolenbroek * For LLC encapsulation, these are defined to have an
3436*d56f51eaSDavid van Moolenbroek * 802.2 LLC header.
3437*d56f51eaSDavid van Moolenbroek *
3438*d56f51eaSDavid van Moolenbroek * For VC encapsulation, they don't, but there's no
3439*d56f51eaSDavid van Moolenbroek * way to check for that; the protocol used on the VC
3440*d56f51eaSDavid van Moolenbroek * is negotiated out of band.
3441*d56f51eaSDavid van Moolenbroek */
3442*d56f51eaSDavid van Moolenbroek return gen_true();
3443*d56f51eaSDavid van Moolenbroek
3444*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11:
3445*d56f51eaSDavid van Moolenbroek case DLT_PRISM_HEADER:
3446*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO:
3447*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO_AVS:
3448*d56f51eaSDavid van Moolenbroek case DLT_PPI:
3449*d56f51eaSDavid van Moolenbroek /*
3450*d56f51eaSDavid van Moolenbroek * Check that we have a data frame.
3451*d56f51eaSDavid van Moolenbroek */
3452*d56f51eaSDavid van Moolenbroek b0 = gen_check_802_11_data_frame();
3453*d56f51eaSDavid van Moolenbroek return b0;
3454*d56f51eaSDavid van Moolenbroek
3455*d56f51eaSDavid van Moolenbroek default:
3456*d56f51eaSDavid van Moolenbroek bpf_error("'llc' not supported for linktype %d", linktype);
3457*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
3458*d56f51eaSDavid van Moolenbroek }
3459*d56f51eaSDavid van Moolenbroek }
3460*d56f51eaSDavid van Moolenbroek
3461*d56f51eaSDavid van Moolenbroek struct block *
gen_llc_i(void)3462*d56f51eaSDavid van Moolenbroek gen_llc_i(void)
3463*d56f51eaSDavid van Moolenbroek {
3464*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
3465*d56f51eaSDavid van Moolenbroek struct slist *s;
3466*d56f51eaSDavid van Moolenbroek
3467*d56f51eaSDavid van Moolenbroek /*
3468*d56f51eaSDavid van Moolenbroek * Check whether this is an LLC frame.
3469*d56f51eaSDavid van Moolenbroek */
3470*d56f51eaSDavid van Moolenbroek b0 = gen_llc();
3471*d56f51eaSDavid van Moolenbroek
3472*d56f51eaSDavid van Moolenbroek /*
3473*d56f51eaSDavid van Moolenbroek * Load the control byte and test the low-order bit; it must
3474*d56f51eaSDavid van Moolenbroek * be clear for I frames.
3475*d56f51eaSDavid van Moolenbroek */
3476*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LLC, 2, BPF_B);
3477*d56f51eaSDavid van Moolenbroek b1 = new_block(JMP(BPF_JSET));
3478*d56f51eaSDavid van Moolenbroek b1->s.k = 0x01;
3479*d56f51eaSDavid van Moolenbroek b1->stmts = s;
3480*d56f51eaSDavid van Moolenbroek gen_not(b1);
3481*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
3482*d56f51eaSDavid van Moolenbroek return b1;
3483*d56f51eaSDavid van Moolenbroek }
3484*d56f51eaSDavid van Moolenbroek
3485*d56f51eaSDavid van Moolenbroek struct block *
gen_llc_s(void)3486*d56f51eaSDavid van Moolenbroek gen_llc_s(void)
3487*d56f51eaSDavid van Moolenbroek {
3488*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
3489*d56f51eaSDavid van Moolenbroek
3490*d56f51eaSDavid van Moolenbroek /*
3491*d56f51eaSDavid van Moolenbroek * Check whether this is an LLC frame.
3492*d56f51eaSDavid van Moolenbroek */
3493*d56f51eaSDavid van Moolenbroek b0 = gen_llc();
3494*d56f51eaSDavid van Moolenbroek
3495*d56f51eaSDavid van Moolenbroek /*
3496*d56f51eaSDavid van Moolenbroek * Now compare the low-order 2 bit of the control byte against
3497*d56f51eaSDavid van Moolenbroek * the appropriate value for S frames.
3498*d56f51eaSDavid van Moolenbroek */
3499*d56f51eaSDavid van Moolenbroek b1 = gen_mcmp(OR_LLC, 2, BPF_B, LLC_S_FMT, 0x03);
3500*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
3501*d56f51eaSDavid van Moolenbroek return b1;
3502*d56f51eaSDavid van Moolenbroek }
3503*d56f51eaSDavid van Moolenbroek
3504*d56f51eaSDavid van Moolenbroek struct block *
gen_llc_u(void)3505*d56f51eaSDavid van Moolenbroek gen_llc_u(void)
3506*d56f51eaSDavid van Moolenbroek {
3507*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
3508*d56f51eaSDavid van Moolenbroek
3509*d56f51eaSDavid van Moolenbroek /*
3510*d56f51eaSDavid van Moolenbroek * Check whether this is an LLC frame.
3511*d56f51eaSDavid van Moolenbroek */
3512*d56f51eaSDavid van Moolenbroek b0 = gen_llc();
3513*d56f51eaSDavid van Moolenbroek
3514*d56f51eaSDavid van Moolenbroek /*
3515*d56f51eaSDavid van Moolenbroek * Now compare the low-order 2 bit of the control byte against
3516*d56f51eaSDavid van Moolenbroek * the appropriate value for U frames.
3517*d56f51eaSDavid van Moolenbroek */
3518*d56f51eaSDavid van Moolenbroek b1 = gen_mcmp(OR_LLC, 2, BPF_B, LLC_U_FMT, 0x03);
3519*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
3520*d56f51eaSDavid van Moolenbroek return b1;
3521*d56f51eaSDavid van Moolenbroek }
3522*d56f51eaSDavid van Moolenbroek
3523*d56f51eaSDavid van Moolenbroek struct block *
gen_llc_s_subtype(bpf_u_int32 subtype)3524*d56f51eaSDavid van Moolenbroek gen_llc_s_subtype(bpf_u_int32 subtype)
3525*d56f51eaSDavid van Moolenbroek {
3526*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
3527*d56f51eaSDavid van Moolenbroek
3528*d56f51eaSDavid van Moolenbroek /*
3529*d56f51eaSDavid van Moolenbroek * Check whether this is an LLC frame.
3530*d56f51eaSDavid van Moolenbroek */
3531*d56f51eaSDavid van Moolenbroek b0 = gen_llc();
3532*d56f51eaSDavid van Moolenbroek
3533*d56f51eaSDavid van Moolenbroek /*
3534*d56f51eaSDavid van Moolenbroek * Now check for an S frame with the appropriate type.
3535*d56f51eaSDavid van Moolenbroek */
3536*d56f51eaSDavid van Moolenbroek b1 = gen_mcmp(OR_LLC, 2, BPF_B, subtype, LLC_S_CMD_MASK);
3537*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
3538*d56f51eaSDavid van Moolenbroek return b1;
3539*d56f51eaSDavid van Moolenbroek }
3540*d56f51eaSDavid van Moolenbroek
3541*d56f51eaSDavid van Moolenbroek struct block *
gen_llc_u_subtype(bpf_u_int32 subtype)3542*d56f51eaSDavid van Moolenbroek gen_llc_u_subtype(bpf_u_int32 subtype)
3543*d56f51eaSDavid van Moolenbroek {
3544*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
3545*d56f51eaSDavid van Moolenbroek
3546*d56f51eaSDavid van Moolenbroek /*
3547*d56f51eaSDavid van Moolenbroek * Check whether this is an LLC frame.
3548*d56f51eaSDavid van Moolenbroek */
3549*d56f51eaSDavid van Moolenbroek b0 = gen_llc();
3550*d56f51eaSDavid van Moolenbroek
3551*d56f51eaSDavid van Moolenbroek /*
3552*d56f51eaSDavid van Moolenbroek * Now check for a U frame with the appropriate type.
3553*d56f51eaSDavid van Moolenbroek */
3554*d56f51eaSDavid van Moolenbroek b1 = gen_mcmp(OR_LLC, 2, BPF_B, subtype, LLC_U_CMD_MASK);
3555*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
3556*d56f51eaSDavid van Moolenbroek return b1;
3557*d56f51eaSDavid van Moolenbroek }
3558*d56f51eaSDavid van Moolenbroek
3559*d56f51eaSDavid van Moolenbroek /*
3560*d56f51eaSDavid van Moolenbroek * Generate code to match a particular packet type, for link-layer types
3561*d56f51eaSDavid van Moolenbroek * using 802.2 LLC headers.
3562*d56f51eaSDavid van Moolenbroek *
3563*d56f51eaSDavid van Moolenbroek * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used
3564*d56f51eaSDavid van Moolenbroek * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues.
3565*d56f51eaSDavid van Moolenbroek *
3566*d56f51eaSDavid van Moolenbroek * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
3567*d56f51eaSDavid van Moolenbroek * value, if <= ETHERMTU. We use that to determine whether to
3568*d56f51eaSDavid van Moolenbroek * match the DSAP or both DSAP and LSAP or to check the OUI and
3569*d56f51eaSDavid van Moolenbroek * protocol ID in a SNAP header.
3570*d56f51eaSDavid van Moolenbroek */
3571*d56f51eaSDavid van Moolenbroek static struct block *
gen_llc_linktype(proto)3572*d56f51eaSDavid van Moolenbroek gen_llc_linktype(proto)
3573*d56f51eaSDavid van Moolenbroek int proto;
3574*d56f51eaSDavid van Moolenbroek {
3575*d56f51eaSDavid van Moolenbroek /*
3576*d56f51eaSDavid van Moolenbroek * XXX - handle token-ring variable-length header.
3577*d56f51eaSDavid van Moolenbroek */
3578*d56f51eaSDavid van Moolenbroek switch (proto) {
3579*d56f51eaSDavid van Moolenbroek
3580*d56f51eaSDavid van Moolenbroek case LLCSAP_IP:
3581*d56f51eaSDavid van Moolenbroek case LLCSAP_ISONS:
3582*d56f51eaSDavid van Moolenbroek case LLCSAP_NETBEUI:
3583*d56f51eaSDavid van Moolenbroek /*
3584*d56f51eaSDavid van Moolenbroek * XXX - should we check both the DSAP and the
3585*d56f51eaSDavid van Moolenbroek * SSAP, like this, or should we check just the
3586*d56f51eaSDavid van Moolenbroek * DSAP, as we do for other SAP values?
3587*d56f51eaSDavid van Moolenbroek */
3588*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_LLC, 0, BPF_H, (bpf_u_int32)
3589*d56f51eaSDavid van Moolenbroek ((proto << 8) | proto));
3590*d56f51eaSDavid van Moolenbroek
3591*d56f51eaSDavid van Moolenbroek case LLCSAP_IPX:
3592*d56f51eaSDavid van Moolenbroek /*
3593*d56f51eaSDavid van Moolenbroek * XXX - are there ever SNAP frames for IPX on
3594*d56f51eaSDavid van Moolenbroek * non-Ethernet 802.x networks?
3595*d56f51eaSDavid van Moolenbroek */
3596*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_LLC, 0, BPF_B,
3597*d56f51eaSDavid van Moolenbroek (bpf_int32)LLCSAP_IPX);
3598*d56f51eaSDavid van Moolenbroek
3599*d56f51eaSDavid van Moolenbroek case ETHERTYPE_ATALK:
3600*d56f51eaSDavid van Moolenbroek /*
3601*d56f51eaSDavid van Moolenbroek * 802.2-encapsulated ETHERTYPE_ATALK packets are
3602*d56f51eaSDavid van Moolenbroek * SNAP packets with an organization code of
3603*d56f51eaSDavid van Moolenbroek * 0x080007 (Apple, for Appletalk) and a protocol
3604*d56f51eaSDavid van Moolenbroek * type of ETHERTYPE_ATALK (Appletalk).
3605*d56f51eaSDavid van Moolenbroek *
3606*d56f51eaSDavid van Moolenbroek * XXX - check for an organization code of
3607*d56f51eaSDavid van Moolenbroek * encapsulated Ethernet as well?
3608*d56f51eaSDavid van Moolenbroek */
3609*d56f51eaSDavid van Moolenbroek return gen_snap(0x080007, ETHERTYPE_ATALK);
3610*d56f51eaSDavid van Moolenbroek
3611*d56f51eaSDavid van Moolenbroek default:
3612*d56f51eaSDavid van Moolenbroek /*
3613*d56f51eaSDavid van Moolenbroek * XXX - we don't have to check for IPX 802.3
3614*d56f51eaSDavid van Moolenbroek * here, but should we check for the IPX Ethertype?
3615*d56f51eaSDavid van Moolenbroek */
3616*d56f51eaSDavid van Moolenbroek if (proto <= ETHERMTU) {
3617*d56f51eaSDavid van Moolenbroek /*
3618*d56f51eaSDavid van Moolenbroek * This is an LLC SAP value, so check
3619*d56f51eaSDavid van Moolenbroek * the DSAP.
3620*d56f51eaSDavid van Moolenbroek */
3621*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_LLC, 0, BPF_B, (bpf_int32)proto);
3622*d56f51eaSDavid van Moolenbroek } else {
3623*d56f51eaSDavid van Moolenbroek /*
3624*d56f51eaSDavid van Moolenbroek * This is an Ethernet type; we assume that it's
3625*d56f51eaSDavid van Moolenbroek * unlikely that it'll appear in the right place
3626*d56f51eaSDavid van Moolenbroek * at random, and therefore check only the
3627*d56f51eaSDavid van Moolenbroek * location that would hold the Ethernet type
3628*d56f51eaSDavid van Moolenbroek * in a SNAP frame with an organization code of
3629*d56f51eaSDavid van Moolenbroek * 0x000000 (encapsulated Ethernet).
3630*d56f51eaSDavid van Moolenbroek *
3631*d56f51eaSDavid van Moolenbroek * XXX - if we were to check for the SNAP DSAP and
3632*d56f51eaSDavid van Moolenbroek * LSAP, as per XXX, and were also to check for an
3633*d56f51eaSDavid van Moolenbroek * organization code of 0x000000 (encapsulated
3634*d56f51eaSDavid van Moolenbroek * Ethernet), we'd do
3635*d56f51eaSDavid van Moolenbroek *
3636*d56f51eaSDavid van Moolenbroek * return gen_snap(0x000000, proto);
3637*d56f51eaSDavid van Moolenbroek *
3638*d56f51eaSDavid van Moolenbroek * here; for now, we don't, as per the above.
3639*d56f51eaSDavid van Moolenbroek * I don't know whether it's worth the extra CPU
3640*d56f51eaSDavid van Moolenbroek * time to do the right check or not.
3641*d56f51eaSDavid van Moolenbroek */
3642*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_LLC, 6, BPF_H, (bpf_int32)proto);
3643*d56f51eaSDavid van Moolenbroek }
3644*d56f51eaSDavid van Moolenbroek }
3645*d56f51eaSDavid van Moolenbroek }
3646*d56f51eaSDavid van Moolenbroek
3647*d56f51eaSDavid van Moolenbroek static struct block *
gen_hostop(addr,mask,dir,proto,src_off,dst_off)3648*d56f51eaSDavid van Moolenbroek gen_hostop(addr, mask, dir, proto, src_off, dst_off)
3649*d56f51eaSDavid van Moolenbroek bpf_u_int32 addr;
3650*d56f51eaSDavid van Moolenbroek bpf_u_int32 mask;
3651*d56f51eaSDavid van Moolenbroek int dir, proto;
3652*d56f51eaSDavid van Moolenbroek u_int src_off, dst_off;
3653*d56f51eaSDavid van Moolenbroek {
3654*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
3655*d56f51eaSDavid van Moolenbroek u_int offset;
3656*d56f51eaSDavid van Moolenbroek
3657*d56f51eaSDavid van Moolenbroek switch (dir) {
3658*d56f51eaSDavid van Moolenbroek
3659*d56f51eaSDavid van Moolenbroek case Q_SRC:
3660*d56f51eaSDavid van Moolenbroek offset = src_off;
3661*d56f51eaSDavid van Moolenbroek break;
3662*d56f51eaSDavid van Moolenbroek
3663*d56f51eaSDavid van Moolenbroek case Q_DST:
3664*d56f51eaSDavid van Moolenbroek offset = dst_off;
3665*d56f51eaSDavid van Moolenbroek break;
3666*d56f51eaSDavid van Moolenbroek
3667*d56f51eaSDavid van Moolenbroek case Q_AND:
3668*d56f51eaSDavid van Moolenbroek b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
3669*d56f51eaSDavid van Moolenbroek b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
3670*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
3671*d56f51eaSDavid van Moolenbroek return b1;
3672*d56f51eaSDavid van Moolenbroek
3673*d56f51eaSDavid van Moolenbroek case Q_OR:
3674*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
3675*d56f51eaSDavid van Moolenbroek b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
3676*d56f51eaSDavid van Moolenbroek b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
3677*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
3678*d56f51eaSDavid van Moolenbroek return b1;
3679*d56f51eaSDavid van Moolenbroek
3680*d56f51eaSDavid van Moolenbroek default:
3681*d56f51eaSDavid van Moolenbroek abort();
3682*d56f51eaSDavid van Moolenbroek }
3683*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(proto);
3684*d56f51eaSDavid van Moolenbroek b1 = gen_mcmp(OR_LINKPL, offset, BPF_W, (bpf_int32)addr, mask);
3685*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
3686*d56f51eaSDavid van Moolenbroek return b1;
3687*d56f51eaSDavid van Moolenbroek }
3688*d56f51eaSDavid van Moolenbroek
3689*d56f51eaSDavid van Moolenbroek #ifdef INET6
3690*d56f51eaSDavid van Moolenbroek static struct block *
gen_hostop6(addr,mask,dir,proto,src_off,dst_off)3691*d56f51eaSDavid van Moolenbroek gen_hostop6(addr, mask, dir, proto, src_off, dst_off)
3692*d56f51eaSDavid van Moolenbroek struct in6_addr *addr;
3693*d56f51eaSDavid van Moolenbroek struct in6_addr *mask;
3694*d56f51eaSDavid van Moolenbroek int dir, proto;
3695*d56f51eaSDavid van Moolenbroek u_int src_off, dst_off;
3696*d56f51eaSDavid van Moolenbroek {
3697*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
3698*d56f51eaSDavid van Moolenbroek u_int offset;
3699*d56f51eaSDavid van Moolenbroek u_int32_t *a, *m;
3700*d56f51eaSDavid van Moolenbroek
3701*d56f51eaSDavid van Moolenbroek switch (dir) {
3702*d56f51eaSDavid van Moolenbroek
3703*d56f51eaSDavid van Moolenbroek case Q_SRC:
3704*d56f51eaSDavid van Moolenbroek offset = src_off;
3705*d56f51eaSDavid van Moolenbroek break;
3706*d56f51eaSDavid van Moolenbroek
3707*d56f51eaSDavid van Moolenbroek case Q_DST:
3708*d56f51eaSDavid van Moolenbroek offset = dst_off;
3709*d56f51eaSDavid van Moolenbroek break;
3710*d56f51eaSDavid van Moolenbroek
3711*d56f51eaSDavid van Moolenbroek case Q_AND:
3712*d56f51eaSDavid van Moolenbroek b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
3713*d56f51eaSDavid van Moolenbroek b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
3714*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
3715*d56f51eaSDavid van Moolenbroek return b1;
3716*d56f51eaSDavid van Moolenbroek
3717*d56f51eaSDavid van Moolenbroek case Q_OR:
3718*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
3719*d56f51eaSDavid van Moolenbroek b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
3720*d56f51eaSDavid van Moolenbroek b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
3721*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
3722*d56f51eaSDavid van Moolenbroek return b1;
3723*d56f51eaSDavid van Moolenbroek
3724*d56f51eaSDavid van Moolenbroek default:
3725*d56f51eaSDavid van Moolenbroek abort();
3726*d56f51eaSDavid van Moolenbroek }
3727*d56f51eaSDavid van Moolenbroek /* this order is important */
3728*d56f51eaSDavid van Moolenbroek a = (u_int32_t *)addr;
3729*d56f51eaSDavid van Moolenbroek m = (u_int32_t *)mask;
3730*d56f51eaSDavid van Moolenbroek b1 = gen_mcmp(OR_LINKPL, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
3731*d56f51eaSDavid van Moolenbroek b0 = gen_mcmp(OR_LINKPL, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
3732*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
3733*d56f51eaSDavid van Moolenbroek b0 = gen_mcmp(OR_LINKPL, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
3734*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
3735*d56f51eaSDavid van Moolenbroek b0 = gen_mcmp(OR_LINKPL, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
3736*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
3737*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(proto);
3738*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
3739*d56f51eaSDavid van Moolenbroek return b1;
3740*d56f51eaSDavid van Moolenbroek }
3741*d56f51eaSDavid van Moolenbroek #endif
3742*d56f51eaSDavid van Moolenbroek
3743*d56f51eaSDavid van Moolenbroek static struct block *
gen_ehostop(eaddr,dir)3744*d56f51eaSDavid van Moolenbroek gen_ehostop(eaddr, dir)
3745*d56f51eaSDavid van Moolenbroek register const u_char *eaddr;
3746*d56f51eaSDavid van Moolenbroek register int dir;
3747*d56f51eaSDavid van Moolenbroek {
3748*d56f51eaSDavid van Moolenbroek register struct block *b0, *b1;
3749*d56f51eaSDavid van Moolenbroek
3750*d56f51eaSDavid van Moolenbroek switch (dir) {
3751*d56f51eaSDavid van Moolenbroek case Q_SRC:
3752*d56f51eaSDavid van Moolenbroek return gen_bcmp(OR_LINKHDR, 6, 6, eaddr);
3753*d56f51eaSDavid van Moolenbroek
3754*d56f51eaSDavid van Moolenbroek case Q_DST:
3755*d56f51eaSDavid van Moolenbroek return gen_bcmp(OR_LINKHDR, 0, 6, eaddr);
3756*d56f51eaSDavid van Moolenbroek
3757*d56f51eaSDavid van Moolenbroek case Q_AND:
3758*d56f51eaSDavid van Moolenbroek b0 = gen_ehostop(eaddr, Q_SRC);
3759*d56f51eaSDavid van Moolenbroek b1 = gen_ehostop(eaddr, Q_DST);
3760*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
3761*d56f51eaSDavid van Moolenbroek return b1;
3762*d56f51eaSDavid van Moolenbroek
3763*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
3764*d56f51eaSDavid van Moolenbroek case Q_OR:
3765*d56f51eaSDavid van Moolenbroek b0 = gen_ehostop(eaddr, Q_SRC);
3766*d56f51eaSDavid van Moolenbroek b1 = gen_ehostop(eaddr, Q_DST);
3767*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
3768*d56f51eaSDavid van Moolenbroek return b1;
3769*d56f51eaSDavid van Moolenbroek
3770*d56f51eaSDavid van Moolenbroek case Q_ADDR1:
3771*d56f51eaSDavid van Moolenbroek bpf_error("'addr1' is only supported on 802.11 with 802.11 headers");
3772*d56f51eaSDavid van Moolenbroek break;
3773*d56f51eaSDavid van Moolenbroek
3774*d56f51eaSDavid van Moolenbroek case Q_ADDR2:
3775*d56f51eaSDavid van Moolenbroek bpf_error("'addr2' is only supported on 802.11 with 802.11 headers");
3776*d56f51eaSDavid van Moolenbroek break;
3777*d56f51eaSDavid van Moolenbroek
3778*d56f51eaSDavid van Moolenbroek case Q_ADDR3:
3779*d56f51eaSDavid van Moolenbroek bpf_error("'addr3' is only supported on 802.11 with 802.11 headers");
3780*d56f51eaSDavid van Moolenbroek break;
3781*d56f51eaSDavid van Moolenbroek
3782*d56f51eaSDavid van Moolenbroek case Q_ADDR4:
3783*d56f51eaSDavid van Moolenbroek bpf_error("'addr4' is only supported on 802.11 with 802.11 headers");
3784*d56f51eaSDavid van Moolenbroek break;
3785*d56f51eaSDavid van Moolenbroek
3786*d56f51eaSDavid van Moolenbroek case Q_RA:
3787*d56f51eaSDavid van Moolenbroek bpf_error("'ra' is only supported on 802.11 with 802.11 headers");
3788*d56f51eaSDavid van Moolenbroek break;
3789*d56f51eaSDavid van Moolenbroek
3790*d56f51eaSDavid van Moolenbroek case Q_TA:
3791*d56f51eaSDavid van Moolenbroek bpf_error("'ta' is only supported on 802.11 with 802.11 headers");
3792*d56f51eaSDavid van Moolenbroek break;
3793*d56f51eaSDavid van Moolenbroek }
3794*d56f51eaSDavid van Moolenbroek abort();
3795*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
3796*d56f51eaSDavid van Moolenbroek }
3797*d56f51eaSDavid van Moolenbroek
3798*d56f51eaSDavid van Moolenbroek /*
3799*d56f51eaSDavid van Moolenbroek * Like gen_ehostop, but for DLT_FDDI
3800*d56f51eaSDavid van Moolenbroek */
3801*d56f51eaSDavid van Moolenbroek static struct block *
gen_fhostop(eaddr,dir)3802*d56f51eaSDavid van Moolenbroek gen_fhostop(eaddr, dir)
3803*d56f51eaSDavid van Moolenbroek register const u_char *eaddr;
3804*d56f51eaSDavid van Moolenbroek register int dir;
3805*d56f51eaSDavid van Moolenbroek {
3806*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
3807*d56f51eaSDavid van Moolenbroek
3808*d56f51eaSDavid van Moolenbroek switch (dir) {
3809*d56f51eaSDavid van Moolenbroek case Q_SRC:
3810*d56f51eaSDavid van Moolenbroek return gen_bcmp(OR_LINKHDR, 6 + 1 + pcap_fddipad, 6, eaddr);
3811*d56f51eaSDavid van Moolenbroek
3812*d56f51eaSDavid van Moolenbroek case Q_DST:
3813*d56f51eaSDavid van Moolenbroek return gen_bcmp(OR_LINKHDR, 0 + 1 + pcap_fddipad, 6, eaddr);
3814*d56f51eaSDavid van Moolenbroek
3815*d56f51eaSDavid van Moolenbroek case Q_AND:
3816*d56f51eaSDavid van Moolenbroek b0 = gen_fhostop(eaddr, Q_SRC);
3817*d56f51eaSDavid van Moolenbroek b1 = gen_fhostop(eaddr, Q_DST);
3818*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
3819*d56f51eaSDavid van Moolenbroek return b1;
3820*d56f51eaSDavid van Moolenbroek
3821*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
3822*d56f51eaSDavid van Moolenbroek case Q_OR:
3823*d56f51eaSDavid van Moolenbroek b0 = gen_fhostop(eaddr, Q_SRC);
3824*d56f51eaSDavid van Moolenbroek b1 = gen_fhostop(eaddr, Q_DST);
3825*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
3826*d56f51eaSDavid van Moolenbroek return b1;
3827*d56f51eaSDavid van Moolenbroek
3828*d56f51eaSDavid van Moolenbroek case Q_ADDR1:
3829*d56f51eaSDavid van Moolenbroek bpf_error("'addr1' is only supported on 802.11");
3830*d56f51eaSDavid van Moolenbroek break;
3831*d56f51eaSDavid van Moolenbroek
3832*d56f51eaSDavid van Moolenbroek case Q_ADDR2:
3833*d56f51eaSDavid van Moolenbroek bpf_error("'addr2' is only supported on 802.11");
3834*d56f51eaSDavid van Moolenbroek break;
3835*d56f51eaSDavid van Moolenbroek
3836*d56f51eaSDavid van Moolenbroek case Q_ADDR3:
3837*d56f51eaSDavid van Moolenbroek bpf_error("'addr3' is only supported on 802.11");
3838*d56f51eaSDavid van Moolenbroek break;
3839*d56f51eaSDavid van Moolenbroek
3840*d56f51eaSDavid van Moolenbroek case Q_ADDR4:
3841*d56f51eaSDavid van Moolenbroek bpf_error("'addr4' is only supported on 802.11");
3842*d56f51eaSDavid van Moolenbroek break;
3843*d56f51eaSDavid van Moolenbroek
3844*d56f51eaSDavid van Moolenbroek case Q_RA:
3845*d56f51eaSDavid van Moolenbroek bpf_error("'ra' is only supported on 802.11");
3846*d56f51eaSDavid van Moolenbroek break;
3847*d56f51eaSDavid van Moolenbroek
3848*d56f51eaSDavid van Moolenbroek case Q_TA:
3849*d56f51eaSDavid van Moolenbroek bpf_error("'ta' is only supported on 802.11");
3850*d56f51eaSDavid van Moolenbroek break;
3851*d56f51eaSDavid van Moolenbroek }
3852*d56f51eaSDavid van Moolenbroek abort();
3853*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
3854*d56f51eaSDavid van Moolenbroek }
3855*d56f51eaSDavid van Moolenbroek
3856*d56f51eaSDavid van Moolenbroek /*
3857*d56f51eaSDavid van Moolenbroek * Like gen_ehostop, but for DLT_IEEE802 (Token Ring)
3858*d56f51eaSDavid van Moolenbroek */
3859*d56f51eaSDavid van Moolenbroek static struct block *
gen_thostop(eaddr,dir)3860*d56f51eaSDavid van Moolenbroek gen_thostop(eaddr, dir)
3861*d56f51eaSDavid van Moolenbroek register const u_char *eaddr;
3862*d56f51eaSDavid van Moolenbroek register int dir;
3863*d56f51eaSDavid van Moolenbroek {
3864*d56f51eaSDavid van Moolenbroek register struct block *b0, *b1;
3865*d56f51eaSDavid van Moolenbroek
3866*d56f51eaSDavid van Moolenbroek switch (dir) {
3867*d56f51eaSDavid van Moolenbroek case Q_SRC:
3868*d56f51eaSDavid van Moolenbroek return gen_bcmp(OR_LINKHDR, 8, 6, eaddr);
3869*d56f51eaSDavid van Moolenbroek
3870*d56f51eaSDavid van Moolenbroek case Q_DST:
3871*d56f51eaSDavid van Moolenbroek return gen_bcmp(OR_LINKHDR, 2, 6, eaddr);
3872*d56f51eaSDavid van Moolenbroek
3873*d56f51eaSDavid van Moolenbroek case Q_AND:
3874*d56f51eaSDavid van Moolenbroek b0 = gen_thostop(eaddr, Q_SRC);
3875*d56f51eaSDavid van Moolenbroek b1 = gen_thostop(eaddr, Q_DST);
3876*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
3877*d56f51eaSDavid van Moolenbroek return b1;
3878*d56f51eaSDavid van Moolenbroek
3879*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
3880*d56f51eaSDavid van Moolenbroek case Q_OR:
3881*d56f51eaSDavid van Moolenbroek b0 = gen_thostop(eaddr, Q_SRC);
3882*d56f51eaSDavid van Moolenbroek b1 = gen_thostop(eaddr, Q_DST);
3883*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
3884*d56f51eaSDavid van Moolenbroek return b1;
3885*d56f51eaSDavid van Moolenbroek
3886*d56f51eaSDavid van Moolenbroek case Q_ADDR1:
3887*d56f51eaSDavid van Moolenbroek bpf_error("'addr1' is only supported on 802.11");
3888*d56f51eaSDavid van Moolenbroek break;
3889*d56f51eaSDavid van Moolenbroek
3890*d56f51eaSDavid van Moolenbroek case Q_ADDR2:
3891*d56f51eaSDavid van Moolenbroek bpf_error("'addr2' is only supported on 802.11");
3892*d56f51eaSDavid van Moolenbroek break;
3893*d56f51eaSDavid van Moolenbroek
3894*d56f51eaSDavid van Moolenbroek case Q_ADDR3:
3895*d56f51eaSDavid van Moolenbroek bpf_error("'addr3' is only supported on 802.11");
3896*d56f51eaSDavid van Moolenbroek break;
3897*d56f51eaSDavid van Moolenbroek
3898*d56f51eaSDavid van Moolenbroek case Q_ADDR4:
3899*d56f51eaSDavid van Moolenbroek bpf_error("'addr4' is only supported on 802.11");
3900*d56f51eaSDavid van Moolenbroek break;
3901*d56f51eaSDavid van Moolenbroek
3902*d56f51eaSDavid van Moolenbroek case Q_RA:
3903*d56f51eaSDavid van Moolenbroek bpf_error("'ra' is only supported on 802.11");
3904*d56f51eaSDavid van Moolenbroek break;
3905*d56f51eaSDavid van Moolenbroek
3906*d56f51eaSDavid van Moolenbroek case Q_TA:
3907*d56f51eaSDavid van Moolenbroek bpf_error("'ta' is only supported on 802.11");
3908*d56f51eaSDavid van Moolenbroek break;
3909*d56f51eaSDavid van Moolenbroek }
3910*d56f51eaSDavid van Moolenbroek abort();
3911*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
3912*d56f51eaSDavid van Moolenbroek }
3913*d56f51eaSDavid van Moolenbroek
3914*d56f51eaSDavid van Moolenbroek /*
3915*d56f51eaSDavid van Moolenbroek * Like gen_ehostop, but for DLT_IEEE802_11 (802.11 wireless LAN) and
3916*d56f51eaSDavid van Moolenbroek * various 802.11 + radio headers.
3917*d56f51eaSDavid van Moolenbroek */
3918*d56f51eaSDavid van Moolenbroek static struct block *
gen_wlanhostop(eaddr,dir)3919*d56f51eaSDavid van Moolenbroek gen_wlanhostop(eaddr, dir)
3920*d56f51eaSDavid van Moolenbroek register const u_char *eaddr;
3921*d56f51eaSDavid van Moolenbroek register int dir;
3922*d56f51eaSDavid van Moolenbroek {
3923*d56f51eaSDavid van Moolenbroek register struct block *b0, *b1, *b2;
3924*d56f51eaSDavid van Moolenbroek register struct slist *s;
3925*d56f51eaSDavid van Moolenbroek
3926*d56f51eaSDavid van Moolenbroek #ifdef ENABLE_WLAN_FILTERING_PATCH
3927*d56f51eaSDavid van Moolenbroek /*
3928*d56f51eaSDavid van Moolenbroek * TODO GV 20070613
3929*d56f51eaSDavid van Moolenbroek * We need to disable the optimizer because the optimizer is buggy
3930*d56f51eaSDavid van Moolenbroek * and wipes out some LD instructions generated by the below
3931*d56f51eaSDavid van Moolenbroek * code to validate the Frame Control bits
3932*d56f51eaSDavid van Moolenbroek */
3933*d56f51eaSDavid van Moolenbroek no_optimize = 1;
3934*d56f51eaSDavid van Moolenbroek #endif /* ENABLE_WLAN_FILTERING_PATCH */
3935*d56f51eaSDavid van Moolenbroek
3936*d56f51eaSDavid van Moolenbroek switch (dir) {
3937*d56f51eaSDavid van Moolenbroek case Q_SRC:
3938*d56f51eaSDavid van Moolenbroek /*
3939*d56f51eaSDavid van Moolenbroek * Oh, yuk.
3940*d56f51eaSDavid van Moolenbroek *
3941*d56f51eaSDavid van Moolenbroek * For control frames, there is no SA.
3942*d56f51eaSDavid van Moolenbroek *
3943*d56f51eaSDavid van Moolenbroek * For management frames, SA is at an
3944*d56f51eaSDavid van Moolenbroek * offset of 10 from the beginning of
3945*d56f51eaSDavid van Moolenbroek * the packet.
3946*d56f51eaSDavid van Moolenbroek *
3947*d56f51eaSDavid van Moolenbroek * For data frames, SA is at an offset
3948*d56f51eaSDavid van Moolenbroek * of 10 from the beginning of the packet
3949*d56f51eaSDavid van Moolenbroek * if From DS is clear, at an offset of
3950*d56f51eaSDavid van Moolenbroek * 16 from the beginning of the packet
3951*d56f51eaSDavid van Moolenbroek * if From DS is set and To DS is clear,
3952*d56f51eaSDavid van Moolenbroek * and an offset of 24 from the beginning
3953*d56f51eaSDavid van Moolenbroek * of the packet if From DS is set and To DS
3954*d56f51eaSDavid van Moolenbroek * is set.
3955*d56f51eaSDavid van Moolenbroek */
3956*d56f51eaSDavid van Moolenbroek
3957*d56f51eaSDavid van Moolenbroek /*
3958*d56f51eaSDavid van Moolenbroek * Generate the tests to be done for data frames
3959*d56f51eaSDavid van Moolenbroek * with From DS set.
3960*d56f51eaSDavid van Moolenbroek *
3961*d56f51eaSDavid van Moolenbroek * First, check for To DS set, i.e. check "link[1] & 0x01".
3962*d56f51eaSDavid van Moolenbroek */
3963*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 1, BPF_B);
3964*d56f51eaSDavid van Moolenbroek b1 = new_block(JMP(BPF_JSET));
3965*d56f51eaSDavid van Moolenbroek b1->s.k = 0x01; /* To DS */
3966*d56f51eaSDavid van Moolenbroek b1->stmts = s;
3967*d56f51eaSDavid van Moolenbroek
3968*d56f51eaSDavid van Moolenbroek /*
3969*d56f51eaSDavid van Moolenbroek * If To DS is set, the SA is at 24.
3970*d56f51eaSDavid van Moolenbroek */
3971*d56f51eaSDavid van Moolenbroek b0 = gen_bcmp(OR_LINKHDR, 24, 6, eaddr);
3972*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
3973*d56f51eaSDavid van Moolenbroek
3974*d56f51eaSDavid van Moolenbroek /*
3975*d56f51eaSDavid van Moolenbroek * Now, check for To DS not set, i.e. check
3976*d56f51eaSDavid van Moolenbroek * "!(link[1] & 0x01)".
3977*d56f51eaSDavid van Moolenbroek */
3978*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 1, BPF_B);
3979*d56f51eaSDavid van Moolenbroek b2 = new_block(JMP(BPF_JSET));
3980*d56f51eaSDavid van Moolenbroek b2->s.k = 0x01; /* To DS */
3981*d56f51eaSDavid van Moolenbroek b2->stmts = s;
3982*d56f51eaSDavid van Moolenbroek gen_not(b2);
3983*d56f51eaSDavid van Moolenbroek
3984*d56f51eaSDavid van Moolenbroek /*
3985*d56f51eaSDavid van Moolenbroek * If To DS is not set, the SA is at 16.
3986*d56f51eaSDavid van Moolenbroek */
3987*d56f51eaSDavid van Moolenbroek b1 = gen_bcmp(OR_LINKHDR, 16, 6, eaddr);
3988*d56f51eaSDavid van Moolenbroek gen_and(b2, b1);
3989*d56f51eaSDavid van Moolenbroek
3990*d56f51eaSDavid van Moolenbroek /*
3991*d56f51eaSDavid van Moolenbroek * Now OR together the last two checks. That gives
3992*d56f51eaSDavid van Moolenbroek * the complete set of checks for data frames with
3993*d56f51eaSDavid van Moolenbroek * From DS set.
3994*d56f51eaSDavid van Moolenbroek */
3995*d56f51eaSDavid van Moolenbroek gen_or(b1, b0);
3996*d56f51eaSDavid van Moolenbroek
3997*d56f51eaSDavid van Moolenbroek /*
3998*d56f51eaSDavid van Moolenbroek * Now check for From DS being set, and AND that with
3999*d56f51eaSDavid van Moolenbroek * the ORed-together checks.
4000*d56f51eaSDavid van Moolenbroek */
4001*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 1, BPF_B);
4002*d56f51eaSDavid van Moolenbroek b1 = new_block(JMP(BPF_JSET));
4003*d56f51eaSDavid van Moolenbroek b1->s.k = 0x02; /* From DS */
4004*d56f51eaSDavid van Moolenbroek b1->stmts = s;
4005*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
4006*d56f51eaSDavid van Moolenbroek
4007*d56f51eaSDavid van Moolenbroek /*
4008*d56f51eaSDavid van Moolenbroek * Now check for data frames with From DS not set.
4009*d56f51eaSDavid van Moolenbroek */
4010*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 1, BPF_B);
4011*d56f51eaSDavid van Moolenbroek b2 = new_block(JMP(BPF_JSET));
4012*d56f51eaSDavid van Moolenbroek b2->s.k = 0x02; /* From DS */
4013*d56f51eaSDavid van Moolenbroek b2->stmts = s;
4014*d56f51eaSDavid van Moolenbroek gen_not(b2);
4015*d56f51eaSDavid van Moolenbroek
4016*d56f51eaSDavid van Moolenbroek /*
4017*d56f51eaSDavid van Moolenbroek * If From DS isn't set, the SA is at 10.
4018*d56f51eaSDavid van Moolenbroek */
4019*d56f51eaSDavid van Moolenbroek b1 = gen_bcmp(OR_LINKHDR, 10, 6, eaddr);
4020*d56f51eaSDavid van Moolenbroek gen_and(b2, b1);
4021*d56f51eaSDavid van Moolenbroek
4022*d56f51eaSDavid van Moolenbroek /*
4023*d56f51eaSDavid van Moolenbroek * Now OR together the checks for data frames with
4024*d56f51eaSDavid van Moolenbroek * From DS not set and for data frames with From DS
4025*d56f51eaSDavid van Moolenbroek * set; that gives the checks done for data frames.
4026*d56f51eaSDavid van Moolenbroek */
4027*d56f51eaSDavid van Moolenbroek gen_or(b1, b0);
4028*d56f51eaSDavid van Moolenbroek
4029*d56f51eaSDavid van Moolenbroek /*
4030*d56f51eaSDavid van Moolenbroek * Now check for a data frame.
4031*d56f51eaSDavid van Moolenbroek * I.e, check "link[0] & 0x08".
4032*d56f51eaSDavid van Moolenbroek */
4033*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 0, BPF_B);
4034*d56f51eaSDavid van Moolenbroek b1 = new_block(JMP(BPF_JSET));
4035*d56f51eaSDavid van Moolenbroek b1->s.k = 0x08;
4036*d56f51eaSDavid van Moolenbroek b1->stmts = s;
4037*d56f51eaSDavid van Moolenbroek
4038*d56f51eaSDavid van Moolenbroek /*
4039*d56f51eaSDavid van Moolenbroek * AND that with the checks done for data frames.
4040*d56f51eaSDavid van Moolenbroek */
4041*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
4042*d56f51eaSDavid van Moolenbroek
4043*d56f51eaSDavid van Moolenbroek /*
4044*d56f51eaSDavid van Moolenbroek * If the high-order bit of the type value is 0, this
4045*d56f51eaSDavid van Moolenbroek * is a management frame.
4046*d56f51eaSDavid van Moolenbroek * I.e, check "!(link[0] & 0x08)".
4047*d56f51eaSDavid van Moolenbroek */
4048*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 0, BPF_B);
4049*d56f51eaSDavid van Moolenbroek b2 = new_block(JMP(BPF_JSET));
4050*d56f51eaSDavid van Moolenbroek b2->s.k = 0x08;
4051*d56f51eaSDavid van Moolenbroek b2->stmts = s;
4052*d56f51eaSDavid van Moolenbroek gen_not(b2);
4053*d56f51eaSDavid van Moolenbroek
4054*d56f51eaSDavid van Moolenbroek /*
4055*d56f51eaSDavid van Moolenbroek * For management frames, the SA is at 10.
4056*d56f51eaSDavid van Moolenbroek */
4057*d56f51eaSDavid van Moolenbroek b1 = gen_bcmp(OR_LINKHDR, 10, 6, eaddr);
4058*d56f51eaSDavid van Moolenbroek gen_and(b2, b1);
4059*d56f51eaSDavid van Moolenbroek
4060*d56f51eaSDavid van Moolenbroek /*
4061*d56f51eaSDavid van Moolenbroek * OR that with the checks done for data frames.
4062*d56f51eaSDavid van Moolenbroek * That gives the checks done for management and
4063*d56f51eaSDavid van Moolenbroek * data frames.
4064*d56f51eaSDavid van Moolenbroek */
4065*d56f51eaSDavid van Moolenbroek gen_or(b1, b0);
4066*d56f51eaSDavid van Moolenbroek
4067*d56f51eaSDavid van Moolenbroek /*
4068*d56f51eaSDavid van Moolenbroek * If the low-order bit of the type value is 1,
4069*d56f51eaSDavid van Moolenbroek * this is either a control frame or a frame
4070*d56f51eaSDavid van Moolenbroek * with a reserved type, and thus not a
4071*d56f51eaSDavid van Moolenbroek * frame with an SA.
4072*d56f51eaSDavid van Moolenbroek *
4073*d56f51eaSDavid van Moolenbroek * I.e., check "!(link[0] & 0x04)".
4074*d56f51eaSDavid van Moolenbroek */
4075*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 0, BPF_B);
4076*d56f51eaSDavid van Moolenbroek b1 = new_block(JMP(BPF_JSET));
4077*d56f51eaSDavid van Moolenbroek b1->s.k = 0x04;
4078*d56f51eaSDavid van Moolenbroek b1->stmts = s;
4079*d56f51eaSDavid van Moolenbroek gen_not(b1);
4080*d56f51eaSDavid van Moolenbroek
4081*d56f51eaSDavid van Moolenbroek /*
4082*d56f51eaSDavid van Moolenbroek * AND that with the checks for data and management
4083*d56f51eaSDavid van Moolenbroek * frames.
4084*d56f51eaSDavid van Moolenbroek */
4085*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
4086*d56f51eaSDavid van Moolenbroek return b0;
4087*d56f51eaSDavid van Moolenbroek
4088*d56f51eaSDavid van Moolenbroek case Q_DST:
4089*d56f51eaSDavid van Moolenbroek /*
4090*d56f51eaSDavid van Moolenbroek * Oh, yuk.
4091*d56f51eaSDavid van Moolenbroek *
4092*d56f51eaSDavid van Moolenbroek * For control frames, there is no DA.
4093*d56f51eaSDavid van Moolenbroek *
4094*d56f51eaSDavid van Moolenbroek * For management frames, DA is at an
4095*d56f51eaSDavid van Moolenbroek * offset of 4 from the beginning of
4096*d56f51eaSDavid van Moolenbroek * the packet.
4097*d56f51eaSDavid van Moolenbroek *
4098*d56f51eaSDavid van Moolenbroek * For data frames, DA is at an offset
4099*d56f51eaSDavid van Moolenbroek * of 4 from the beginning of the packet
4100*d56f51eaSDavid van Moolenbroek * if To DS is clear and at an offset of
4101*d56f51eaSDavid van Moolenbroek * 16 from the beginning of the packet
4102*d56f51eaSDavid van Moolenbroek * if To DS is set.
4103*d56f51eaSDavid van Moolenbroek */
4104*d56f51eaSDavid van Moolenbroek
4105*d56f51eaSDavid van Moolenbroek /*
4106*d56f51eaSDavid van Moolenbroek * Generate the tests to be done for data frames.
4107*d56f51eaSDavid van Moolenbroek *
4108*d56f51eaSDavid van Moolenbroek * First, check for To DS set, i.e. "link[1] & 0x01".
4109*d56f51eaSDavid van Moolenbroek */
4110*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 1, BPF_B);
4111*d56f51eaSDavid van Moolenbroek b1 = new_block(JMP(BPF_JSET));
4112*d56f51eaSDavid van Moolenbroek b1->s.k = 0x01; /* To DS */
4113*d56f51eaSDavid van Moolenbroek b1->stmts = s;
4114*d56f51eaSDavid van Moolenbroek
4115*d56f51eaSDavid van Moolenbroek /*
4116*d56f51eaSDavid van Moolenbroek * If To DS is set, the DA is at 16.
4117*d56f51eaSDavid van Moolenbroek */
4118*d56f51eaSDavid van Moolenbroek b0 = gen_bcmp(OR_LINKHDR, 16, 6, eaddr);
4119*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
4120*d56f51eaSDavid van Moolenbroek
4121*d56f51eaSDavid van Moolenbroek /*
4122*d56f51eaSDavid van Moolenbroek * Now, check for To DS not set, i.e. check
4123*d56f51eaSDavid van Moolenbroek * "!(link[1] & 0x01)".
4124*d56f51eaSDavid van Moolenbroek */
4125*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 1, BPF_B);
4126*d56f51eaSDavid van Moolenbroek b2 = new_block(JMP(BPF_JSET));
4127*d56f51eaSDavid van Moolenbroek b2->s.k = 0x01; /* To DS */
4128*d56f51eaSDavid van Moolenbroek b2->stmts = s;
4129*d56f51eaSDavid van Moolenbroek gen_not(b2);
4130*d56f51eaSDavid van Moolenbroek
4131*d56f51eaSDavid van Moolenbroek /*
4132*d56f51eaSDavid van Moolenbroek * If To DS is not set, the DA is at 4.
4133*d56f51eaSDavid van Moolenbroek */
4134*d56f51eaSDavid van Moolenbroek b1 = gen_bcmp(OR_LINKHDR, 4, 6, eaddr);
4135*d56f51eaSDavid van Moolenbroek gen_and(b2, b1);
4136*d56f51eaSDavid van Moolenbroek
4137*d56f51eaSDavid van Moolenbroek /*
4138*d56f51eaSDavid van Moolenbroek * Now OR together the last two checks. That gives
4139*d56f51eaSDavid van Moolenbroek * the complete set of checks for data frames.
4140*d56f51eaSDavid van Moolenbroek */
4141*d56f51eaSDavid van Moolenbroek gen_or(b1, b0);
4142*d56f51eaSDavid van Moolenbroek
4143*d56f51eaSDavid van Moolenbroek /*
4144*d56f51eaSDavid van Moolenbroek * Now check for a data frame.
4145*d56f51eaSDavid van Moolenbroek * I.e, check "link[0] & 0x08".
4146*d56f51eaSDavid van Moolenbroek */
4147*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 0, BPF_B);
4148*d56f51eaSDavid van Moolenbroek b1 = new_block(JMP(BPF_JSET));
4149*d56f51eaSDavid van Moolenbroek b1->s.k = 0x08;
4150*d56f51eaSDavid van Moolenbroek b1->stmts = s;
4151*d56f51eaSDavid van Moolenbroek
4152*d56f51eaSDavid van Moolenbroek /*
4153*d56f51eaSDavid van Moolenbroek * AND that with the checks done for data frames.
4154*d56f51eaSDavid van Moolenbroek */
4155*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
4156*d56f51eaSDavid van Moolenbroek
4157*d56f51eaSDavid van Moolenbroek /*
4158*d56f51eaSDavid van Moolenbroek * If the high-order bit of the type value is 0, this
4159*d56f51eaSDavid van Moolenbroek * is a management frame.
4160*d56f51eaSDavid van Moolenbroek * I.e, check "!(link[0] & 0x08)".
4161*d56f51eaSDavid van Moolenbroek */
4162*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 0, BPF_B);
4163*d56f51eaSDavid van Moolenbroek b2 = new_block(JMP(BPF_JSET));
4164*d56f51eaSDavid van Moolenbroek b2->s.k = 0x08;
4165*d56f51eaSDavid van Moolenbroek b2->stmts = s;
4166*d56f51eaSDavid van Moolenbroek gen_not(b2);
4167*d56f51eaSDavid van Moolenbroek
4168*d56f51eaSDavid van Moolenbroek /*
4169*d56f51eaSDavid van Moolenbroek * For management frames, the DA is at 4.
4170*d56f51eaSDavid van Moolenbroek */
4171*d56f51eaSDavid van Moolenbroek b1 = gen_bcmp(OR_LINKHDR, 4, 6, eaddr);
4172*d56f51eaSDavid van Moolenbroek gen_and(b2, b1);
4173*d56f51eaSDavid van Moolenbroek
4174*d56f51eaSDavid van Moolenbroek /*
4175*d56f51eaSDavid van Moolenbroek * OR that with the checks done for data frames.
4176*d56f51eaSDavid van Moolenbroek * That gives the checks done for management and
4177*d56f51eaSDavid van Moolenbroek * data frames.
4178*d56f51eaSDavid van Moolenbroek */
4179*d56f51eaSDavid van Moolenbroek gen_or(b1, b0);
4180*d56f51eaSDavid van Moolenbroek
4181*d56f51eaSDavid van Moolenbroek /*
4182*d56f51eaSDavid van Moolenbroek * If the low-order bit of the type value is 1,
4183*d56f51eaSDavid van Moolenbroek * this is either a control frame or a frame
4184*d56f51eaSDavid van Moolenbroek * with a reserved type, and thus not a
4185*d56f51eaSDavid van Moolenbroek * frame with an SA.
4186*d56f51eaSDavid van Moolenbroek *
4187*d56f51eaSDavid van Moolenbroek * I.e., check "!(link[0] & 0x04)".
4188*d56f51eaSDavid van Moolenbroek */
4189*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 0, BPF_B);
4190*d56f51eaSDavid van Moolenbroek b1 = new_block(JMP(BPF_JSET));
4191*d56f51eaSDavid van Moolenbroek b1->s.k = 0x04;
4192*d56f51eaSDavid van Moolenbroek b1->stmts = s;
4193*d56f51eaSDavid van Moolenbroek gen_not(b1);
4194*d56f51eaSDavid van Moolenbroek
4195*d56f51eaSDavid van Moolenbroek /*
4196*d56f51eaSDavid van Moolenbroek * AND that with the checks for data and management
4197*d56f51eaSDavid van Moolenbroek * frames.
4198*d56f51eaSDavid van Moolenbroek */
4199*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
4200*d56f51eaSDavid van Moolenbroek return b0;
4201*d56f51eaSDavid van Moolenbroek
4202*d56f51eaSDavid van Moolenbroek case Q_RA:
4203*d56f51eaSDavid van Moolenbroek /*
4204*d56f51eaSDavid van Moolenbroek * Not present in management frames; addr1 in other
4205*d56f51eaSDavid van Moolenbroek * frames.
4206*d56f51eaSDavid van Moolenbroek */
4207*d56f51eaSDavid van Moolenbroek
4208*d56f51eaSDavid van Moolenbroek /*
4209*d56f51eaSDavid van Moolenbroek * If the high-order bit of the type value is 0, this
4210*d56f51eaSDavid van Moolenbroek * is a management frame.
4211*d56f51eaSDavid van Moolenbroek * I.e, check "(link[0] & 0x08)".
4212*d56f51eaSDavid van Moolenbroek */
4213*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 0, BPF_B);
4214*d56f51eaSDavid van Moolenbroek b1 = new_block(JMP(BPF_JSET));
4215*d56f51eaSDavid van Moolenbroek b1->s.k = 0x08;
4216*d56f51eaSDavid van Moolenbroek b1->stmts = s;
4217*d56f51eaSDavid van Moolenbroek
4218*d56f51eaSDavid van Moolenbroek /*
4219*d56f51eaSDavid van Moolenbroek * Check addr1.
4220*d56f51eaSDavid van Moolenbroek */
4221*d56f51eaSDavid van Moolenbroek b0 = gen_bcmp(OR_LINKHDR, 4, 6, eaddr);
4222*d56f51eaSDavid van Moolenbroek
4223*d56f51eaSDavid van Moolenbroek /*
4224*d56f51eaSDavid van Moolenbroek * AND that with the check of addr1.
4225*d56f51eaSDavid van Moolenbroek */
4226*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
4227*d56f51eaSDavid van Moolenbroek return (b0);
4228*d56f51eaSDavid van Moolenbroek
4229*d56f51eaSDavid van Moolenbroek case Q_TA:
4230*d56f51eaSDavid van Moolenbroek /*
4231*d56f51eaSDavid van Moolenbroek * Not present in management frames; addr2, if present,
4232*d56f51eaSDavid van Moolenbroek * in other frames.
4233*d56f51eaSDavid van Moolenbroek */
4234*d56f51eaSDavid van Moolenbroek
4235*d56f51eaSDavid van Moolenbroek /*
4236*d56f51eaSDavid van Moolenbroek * Not present in CTS or ACK control frames.
4237*d56f51eaSDavid van Moolenbroek */
4238*d56f51eaSDavid van Moolenbroek b0 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
4239*d56f51eaSDavid van Moolenbroek IEEE80211_FC0_TYPE_MASK);
4240*d56f51eaSDavid van Moolenbroek gen_not(b0);
4241*d56f51eaSDavid van Moolenbroek b1 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
4242*d56f51eaSDavid van Moolenbroek IEEE80211_FC0_SUBTYPE_MASK);
4243*d56f51eaSDavid van Moolenbroek gen_not(b1);
4244*d56f51eaSDavid van Moolenbroek b2 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
4245*d56f51eaSDavid van Moolenbroek IEEE80211_FC0_SUBTYPE_MASK);
4246*d56f51eaSDavid van Moolenbroek gen_not(b2);
4247*d56f51eaSDavid van Moolenbroek gen_and(b1, b2);
4248*d56f51eaSDavid van Moolenbroek gen_or(b0, b2);
4249*d56f51eaSDavid van Moolenbroek
4250*d56f51eaSDavid van Moolenbroek /*
4251*d56f51eaSDavid van Moolenbroek * If the high-order bit of the type value is 0, this
4252*d56f51eaSDavid van Moolenbroek * is a management frame.
4253*d56f51eaSDavid van Moolenbroek * I.e, check "(link[0] & 0x08)".
4254*d56f51eaSDavid van Moolenbroek */
4255*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 0, BPF_B);
4256*d56f51eaSDavid van Moolenbroek b1 = new_block(JMP(BPF_JSET));
4257*d56f51eaSDavid van Moolenbroek b1->s.k = 0x08;
4258*d56f51eaSDavid van Moolenbroek b1->stmts = s;
4259*d56f51eaSDavid van Moolenbroek
4260*d56f51eaSDavid van Moolenbroek /*
4261*d56f51eaSDavid van Moolenbroek * AND that with the check for frames other than
4262*d56f51eaSDavid van Moolenbroek * CTS and ACK frames.
4263*d56f51eaSDavid van Moolenbroek */
4264*d56f51eaSDavid van Moolenbroek gen_and(b1, b2);
4265*d56f51eaSDavid van Moolenbroek
4266*d56f51eaSDavid van Moolenbroek /*
4267*d56f51eaSDavid van Moolenbroek * Check addr2.
4268*d56f51eaSDavid van Moolenbroek */
4269*d56f51eaSDavid van Moolenbroek b1 = gen_bcmp(OR_LINKHDR, 10, 6, eaddr);
4270*d56f51eaSDavid van Moolenbroek gen_and(b2, b1);
4271*d56f51eaSDavid van Moolenbroek return b1;
4272*d56f51eaSDavid van Moolenbroek
4273*d56f51eaSDavid van Moolenbroek /*
4274*d56f51eaSDavid van Moolenbroek * XXX - add BSSID keyword?
4275*d56f51eaSDavid van Moolenbroek */
4276*d56f51eaSDavid van Moolenbroek case Q_ADDR1:
4277*d56f51eaSDavid van Moolenbroek return (gen_bcmp(OR_LINKHDR, 4, 6, eaddr));
4278*d56f51eaSDavid van Moolenbroek
4279*d56f51eaSDavid van Moolenbroek case Q_ADDR2:
4280*d56f51eaSDavid van Moolenbroek /*
4281*d56f51eaSDavid van Moolenbroek * Not present in CTS or ACK control frames.
4282*d56f51eaSDavid van Moolenbroek */
4283*d56f51eaSDavid van Moolenbroek b0 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
4284*d56f51eaSDavid van Moolenbroek IEEE80211_FC0_TYPE_MASK);
4285*d56f51eaSDavid van Moolenbroek gen_not(b0);
4286*d56f51eaSDavid van Moolenbroek b1 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
4287*d56f51eaSDavid van Moolenbroek IEEE80211_FC0_SUBTYPE_MASK);
4288*d56f51eaSDavid van Moolenbroek gen_not(b1);
4289*d56f51eaSDavid van Moolenbroek b2 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
4290*d56f51eaSDavid van Moolenbroek IEEE80211_FC0_SUBTYPE_MASK);
4291*d56f51eaSDavid van Moolenbroek gen_not(b2);
4292*d56f51eaSDavid van Moolenbroek gen_and(b1, b2);
4293*d56f51eaSDavid van Moolenbroek gen_or(b0, b2);
4294*d56f51eaSDavid van Moolenbroek b1 = gen_bcmp(OR_LINKHDR, 10, 6, eaddr);
4295*d56f51eaSDavid van Moolenbroek gen_and(b2, b1);
4296*d56f51eaSDavid van Moolenbroek return b1;
4297*d56f51eaSDavid van Moolenbroek
4298*d56f51eaSDavid van Moolenbroek case Q_ADDR3:
4299*d56f51eaSDavid van Moolenbroek /*
4300*d56f51eaSDavid van Moolenbroek * Not present in control frames.
4301*d56f51eaSDavid van Moolenbroek */
4302*d56f51eaSDavid van Moolenbroek b0 = gen_mcmp(OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
4303*d56f51eaSDavid van Moolenbroek IEEE80211_FC0_TYPE_MASK);
4304*d56f51eaSDavid van Moolenbroek gen_not(b0);
4305*d56f51eaSDavid van Moolenbroek b1 = gen_bcmp(OR_LINKHDR, 16, 6, eaddr);
4306*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
4307*d56f51eaSDavid van Moolenbroek return b1;
4308*d56f51eaSDavid van Moolenbroek
4309*d56f51eaSDavid van Moolenbroek case Q_ADDR4:
4310*d56f51eaSDavid van Moolenbroek /*
4311*d56f51eaSDavid van Moolenbroek * Present only if the direction mask has both "From DS"
4312*d56f51eaSDavid van Moolenbroek * and "To DS" set. Neither control frames nor management
4313*d56f51eaSDavid van Moolenbroek * frames should have both of those set, so we don't
4314*d56f51eaSDavid van Moolenbroek * check the frame type.
4315*d56f51eaSDavid van Moolenbroek */
4316*d56f51eaSDavid van Moolenbroek b0 = gen_mcmp(OR_LINKHDR, 1, BPF_B,
4317*d56f51eaSDavid van Moolenbroek IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
4318*d56f51eaSDavid van Moolenbroek b1 = gen_bcmp(OR_LINKHDR, 24, 6, eaddr);
4319*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
4320*d56f51eaSDavid van Moolenbroek return b1;
4321*d56f51eaSDavid van Moolenbroek
4322*d56f51eaSDavid van Moolenbroek case Q_AND:
4323*d56f51eaSDavid van Moolenbroek b0 = gen_wlanhostop(eaddr, Q_SRC);
4324*d56f51eaSDavid van Moolenbroek b1 = gen_wlanhostop(eaddr, Q_DST);
4325*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
4326*d56f51eaSDavid van Moolenbroek return b1;
4327*d56f51eaSDavid van Moolenbroek
4328*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
4329*d56f51eaSDavid van Moolenbroek case Q_OR:
4330*d56f51eaSDavid van Moolenbroek b0 = gen_wlanhostop(eaddr, Q_SRC);
4331*d56f51eaSDavid van Moolenbroek b1 = gen_wlanhostop(eaddr, Q_DST);
4332*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
4333*d56f51eaSDavid van Moolenbroek return b1;
4334*d56f51eaSDavid van Moolenbroek }
4335*d56f51eaSDavid van Moolenbroek abort();
4336*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
4337*d56f51eaSDavid van Moolenbroek }
4338*d56f51eaSDavid van Moolenbroek
4339*d56f51eaSDavid van Moolenbroek /*
4340*d56f51eaSDavid van Moolenbroek * Like gen_ehostop, but for RFC 2625 IP-over-Fibre-Channel.
4341*d56f51eaSDavid van Moolenbroek * (We assume that the addresses are IEEE 48-bit MAC addresses,
4342*d56f51eaSDavid van Moolenbroek * as the RFC states.)
4343*d56f51eaSDavid van Moolenbroek */
4344*d56f51eaSDavid van Moolenbroek static struct block *
gen_ipfchostop(eaddr,dir)4345*d56f51eaSDavid van Moolenbroek gen_ipfchostop(eaddr, dir)
4346*d56f51eaSDavid van Moolenbroek register const u_char *eaddr;
4347*d56f51eaSDavid van Moolenbroek register int dir;
4348*d56f51eaSDavid van Moolenbroek {
4349*d56f51eaSDavid van Moolenbroek register struct block *b0, *b1;
4350*d56f51eaSDavid van Moolenbroek
4351*d56f51eaSDavid van Moolenbroek switch (dir) {
4352*d56f51eaSDavid van Moolenbroek case Q_SRC:
4353*d56f51eaSDavid van Moolenbroek return gen_bcmp(OR_LINKHDR, 10, 6, eaddr);
4354*d56f51eaSDavid van Moolenbroek
4355*d56f51eaSDavid van Moolenbroek case Q_DST:
4356*d56f51eaSDavid van Moolenbroek return gen_bcmp(OR_LINKHDR, 2, 6, eaddr);
4357*d56f51eaSDavid van Moolenbroek
4358*d56f51eaSDavid van Moolenbroek case Q_AND:
4359*d56f51eaSDavid van Moolenbroek b0 = gen_ipfchostop(eaddr, Q_SRC);
4360*d56f51eaSDavid van Moolenbroek b1 = gen_ipfchostop(eaddr, Q_DST);
4361*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
4362*d56f51eaSDavid van Moolenbroek return b1;
4363*d56f51eaSDavid van Moolenbroek
4364*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
4365*d56f51eaSDavid van Moolenbroek case Q_OR:
4366*d56f51eaSDavid van Moolenbroek b0 = gen_ipfchostop(eaddr, Q_SRC);
4367*d56f51eaSDavid van Moolenbroek b1 = gen_ipfchostop(eaddr, Q_DST);
4368*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
4369*d56f51eaSDavid van Moolenbroek return b1;
4370*d56f51eaSDavid van Moolenbroek
4371*d56f51eaSDavid van Moolenbroek case Q_ADDR1:
4372*d56f51eaSDavid van Moolenbroek bpf_error("'addr1' is only supported on 802.11");
4373*d56f51eaSDavid van Moolenbroek break;
4374*d56f51eaSDavid van Moolenbroek
4375*d56f51eaSDavid van Moolenbroek case Q_ADDR2:
4376*d56f51eaSDavid van Moolenbroek bpf_error("'addr2' is only supported on 802.11");
4377*d56f51eaSDavid van Moolenbroek break;
4378*d56f51eaSDavid van Moolenbroek
4379*d56f51eaSDavid van Moolenbroek case Q_ADDR3:
4380*d56f51eaSDavid van Moolenbroek bpf_error("'addr3' is only supported on 802.11");
4381*d56f51eaSDavid van Moolenbroek break;
4382*d56f51eaSDavid van Moolenbroek
4383*d56f51eaSDavid van Moolenbroek case Q_ADDR4:
4384*d56f51eaSDavid van Moolenbroek bpf_error("'addr4' is only supported on 802.11");
4385*d56f51eaSDavid van Moolenbroek break;
4386*d56f51eaSDavid van Moolenbroek
4387*d56f51eaSDavid van Moolenbroek case Q_RA:
4388*d56f51eaSDavid van Moolenbroek bpf_error("'ra' is only supported on 802.11");
4389*d56f51eaSDavid van Moolenbroek break;
4390*d56f51eaSDavid van Moolenbroek
4391*d56f51eaSDavid van Moolenbroek case Q_TA:
4392*d56f51eaSDavid van Moolenbroek bpf_error("'ta' is only supported on 802.11");
4393*d56f51eaSDavid van Moolenbroek break;
4394*d56f51eaSDavid van Moolenbroek }
4395*d56f51eaSDavid van Moolenbroek abort();
4396*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
4397*d56f51eaSDavid van Moolenbroek }
4398*d56f51eaSDavid van Moolenbroek
4399*d56f51eaSDavid van Moolenbroek /*
4400*d56f51eaSDavid van Moolenbroek * This is quite tricky because there may be pad bytes in front of the
4401*d56f51eaSDavid van Moolenbroek * DECNET header, and then there are two possible data packet formats that
4402*d56f51eaSDavid van Moolenbroek * carry both src and dst addresses, plus 5 packet types in a format that
4403*d56f51eaSDavid van Moolenbroek * carries only the src node, plus 2 types that use a different format and
4404*d56f51eaSDavid van Moolenbroek * also carry just the src node.
4405*d56f51eaSDavid van Moolenbroek *
4406*d56f51eaSDavid van Moolenbroek * Yuck.
4407*d56f51eaSDavid van Moolenbroek *
4408*d56f51eaSDavid van Moolenbroek * Instead of doing those all right, we just look for data packets with
4409*d56f51eaSDavid van Moolenbroek * 0 or 1 bytes of padding. If you want to look at other packets, that
4410*d56f51eaSDavid van Moolenbroek * will require a lot more hacking.
4411*d56f51eaSDavid van Moolenbroek *
4412*d56f51eaSDavid van Moolenbroek * To add support for filtering on DECNET "areas" (network numbers)
4413*d56f51eaSDavid van Moolenbroek * one would want to add a "mask" argument to this routine. That would
4414*d56f51eaSDavid van Moolenbroek * make the filter even more inefficient, although one could be clever
4415*d56f51eaSDavid van Moolenbroek * and not generate masking instructions if the mask is 0xFFFF.
4416*d56f51eaSDavid van Moolenbroek */
4417*d56f51eaSDavid van Moolenbroek static struct block *
gen_dnhostop(addr,dir)4418*d56f51eaSDavid van Moolenbroek gen_dnhostop(addr, dir)
4419*d56f51eaSDavid van Moolenbroek bpf_u_int32 addr;
4420*d56f51eaSDavid van Moolenbroek int dir;
4421*d56f51eaSDavid van Moolenbroek {
4422*d56f51eaSDavid van Moolenbroek struct block *b0, *b1, *b2, *tmp;
4423*d56f51eaSDavid van Moolenbroek u_int offset_lh; /* offset if long header is received */
4424*d56f51eaSDavid van Moolenbroek u_int offset_sh; /* offset if short header is received */
4425*d56f51eaSDavid van Moolenbroek
4426*d56f51eaSDavid van Moolenbroek switch (dir) {
4427*d56f51eaSDavid van Moolenbroek
4428*d56f51eaSDavid van Moolenbroek case Q_DST:
4429*d56f51eaSDavid van Moolenbroek offset_sh = 1; /* follows flags */
4430*d56f51eaSDavid van Moolenbroek offset_lh = 7; /* flgs,darea,dsubarea,HIORD */
4431*d56f51eaSDavid van Moolenbroek break;
4432*d56f51eaSDavid van Moolenbroek
4433*d56f51eaSDavid van Moolenbroek case Q_SRC:
4434*d56f51eaSDavid van Moolenbroek offset_sh = 3; /* follows flags, dstnode */
4435*d56f51eaSDavid van Moolenbroek offset_lh = 15; /* flgs,darea,dsubarea,did,sarea,ssub,HIORD */
4436*d56f51eaSDavid van Moolenbroek break;
4437*d56f51eaSDavid van Moolenbroek
4438*d56f51eaSDavid van Moolenbroek case Q_AND:
4439*d56f51eaSDavid van Moolenbroek /* Inefficient because we do our Calvinball dance twice */
4440*d56f51eaSDavid van Moolenbroek b0 = gen_dnhostop(addr, Q_SRC);
4441*d56f51eaSDavid van Moolenbroek b1 = gen_dnhostop(addr, Q_DST);
4442*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
4443*d56f51eaSDavid van Moolenbroek return b1;
4444*d56f51eaSDavid van Moolenbroek
4445*d56f51eaSDavid van Moolenbroek case Q_OR:
4446*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
4447*d56f51eaSDavid van Moolenbroek /* Inefficient because we do our Calvinball dance twice */
4448*d56f51eaSDavid van Moolenbroek b0 = gen_dnhostop(addr, Q_SRC);
4449*d56f51eaSDavid van Moolenbroek b1 = gen_dnhostop(addr, Q_DST);
4450*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
4451*d56f51eaSDavid van Moolenbroek return b1;
4452*d56f51eaSDavid van Moolenbroek
4453*d56f51eaSDavid van Moolenbroek case Q_ISO:
4454*d56f51eaSDavid van Moolenbroek bpf_error("ISO host filtering not implemented");
4455*d56f51eaSDavid van Moolenbroek
4456*d56f51eaSDavid van Moolenbroek default:
4457*d56f51eaSDavid van Moolenbroek abort();
4458*d56f51eaSDavid van Moolenbroek }
4459*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(ETHERTYPE_DN);
4460*d56f51eaSDavid van Moolenbroek /* Check for pad = 1, long header case */
4461*d56f51eaSDavid van Moolenbroek tmp = gen_mcmp(OR_LINKPL, 2, BPF_H,
4462*d56f51eaSDavid van Moolenbroek (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF));
4463*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LINKPL, 2 + 1 + offset_lh,
4464*d56f51eaSDavid van Moolenbroek BPF_H, (bpf_int32)ntohs((u_short)addr));
4465*d56f51eaSDavid van Moolenbroek gen_and(tmp, b1);
4466*d56f51eaSDavid van Moolenbroek /* Check for pad = 0, long header case */
4467*d56f51eaSDavid van Moolenbroek tmp = gen_mcmp(OR_LINKPL, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
4468*d56f51eaSDavid van Moolenbroek b2 = gen_cmp(OR_LINKPL, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr));
4469*d56f51eaSDavid van Moolenbroek gen_and(tmp, b2);
4470*d56f51eaSDavid van Moolenbroek gen_or(b2, b1);
4471*d56f51eaSDavid van Moolenbroek /* Check for pad = 1, short header case */
4472*d56f51eaSDavid van Moolenbroek tmp = gen_mcmp(OR_LINKPL, 2, BPF_H,
4473*d56f51eaSDavid van Moolenbroek (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF));
4474*d56f51eaSDavid van Moolenbroek b2 = gen_cmp(OR_LINKPL, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
4475*d56f51eaSDavid van Moolenbroek gen_and(tmp, b2);
4476*d56f51eaSDavid van Moolenbroek gen_or(b2, b1);
4477*d56f51eaSDavid van Moolenbroek /* Check for pad = 0, short header case */
4478*d56f51eaSDavid van Moolenbroek tmp = gen_mcmp(OR_LINKPL, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
4479*d56f51eaSDavid van Moolenbroek b2 = gen_cmp(OR_LINKPL, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
4480*d56f51eaSDavid van Moolenbroek gen_and(tmp, b2);
4481*d56f51eaSDavid van Moolenbroek gen_or(b2, b1);
4482*d56f51eaSDavid van Moolenbroek
4483*d56f51eaSDavid van Moolenbroek /* Combine with test for linktype */
4484*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
4485*d56f51eaSDavid van Moolenbroek return b1;
4486*d56f51eaSDavid van Moolenbroek }
4487*d56f51eaSDavid van Moolenbroek
4488*d56f51eaSDavid van Moolenbroek /*
4489*d56f51eaSDavid van Moolenbroek * Generate a check for IPv4 or IPv6 for MPLS-encapsulated packets;
4490*d56f51eaSDavid van Moolenbroek * test the bottom-of-stack bit, and then check the version number
4491*d56f51eaSDavid van Moolenbroek * field in the IP header.
4492*d56f51eaSDavid van Moolenbroek */
4493*d56f51eaSDavid van Moolenbroek static struct block *
gen_mpls_linktype(proto)4494*d56f51eaSDavid van Moolenbroek gen_mpls_linktype(proto)
4495*d56f51eaSDavid van Moolenbroek int proto;
4496*d56f51eaSDavid van Moolenbroek {
4497*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
4498*d56f51eaSDavid van Moolenbroek
4499*d56f51eaSDavid van Moolenbroek switch (proto) {
4500*d56f51eaSDavid van Moolenbroek
4501*d56f51eaSDavid van Moolenbroek case Q_IP:
4502*d56f51eaSDavid van Moolenbroek /* match the bottom-of-stack bit */
4503*d56f51eaSDavid van Moolenbroek b0 = gen_mcmp(OR_LINKPL, -2, BPF_B, 0x01, 0x01);
4504*d56f51eaSDavid van Moolenbroek /* match the IPv4 version number */
4505*d56f51eaSDavid van Moolenbroek b1 = gen_mcmp(OR_LINKPL, 0, BPF_B, 0x40, 0xf0);
4506*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
4507*d56f51eaSDavid van Moolenbroek return b1;
4508*d56f51eaSDavid van Moolenbroek
4509*d56f51eaSDavid van Moolenbroek case Q_IPV6:
4510*d56f51eaSDavid van Moolenbroek /* match the bottom-of-stack bit */
4511*d56f51eaSDavid van Moolenbroek b0 = gen_mcmp(OR_LINKPL, -2, BPF_B, 0x01, 0x01);
4512*d56f51eaSDavid van Moolenbroek /* match the IPv4 version number */
4513*d56f51eaSDavid van Moolenbroek b1 = gen_mcmp(OR_LINKPL, 0, BPF_B, 0x60, 0xf0);
4514*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
4515*d56f51eaSDavid van Moolenbroek return b1;
4516*d56f51eaSDavid van Moolenbroek
4517*d56f51eaSDavid van Moolenbroek default:
4518*d56f51eaSDavid van Moolenbroek abort();
4519*d56f51eaSDavid van Moolenbroek }
4520*d56f51eaSDavid van Moolenbroek }
4521*d56f51eaSDavid van Moolenbroek
4522*d56f51eaSDavid van Moolenbroek static struct block *
gen_host(addr,mask,proto,dir,type)4523*d56f51eaSDavid van Moolenbroek gen_host(addr, mask, proto, dir, type)
4524*d56f51eaSDavid van Moolenbroek bpf_u_int32 addr;
4525*d56f51eaSDavid van Moolenbroek bpf_u_int32 mask;
4526*d56f51eaSDavid van Moolenbroek int proto;
4527*d56f51eaSDavid van Moolenbroek int dir;
4528*d56f51eaSDavid van Moolenbroek int type;
4529*d56f51eaSDavid van Moolenbroek {
4530*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
4531*d56f51eaSDavid van Moolenbroek const char *typestr;
4532*d56f51eaSDavid van Moolenbroek
4533*d56f51eaSDavid van Moolenbroek if (type == Q_NET)
4534*d56f51eaSDavid van Moolenbroek typestr = "net";
4535*d56f51eaSDavid van Moolenbroek else
4536*d56f51eaSDavid van Moolenbroek typestr = "host";
4537*d56f51eaSDavid van Moolenbroek
4538*d56f51eaSDavid van Moolenbroek switch (proto) {
4539*d56f51eaSDavid van Moolenbroek
4540*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
4541*d56f51eaSDavid van Moolenbroek b0 = gen_host(addr, mask, Q_IP, dir, type);
4542*d56f51eaSDavid van Moolenbroek /*
4543*d56f51eaSDavid van Moolenbroek * Only check for non-IPv4 addresses if we're not
4544*d56f51eaSDavid van Moolenbroek * checking MPLS-encapsulated packets.
4545*d56f51eaSDavid van Moolenbroek */
4546*d56f51eaSDavid van Moolenbroek if (label_stack_depth == 0) {
4547*d56f51eaSDavid van Moolenbroek b1 = gen_host(addr, mask, Q_ARP, dir, type);
4548*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
4549*d56f51eaSDavid van Moolenbroek b0 = gen_host(addr, mask, Q_RARP, dir, type);
4550*d56f51eaSDavid van Moolenbroek gen_or(b1, b0);
4551*d56f51eaSDavid van Moolenbroek }
4552*d56f51eaSDavid van Moolenbroek return b0;
4553*d56f51eaSDavid van Moolenbroek
4554*d56f51eaSDavid van Moolenbroek case Q_IP:
4555*d56f51eaSDavid van Moolenbroek return gen_hostop(addr, mask, dir, ETHERTYPE_IP, 12, 16);
4556*d56f51eaSDavid van Moolenbroek
4557*d56f51eaSDavid van Moolenbroek case Q_RARP:
4558*d56f51eaSDavid van Moolenbroek return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, 14, 24);
4559*d56f51eaSDavid van Moolenbroek
4560*d56f51eaSDavid van Moolenbroek case Q_ARP:
4561*d56f51eaSDavid van Moolenbroek return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, 14, 24);
4562*d56f51eaSDavid van Moolenbroek
4563*d56f51eaSDavid van Moolenbroek case Q_TCP:
4564*d56f51eaSDavid van Moolenbroek bpf_error("'tcp' modifier applied to %s", typestr);
4565*d56f51eaSDavid van Moolenbroek
4566*d56f51eaSDavid van Moolenbroek case Q_SCTP:
4567*d56f51eaSDavid van Moolenbroek bpf_error("'sctp' modifier applied to %s", typestr);
4568*d56f51eaSDavid van Moolenbroek
4569*d56f51eaSDavid van Moolenbroek case Q_UDP:
4570*d56f51eaSDavid van Moolenbroek bpf_error("'udp' modifier applied to %s", typestr);
4571*d56f51eaSDavid van Moolenbroek
4572*d56f51eaSDavid van Moolenbroek case Q_ICMP:
4573*d56f51eaSDavid van Moolenbroek bpf_error("'icmp' modifier applied to %s", typestr);
4574*d56f51eaSDavid van Moolenbroek
4575*d56f51eaSDavid van Moolenbroek case Q_IGMP:
4576*d56f51eaSDavid van Moolenbroek bpf_error("'igmp' modifier applied to %s", typestr);
4577*d56f51eaSDavid van Moolenbroek
4578*d56f51eaSDavid van Moolenbroek case Q_IGRP:
4579*d56f51eaSDavid van Moolenbroek bpf_error("'igrp' modifier applied to %s", typestr);
4580*d56f51eaSDavid van Moolenbroek
4581*d56f51eaSDavid van Moolenbroek case Q_PIM:
4582*d56f51eaSDavid van Moolenbroek bpf_error("'pim' modifier applied to %s", typestr);
4583*d56f51eaSDavid van Moolenbroek
4584*d56f51eaSDavid van Moolenbroek case Q_VRRP:
4585*d56f51eaSDavid van Moolenbroek bpf_error("'vrrp' modifier applied to %s", typestr);
4586*d56f51eaSDavid van Moolenbroek
4587*d56f51eaSDavid van Moolenbroek case Q_CARP:
4588*d56f51eaSDavid van Moolenbroek bpf_error("'carp' modifier applied to %s", typestr);
4589*d56f51eaSDavid van Moolenbroek
4590*d56f51eaSDavid van Moolenbroek case Q_ATALK:
4591*d56f51eaSDavid van Moolenbroek bpf_error("ATALK host filtering not implemented");
4592*d56f51eaSDavid van Moolenbroek
4593*d56f51eaSDavid van Moolenbroek case Q_AARP:
4594*d56f51eaSDavid van Moolenbroek bpf_error("AARP host filtering not implemented");
4595*d56f51eaSDavid van Moolenbroek
4596*d56f51eaSDavid van Moolenbroek case Q_DECNET:
4597*d56f51eaSDavid van Moolenbroek return gen_dnhostop(addr, dir);
4598*d56f51eaSDavid van Moolenbroek
4599*d56f51eaSDavid van Moolenbroek case Q_SCA:
4600*d56f51eaSDavid van Moolenbroek bpf_error("SCA host filtering not implemented");
4601*d56f51eaSDavid van Moolenbroek
4602*d56f51eaSDavid van Moolenbroek case Q_LAT:
4603*d56f51eaSDavid van Moolenbroek bpf_error("LAT host filtering not implemented");
4604*d56f51eaSDavid van Moolenbroek
4605*d56f51eaSDavid van Moolenbroek case Q_MOPDL:
4606*d56f51eaSDavid van Moolenbroek bpf_error("MOPDL host filtering not implemented");
4607*d56f51eaSDavid van Moolenbroek
4608*d56f51eaSDavid van Moolenbroek case Q_MOPRC:
4609*d56f51eaSDavid van Moolenbroek bpf_error("MOPRC host filtering not implemented");
4610*d56f51eaSDavid van Moolenbroek
4611*d56f51eaSDavid van Moolenbroek case Q_IPV6:
4612*d56f51eaSDavid van Moolenbroek bpf_error("'ip6' modifier applied to ip host");
4613*d56f51eaSDavid van Moolenbroek
4614*d56f51eaSDavid van Moolenbroek case Q_ICMPV6:
4615*d56f51eaSDavid van Moolenbroek bpf_error("'icmp6' modifier applied to %s", typestr);
4616*d56f51eaSDavid van Moolenbroek
4617*d56f51eaSDavid van Moolenbroek case Q_AH:
4618*d56f51eaSDavid van Moolenbroek bpf_error("'ah' modifier applied to %s", typestr);
4619*d56f51eaSDavid van Moolenbroek
4620*d56f51eaSDavid van Moolenbroek case Q_ESP:
4621*d56f51eaSDavid van Moolenbroek bpf_error("'esp' modifier applied to %s", typestr);
4622*d56f51eaSDavid van Moolenbroek
4623*d56f51eaSDavid van Moolenbroek case Q_ISO:
4624*d56f51eaSDavid van Moolenbroek bpf_error("ISO host filtering not implemented");
4625*d56f51eaSDavid van Moolenbroek
4626*d56f51eaSDavid van Moolenbroek case Q_ESIS:
4627*d56f51eaSDavid van Moolenbroek bpf_error("'esis' modifier applied to %s", typestr);
4628*d56f51eaSDavid van Moolenbroek
4629*d56f51eaSDavid van Moolenbroek case Q_ISIS:
4630*d56f51eaSDavid van Moolenbroek bpf_error("'isis' modifier applied to %s", typestr);
4631*d56f51eaSDavid van Moolenbroek
4632*d56f51eaSDavid van Moolenbroek case Q_CLNP:
4633*d56f51eaSDavid van Moolenbroek bpf_error("'clnp' modifier applied to %s", typestr);
4634*d56f51eaSDavid van Moolenbroek
4635*d56f51eaSDavid van Moolenbroek case Q_STP:
4636*d56f51eaSDavid van Moolenbroek bpf_error("'stp' modifier applied to %s", typestr);
4637*d56f51eaSDavid van Moolenbroek
4638*d56f51eaSDavid van Moolenbroek case Q_IPX:
4639*d56f51eaSDavid van Moolenbroek bpf_error("IPX host filtering not implemented");
4640*d56f51eaSDavid van Moolenbroek
4641*d56f51eaSDavid van Moolenbroek case Q_NETBEUI:
4642*d56f51eaSDavid van Moolenbroek bpf_error("'netbeui' modifier applied to %s", typestr);
4643*d56f51eaSDavid van Moolenbroek
4644*d56f51eaSDavid van Moolenbroek case Q_RADIO:
4645*d56f51eaSDavid van Moolenbroek bpf_error("'radio' modifier applied to %s", typestr);
4646*d56f51eaSDavid van Moolenbroek
4647*d56f51eaSDavid van Moolenbroek default:
4648*d56f51eaSDavid van Moolenbroek abort();
4649*d56f51eaSDavid van Moolenbroek }
4650*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
4651*d56f51eaSDavid van Moolenbroek }
4652*d56f51eaSDavid van Moolenbroek
4653*d56f51eaSDavid van Moolenbroek #ifdef INET6
4654*d56f51eaSDavid van Moolenbroek static struct block *
gen_host6(addr,mask,proto,dir,type)4655*d56f51eaSDavid van Moolenbroek gen_host6(addr, mask, proto, dir, type)
4656*d56f51eaSDavid van Moolenbroek struct in6_addr *addr;
4657*d56f51eaSDavid van Moolenbroek struct in6_addr *mask;
4658*d56f51eaSDavid van Moolenbroek int proto;
4659*d56f51eaSDavid van Moolenbroek int dir;
4660*d56f51eaSDavid van Moolenbroek int type;
4661*d56f51eaSDavid van Moolenbroek {
4662*d56f51eaSDavid van Moolenbroek const char *typestr;
4663*d56f51eaSDavid van Moolenbroek
4664*d56f51eaSDavid van Moolenbroek if (type == Q_NET)
4665*d56f51eaSDavid van Moolenbroek typestr = "net";
4666*d56f51eaSDavid van Moolenbroek else
4667*d56f51eaSDavid van Moolenbroek typestr = "host";
4668*d56f51eaSDavid van Moolenbroek
4669*d56f51eaSDavid van Moolenbroek switch (proto) {
4670*d56f51eaSDavid van Moolenbroek
4671*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
4672*d56f51eaSDavid van Moolenbroek return gen_host6(addr, mask, Q_IPV6, dir, type);
4673*d56f51eaSDavid van Moolenbroek
4674*d56f51eaSDavid van Moolenbroek case Q_LINK:
4675*d56f51eaSDavid van Moolenbroek bpf_error("link-layer modifier applied to ip6 %s", typestr);
4676*d56f51eaSDavid van Moolenbroek
4677*d56f51eaSDavid van Moolenbroek case Q_IP:
4678*d56f51eaSDavid van Moolenbroek bpf_error("'ip' modifier applied to ip6 %s", typestr);
4679*d56f51eaSDavid van Moolenbroek
4680*d56f51eaSDavid van Moolenbroek case Q_RARP:
4681*d56f51eaSDavid van Moolenbroek bpf_error("'rarp' modifier applied to ip6 %s", typestr);
4682*d56f51eaSDavid van Moolenbroek
4683*d56f51eaSDavid van Moolenbroek case Q_ARP:
4684*d56f51eaSDavid van Moolenbroek bpf_error("'arp' modifier applied to ip6 %s", typestr);
4685*d56f51eaSDavid van Moolenbroek
4686*d56f51eaSDavid van Moolenbroek case Q_SCTP:
4687*d56f51eaSDavid van Moolenbroek bpf_error("'sctp' modifier applied to %s", typestr);
4688*d56f51eaSDavid van Moolenbroek
4689*d56f51eaSDavid van Moolenbroek case Q_TCP:
4690*d56f51eaSDavid van Moolenbroek bpf_error("'tcp' modifier applied to %s", typestr);
4691*d56f51eaSDavid van Moolenbroek
4692*d56f51eaSDavid van Moolenbroek case Q_UDP:
4693*d56f51eaSDavid van Moolenbroek bpf_error("'udp' modifier applied to %s", typestr);
4694*d56f51eaSDavid van Moolenbroek
4695*d56f51eaSDavid van Moolenbroek case Q_ICMP:
4696*d56f51eaSDavid van Moolenbroek bpf_error("'icmp' modifier applied to %s", typestr);
4697*d56f51eaSDavid van Moolenbroek
4698*d56f51eaSDavid van Moolenbroek case Q_IGMP:
4699*d56f51eaSDavid van Moolenbroek bpf_error("'igmp' modifier applied to %s", typestr);
4700*d56f51eaSDavid van Moolenbroek
4701*d56f51eaSDavid van Moolenbroek case Q_IGRP:
4702*d56f51eaSDavid van Moolenbroek bpf_error("'igrp' modifier applied to %s", typestr);
4703*d56f51eaSDavid van Moolenbroek
4704*d56f51eaSDavid van Moolenbroek case Q_PIM:
4705*d56f51eaSDavid van Moolenbroek bpf_error("'pim' modifier applied to %s", typestr);
4706*d56f51eaSDavid van Moolenbroek
4707*d56f51eaSDavid van Moolenbroek case Q_VRRP:
4708*d56f51eaSDavid van Moolenbroek bpf_error("'vrrp' modifier applied to %s", typestr);
4709*d56f51eaSDavid van Moolenbroek
4710*d56f51eaSDavid van Moolenbroek case Q_CARP:
4711*d56f51eaSDavid van Moolenbroek bpf_error("'carp' modifier applied to %s", typestr);
4712*d56f51eaSDavid van Moolenbroek
4713*d56f51eaSDavid van Moolenbroek case Q_ATALK:
4714*d56f51eaSDavid van Moolenbroek bpf_error("ATALK host filtering not implemented");
4715*d56f51eaSDavid van Moolenbroek
4716*d56f51eaSDavid van Moolenbroek case Q_AARP:
4717*d56f51eaSDavid van Moolenbroek bpf_error("AARP host filtering not implemented");
4718*d56f51eaSDavid van Moolenbroek
4719*d56f51eaSDavid van Moolenbroek case Q_DECNET:
4720*d56f51eaSDavid van Moolenbroek bpf_error("'decnet' modifier applied to ip6 %s", typestr);
4721*d56f51eaSDavid van Moolenbroek
4722*d56f51eaSDavid van Moolenbroek case Q_SCA:
4723*d56f51eaSDavid van Moolenbroek bpf_error("SCA host filtering not implemented");
4724*d56f51eaSDavid van Moolenbroek
4725*d56f51eaSDavid van Moolenbroek case Q_LAT:
4726*d56f51eaSDavid van Moolenbroek bpf_error("LAT host filtering not implemented");
4727*d56f51eaSDavid van Moolenbroek
4728*d56f51eaSDavid van Moolenbroek case Q_MOPDL:
4729*d56f51eaSDavid van Moolenbroek bpf_error("MOPDL host filtering not implemented");
4730*d56f51eaSDavid van Moolenbroek
4731*d56f51eaSDavid van Moolenbroek case Q_MOPRC:
4732*d56f51eaSDavid van Moolenbroek bpf_error("MOPRC host filtering not implemented");
4733*d56f51eaSDavid van Moolenbroek
4734*d56f51eaSDavid van Moolenbroek case Q_IPV6:
4735*d56f51eaSDavid van Moolenbroek return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6, 8, 24);
4736*d56f51eaSDavid van Moolenbroek
4737*d56f51eaSDavid van Moolenbroek case Q_ICMPV6:
4738*d56f51eaSDavid van Moolenbroek bpf_error("'icmp6' modifier applied to %s", typestr);
4739*d56f51eaSDavid van Moolenbroek
4740*d56f51eaSDavid van Moolenbroek case Q_AH:
4741*d56f51eaSDavid van Moolenbroek bpf_error("'ah' modifier applied to %s", typestr);
4742*d56f51eaSDavid van Moolenbroek
4743*d56f51eaSDavid van Moolenbroek case Q_ESP:
4744*d56f51eaSDavid van Moolenbroek bpf_error("'esp' modifier applied to %s", typestr);
4745*d56f51eaSDavid van Moolenbroek
4746*d56f51eaSDavid van Moolenbroek case Q_ISO:
4747*d56f51eaSDavid van Moolenbroek bpf_error("ISO host filtering not implemented");
4748*d56f51eaSDavid van Moolenbroek
4749*d56f51eaSDavid van Moolenbroek case Q_ESIS:
4750*d56f51eaSDavid van Moolenbroek bpf_error("'esis' modifier applied to %s", typestr);
4751*d56f51eaSDavid van Moolenbroek
4752*d56f51eaSDavid van Moolenbroek case Q_ISIS:
4753*d56f51eaSDavid van Moolenbroek bpf_error("'isis' modifier applied to %s", typestr);
4754*d56f51eaSDavid van Moolenbroek
4755*d56f51eaSDavid van Moolenbroek case Q_CLNP:
4756*d56f51eaSDavid van Moolenbroek bpf_error("'clnp' modifier applied to %s", typestr);
4757*d56f51eaSDavid van Moolenbroek
4758*d56f51eaSDavid van Moolenbroek case Q_STP:
4759*d56f51eaSDavid van Moolenbroek bpf_error("'stp' modifier applied to %s", typestr);
4760*d56f51eaSDavid van Moolenbroek
4761*d56f51eaSDavid van Moolenbroek case Q_IPX:
4762*d56f51eaSDavid van Moolenbroek bpf_error("IPX host filtering not implemented");
4763*d56f51eaSDavid van Moolenbroek
4764*d56f51eaSDavid van Moolenbroek case Q_NETBEUI:
4765*d56f51eaSDavid van Moolenbroek bpf_error("'netbeui' modifier applied to %s", typestr);
4766*d56f51eaSDavid van Moolenbroek
4767*d56f51eaSDavid van Moolenbroek case Q_RADIO:
4768*d56f51eaSDavid van Moolenbroek bpf_error("'radio' modifier applied to %s", typestr);
4769*d56f51eaSDavid van Moolenbroek
4770*d56f51eaSDavid van Moolenbroek default:
4771*d56f51eaSDavid van Moolenbroek abort();
4772*d56f51eaSDavid van Moolenbroek }
4773*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
4774*d56f51eaSDavid van Moolenbroek }
4775*d56f51eaSDavid van Moolenbroek #endif
4776*d56f51eaSDavid van Moolenbroek
4777*d56f51eaSDavid van Moolenbroek #ifndef INET6
4778*d56f51eaSDavid van Moolenbroek static struct block *
gen_gateway(eaddr,alist,proto,dir)4779*d56f51eaSDavid van Moolenbroek gen_gateway(eaddr, alist, proto, dir)
4780*d56f51eaSDavid van Moolenbroek const u_char *eaddr;
4781*d56f51eaSDavid van Moolenbroek bpf_u_int32 **alist;
4782*d56f51eaSDavid van Moolenbroek int proto;
4783*d56f51eaSDavid van Moolenbroek int dir;
4784*d56f51eaSDavid van Moolenbroek {
4785*d56f51eaSDavid van Moolenbroek struct block *b0, *b1, *tmp;
4786*d56f51eaSDavid van Moolenbroek
4787*d56f51eaSDavid van Moolenbroek if (dir != 0)
4788*d56f51eaSDavid van Moolenbroek bpf_error("direction applied to 'gateway'");
4789*d56f51eaSDavid van Moolenbroek
4790*d56f51eaSDavid van Moolenbroek switch (proto) {
4791*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
4792*d56f51eaSDavid van Moolenbroek case Q_IP:
4793*d56f51eaSDavid van Moolenbroek case Q_ARP:
4794*d56f51eaSDavid van Moolenbroek case Q_RARP:
4795*d56f51eaSDavid van Moolenbroek switch (linktype) {
4796*d56f51eaSDavid van Moolenbroek case DLT_EN10MB:
4797*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER:
4798*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER_TRANSPARENT:
4799*d56f51eaSDavid van Moolenbroek b1 = gen_prevlinkhdr_check();
4800*d56f51eaSDavid van Moolenbroek b0 = gen_ehostop(eaddr, Q_OR);
4801*d56f51eaSDavid van Moolenbroek if (b1 != NULL)
4802*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
4803*d56f51eaSDavid van Moolenbroek break;
4804*d56f51eaSDavid van Moolenbroek case DLT_FDDI:
4805*d56f51eaSDavid van Moolenbroek b0 = gen_fhostop(eaddr, Q_OR);
4806*d56f51eaSDavid van Moolenbroek break;
4807*d56f51eaSDavid van Moolenbroek case DLT_IEEE802:
4808*d56f51eaSDavid van Moolenbroek b0 = gen_thostop(eaddr, Q_OR);
4809*d56f51eaSDavid van Moolenbroek break;
4810*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11:
4811*d56f51eaSDavid van Moolenbroek case DLT_PRISM_HEADER:
4812*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO_AVS:
4813*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO:
4814*d56f51eaSDavid van Moolenbroek case DLT_PPI:
4815*d56f51eaSDavid van Moolenbroek b0 = gen_wlanhostop(eaddr, Q_OR);
4816*d56f51eaSDavid van Moolenbroek break;
4817*d56f51eaSDavid van Moolenbroek case DLT_SUNATM:
4818*d56f51eaSDavid van Moolenbroek /*
4819*d56f51eaSDavid van Moolenbroek * This is LLC-multiplexed traffic; if it were
4820*d56f51eaSDavid van Moolenbroek * LANE, linktype would have been set to
4821*d56f51eaSDavid van Moolenbroek * DLT_EN10MB.
4822*d56f51eaSDavid van Moolenbroek */
4823*d56f51eaSDavid van Moolenbroek bpf_error(
4824*d56f51eaSDavid van Moolenbroek "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
4825*d56f51eaSDavid van Moolenbroek break;
4826*d56f51eaSDavid van Moolenbroek case DLT_IP_OVER_FC:
4827*d56f51eaSDavid van Moolenbroek b0 = gen_ipfchostop(eaddr, Q_OR);
4828*d56f51eaSDavid van Moolenbroek break;
4829*d56f51eaSDavid van Moolenbroek default:
4830*d56f51eaSDavid van Moolenbroek bpf_error(
4831*d56f51eaSDavid van Moolenbroek "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
4832*d56f51eaSDavid van Moolenbroek }
4833*d56f51eaSDavid van Moolenbroek b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST);
4834*d56f51eaSDavid van Moolenbroek while (*alist) {
4835*d56f51eaSDavid van Moolenbroek tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR,
4836*d56f51eaSDavid van Moolenbroek Q_HOST);
4837*d56f51eaSDavid van Moolenbroek gen_or(b1, tmp);
4838*d56f51eaSDavid van Moolenbroek b1 = tmp;
4839*d56f51eaSDavid van Moolenbroek }
4840*d56f51eaSDavid van Moolenbroek gen_not(b1);
4841*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
4842*d56f51eaSDavid van Moolenbroek return b1;
4843*d56f51eaSDavid van Moolenbroek }
4844*d56f51eaSDavid van Moolenbroek bpf_error("illegal modifier of 'gateway'");
4845*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
4846*d56f51eaSDavid van Moolenbroek }
4847*d56f51eaSDavid van Moolenbroek #endif
4848*d56f51eaSDavid van Moolenbroek
4849*d56f51eaSDavid van Moolenbroek struct block *
gen_proto_abbrev(proto)4850*d56f51eaSDavid van Moolenbroek gen_proto_abbrev(proto)
4851*d56f51eaSDavid van Moolenbroek int proto;
4852*d56f51eaSDavid van Moolenbroek {
4853*d56f51eaSDavid van Moolenbroek struct block *b0;
4854*d56f51eaSDavid van Moolenbroek struct block *b1;
4855*d56f51eaSDavid van Moolenbroek
4856*d56f51eaSDavid van Moolenbroek switch (proto) {
4857*d56f51eaSDavid van Moolenbroek
4858*d56f51eaSDavid van Moolenbroek case Q_SCTP:
4859*d56f51eaSDavid van Moolenbroek b1 = gen_proto(IPPROTO_SCTP, Q_IP, Q_DEFAULT);
4860*d56f51eaSDavid van Moolenbroek b0 = gen_proto(IPPROTO_SCTP, Q_IPV6, Q_DEFAULT);
4861*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
4862*d56f51eaSDavid van Moolenbroek break;
4863*d56f51eaSDavid van Moolenbroek
4864*d56f51eaSDavid van Moolenbroek case Q_TCP:
4865*d56f51eaSDavid van Moolenbroek b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT);
4866*d56f51eaSDavid van Moolenbroek b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
4867*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
4868*d56f51eaSDavid van Moolenbroek break;
4869*d56f51eaSDavid van Moolenbroek
4870*d56f51eaSDavid van Moolenbroek case Q_UDP:
4871*d56f51eaSDavid van Moolenbroek b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT);
4872*d56f51eaSDavid van Moolenbroek b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
4873*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
4874*d56f51eaSDavid van Moolenbroek break;
4875*d56f51eaSDavid van Moolenbroek
4876*d56f51eaSDavid van Moolenbroek case Q_ICMP:
4877*d56f51eaSDavid van Moolenbroek b1 = gen_proto(IPPROTO_ICMP, Q_IP, Q_DEFAULT);
4878*d56f51eaSDavid van Moolenbroek break;
4879*d56f51eaSDavid van Moolenbroek
4880*d56f51eaSDavid van Moolenbroek #ifndef IPPROTO_IGMP
4881*d56f51eaSDavid van Moolenbroek #define IPPROTO_IGMP 2
4882*d56f51eaSDavid van Moolenbroek #endif
4883*d56f51eaSDavid van Moolenbroek
4884*d56f51eaSDavid van Moolenbroek case Q_IGMP:
4885*d56f51eaSDavid van Moolenbroek b1 = gen_proto(IPPROTO_IGMP, Q_IP, Q_DEFAULT);
4886*d56f51eaSDavid van Moolenbroek break;
4887*d56f51eaSDavid van Moolenbroek
4888*d56f51eaSDavid van Moolenbroek #ifndef IPPROTO_IGRP
4889*d56f51eaSDavid van Moolenbroek #define IPPROTO_IGRP 9
4890*d56f51eaSDavid van Moolenbroek #endif
4891*d56f51eaSDavid van Moolenbroek case Q_IGRP:
4892*d56f51eaSDavid van Moolenbroek b1 = gen_proto(IPPROTO_IGRP, Q_IP, Q_DEFAULT);
4893*d56f51eaSDavid van Moolenbroek break;
4894*d56f51eaSDavid van Moolenbroek
4895*d56f51eaSDavid van Moolenbroek #ifndef IPPROTO_PIM
4896*d56f51eaSDavid van Moolenbroek #define IPPROTO_PIM 103
4897*d56f51eaSDavid van Moolenbroek #endif
4898*d56f51eaSDavid van Moolenbroek
4899*d56f51eaSDavid van Moolenbroek case Q_PIM:
4900*d56f51eaSDavid van Moolenbroek b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT);
4901*d56f51eaSDavid van Moolenbroek b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
4902*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
4903*d56f51eaSDavid van Moolenbroek break;
4904*d56f51eaSDavid van Moolenbroek
4905*d56f51eaSDavid van Moolenbroek #ifndef IPPROTO_VRRP
4906*d56f51eaSDavid van Moolenbroek #define IPPROTO_VRRP 112
4907*d56f51eaSDavid van Moolenbroek #endif
4908*d56f51eaSDavid van Moolenbroek
4909*d56f51eaSDavid van Moolenbroek case Q_VRRP:
4910*d56f51eaSDavid van Moolenbroek b1 = gen_proto(IPPROTO_VRRP, Q_IP, Q_DEFAULT);
4911*d56f51eaSDavid van Moolenbroek break;
4912*d56f51eaSDavid van Moolenbroek
4913*d56f51eaSDavid van Moolenbroek #ifndef IPPROTO_CARP
4914*d56f51eaSDavid van Moolenbroek #define IPPROTO_CARP 112
4915*d56f51eaSDavid van Moolenbroek #endif
4916*d56f51eaSDavid van Moolenbroek
4917*d56f51eaSDavid van Moolenbroek case Q_CARP:
4918*d56f51eaSDavid van Moolenbroek b1 = gen_proto(IPPROTO_CARP, Q_IP, Q_DEFAULT);
4919*d56f51eaSDavid van Moolenbroek break;
4920*d56f51eaSDavid van Moolenbroek
4921*d56f51eaSDavid van Moolenbroek case Q_IP:
4922*d56f51eaSDavid van Moolenbroek b1 = gen_linktype(ETHERTYPE_IP);
4923*d56f51eaSDavid van Moolenbroek break;
4924*d56f51eaSDavid van Moolenbroek
4925*d56f51eaSDavid van Moolenbroek case Q_ARP:
4926*d56f51eaSDavid van Moolenbroek b1 = gen_linktype(ETHERTYPE_ARP);
4927*d56f51eaSDavid van Moolenbroek break;
4928*d56f51eaSDavid van Moolenbroek
4929*d56f51eaSDavid van Moolenbroek case Q_RARP:
4930*d56f51eaSDavid van Moolenbroek b1 = gen_linktype(ETHERTYPE_REVARP);
4931*d56f51eaSDavid van Moolenbroek break;
4932*d56f51eaSDavid van Moolenbroek
4933*d56f51eaSDavid van Moolenbroek case Q_LINK:
4934*d56f51eaSDavid van Moolenbroek bpf_error("link layer applied in wrong context");
4935*d56f51eaSDavid van Moolenbroek
4936*d56f51eaSDavid van Moolenbroek case Q_ATALK:
4937*d56f51eaSDavid van Moolenbroek b1 = gen_linktype(ETHERTYPE_ATALK);
4938*d56f51eaSDavid van Moolenbroek break;
4939*d56f51eaSDavid van Moolenbroek
4940*d56f51eaSDavid van Moolenbroek case Q_AARP:
4941*d56f51eaSDavid van Moolenbroek b1 = gen_linktype(ETHERTYPE_AARP);
4942*d56f51eaSDavid van Moolenbroek break;
4943*d56f51eaSDavid van Moolenbroek
4944*d56f51eaSDavid van Moolenbroek case Q_DECNET:
4945*d56f51eaSDavid van Moolenbroek b1 = gen_linktype(ETHERTYPE_DN);
4946*d56f51eaSDavid van Moolenbroek break;
4947*d56f51eaSDavid van Moolenbroek
4948*d56f51eaSDavid van Moolenbroek case Q_SCA:
4949*d56f51eaSDavid van Moolenbroek b1 = gen_linktype(ETHERTYPE_SCA);
4950*d56f51eaSDavid van Moolenbroek break;
4951*d56f51eaSDavid van Moolenbroek
4952*d56f51eaSDavid van Moolenbroek case Q_LAT:
4953*d56f51eaSDavid van Moolenbroek b1 = gen_linktype(ETHERTYPE_LAT);
4954*d56f51eaSDavid van Moolenbroek break;
4955*d56f51eaSDavid van Moolenbroek
4956*d56f51eaSDavid van Moolenbroek case Q_MOPDL:
4957*d56f51eaSDavid van Moolenbroek b1 = gen_linktype(ETHERTYPE_MOPDL);
4958*d56f51eaSDavid van Moolenbroek break;
4959*d56f51eaSDavid van Moolenbroek
4960*d56f51eaSDavid van Moolenbroek case Q_MOPRC:
4961*d56f51eaSDavid van Moolenbroek b1 = gen_linktype(ETHERTYPE_MOPRC);
4962*d56f51eaSDavid van Moolenbroek break;
4963*d56f51eaSDavid van Moolenbroek
4964*d56f51eaSDavid van Moolenbroek case Q_IPV6:
4965*d56f51eaSDavid van Moolenbroek b1 = gen_linktype(ETHERTYPE_IPV6);
4966*d56f51eaSDavid van Moolenbroek break;
4967*d56f51eaSDavid van Moolenbroek
4968*d56f51eaSDavid van Moolenbroek #ifndef IPPROTO_ICMPV6
4969*d56f51eaSDavid van Moolenbroek #define IPPROTO_ICMPV6 58
4970*d56f51eaSDavid van Moolenbroek #endif
4971*d56f51eaSDavid van Moolenbroek case Q_ICMPV6:
4972*d56f51eaSDavid van Moolenbroek b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT);
4973*d56f51eaSDavid van Moolenbroek break;
4974*d56f51eaSDavid van Moolenbroek
4975*d56f51eaSDavid van Moolenbroek #ifndef IPPROTO_AH
4976*d56f51eaSDavid van Moolenbroek #define IPPROTO_AH 51
4977*d56f51eaSDavid van Moolenbroek #endif
4978*d56f51eaSDavid van Moolenbroek case Q_AH:
4979*d56f51eaSDavid van Moolenbroek b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT);
4980*d56f51eaSDavid van Moolenbroek b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT);
4981*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
4982*d56f51eaSDavid van Moolenbroek break;
4983*d56f51eaSDavid van Moolenbroek
4984*d56f51eaSDavid van Moolenbroek #ifndef IPPROTO_ESP
4985*d56f51eaSDavid van Moolenbroek #define IPPROTO_ESP 50
4986*d56f51eaSDavid van Moolenbroek #endif
4987*d56f51eaSDavid van Moolenbroek case Q_ESP:
4988*d56f51eaSDavid van Moolenbroek b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT);
4989*d56f51eaSDavid van Moolenbroek b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
4990*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
4991*d56f51eaSDavid van Moolenbroek break;
4992*d56f51eaSDavid van Moolenbroek
4993*d56f51eaSDavid van Moolenbroek case Q_ISO:
4994*d56f51eaSDavid van Moolenbroek b1 = gen_linktype(LLCSAP_ISONS);
4995*d56f51eaSDavid van Moolenbroek break;
4996*d56f51eaSDavid van Moolenbroek
4997*d56f51eaSDavid van Moolenbroek case Q_ESIS:
4998*d56f51eaSDavid van Moolenbroek b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT);
4999*d56f51eaSDavid van Moolenbroek break;
5000*d56f51eaSDavid van Moolenbroek
5001*d56f51eaSDavid van Moolenbroek case Q_ISIS:
5002*d56f51eaSDavid van Moolenbroek b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
5003*d56f51eaSDavid van Moolenbroek break;
5004*d56f51eaSDavid van Moolenbroek
5005*d56f51eaSDavid van Moolenbroek case Q_ISIS_L1: /* all IS-IS Level1 PDU-Types */
5006*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
5007*d56f51eaSDavid van Moolenbroek b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
5008*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5009*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
5010*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5011*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
5012*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5013*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
5014*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5015*d56f51eaSDavid van Moolenbroek break;
5016*d56f51eaSDavid van Moolenbroek
5017*d56f51eaSDavid van Moolenbroek case Q_ISIS_L2: /* all IS-IS Level2 PDU-Types */
5018*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
5019*d56f51eaSDavid van Moolenbroek b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
5020*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5021*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
5022*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5023*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
5024*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5025*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
5026*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5027*d56f51eaSDavid van Moolenbroek break;
5028*d56f51eaSDavid van Moolenbroek
5029*d56f51eaSDavid van Moolenbroek case Q_ISIS_IIH: /* all IS-IS Hello PDU-Types */
5030*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
5031*d56f51eaSDavid van Moolenbroek b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
5032*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5033*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);
5034*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5035*d56f51eaSDavid van Moolenbroek break;
5036*d56f51eaSDavid van Moolenbroek
5037*d56f51eaSDavid van Moolenbroek case Q_ISIS_LSP:
5038*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
5039*d56f51eaSDavid van Moolenbroek b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
5040*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5041*d56f51eaSDavid van Moolenbroek break;
5042*d56f51eaSDavid van Moolenbroek
5043*d56f51eaSDavid van Moolenbroek case Q_ISIS_SNP:
5044*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
5045*d56f51eaSDavid van Moolenbroek b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
5046*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5047*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
5048*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5049*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
5050*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5051*d56f51eaSDavid van Moolenbroek break;
5052*d56f51eaSDavid van Moolenbroek
5053*d56f51eaSDavid van Moolenbroek case Q_ISIS_CSNP:
5054*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
5055*d56f51eaSDavid van Moolenbroek b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
5056*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5057*d56f51eaSDavid van Moolenbroek break;
5058*d56f51eaSDavid van Moolenbroek
5059*d56f51eaSDavid van Moolenbroek case Q_ISIS_PSNP:
5060*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
5061*d56f51eaSDavid van Moolenbroek b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
5062*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5063*d56f51eaSDavid van Moolenbroek break;
5064*d56f51eaSDavid van Moolenbroek
5065*d56f51eaSDavid van Moolenbroek case Q_CLNP:
5066*d56f51eaSDavid van Moolenbroek b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT);
5067*d56f51eaSDavid van Moolenbroek break;
5068*d56f51eaSDavid van Moolenbroek
5069*d56f51eaSDavid van Moolenbroek case Q_STP:
5070*d56f51eaSDavid van Moolenbroek b1 = gen_linktype(LLCSAP_8021D);
5071*d56f51eaSDavid van Moolenbroek break;
5072*d56f51eaSDavid van Moolenbroek
5073*d56f51eaSDavid van Moolenbroek case Q_IPX:
5074*d56f51eaSDavid van Moolenbroek b1 = gen_linktype(LLCSAP_IPX);
5075*d56f51eaSDavid van Moolenbroek break;
5076*d56f51eaSDavid van Moolenbroek
5077*d56f51eaSDavid van Moolenbroek case Q_NETBEUI:
5078*d56f51eaSDavid van Moolenbroek b1 = gen_linktype(LLCSAP_NETBEUI);
5079*d56f51eaSDavid van Moolenbroek break;
5080*d56f51eaSDavid van Moolenbroek
5081*d56f51eaSDavid van Moolenbroek case Q_RADIO:
5082*d56f51eaSDavid van Moolenbroek bpf_error("'radio' is not a valid protocol type");
5083*d56f51eaSDavid van Moolenbroek
5084*d56f51eaSDavid van Moolenbroek default:
5085*d56f51eaSDavid van Moolenbroek abort();
5086*d56f51eaSDavid van Moolenbroek }
5087*d56f51eaSDavid van Moolenbroek return b1;
5088*d56f51eaSDavid van Moolenbroek }
5089*d56f51eaSDavid van Moolenbroek
5090*d56f51eaSDavid van Moolenbroek static struct block *
gen_ipfrag()5091*d56f51eaSDavid van Moolenbroek gen_ipfrag()
5092*d56f51eaSDavid van Moolenbroek {
5093*d56f51eaSDavid van Moolenbroek struct slist *s;
5094*d56f51eaSDavid van Moolenbroek struct block *b;
5095*d56f51eaSDavid van Moolenbroek
5096*d56f51eaSDavid van Moolenbroek /* not IPv4 frag other than the first frag */
5097*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKPL, 6, BPF_H);
5098*d56f51eaSDavid van Moolenbroek b = new_block(JMP(BPF_JSET));
5099*d56f51eaSDavid van Moolenbroek b->s.k = 0x1fff;
5100*d56f51eaSDavid van Moolenbroek b->stmts = s;
5101*d56f51eaSDavid van Moolenbroek gen_not(b);
5102*d56f51eaSDavid van Moolenbroek
5103*d56f51eaSDavid van Moolenbroek return b;
5104*d56f51eaSDavid van Moolenbroek }
5105*d56f51eaSDavid van Moolenbroek
5106*d56f51eaSDavid van Moolenbroek /*
5107*d56f51eaSDavid van Moolenbroek * Generate a comparison to a port value in the transport-layer header
5108*d56f51eaSDavid van Moolenbroek * at the specified offset from the beginning of that header.
5109*d56f51eaSDavid van Moolenbroek *
5110*d56f51eaSDavid van Moolenbroek * XXX - this handles a variable-length prefix preceding the link-layer
5111*d56f51eaSDavid van Moolenbroek * header, such as the radiotap or AVS radio prefix, but doesn't handle
5112*d56f51eaSDavid van Moolenbroek * variable-length link-layer headers (such as Token Ring or 802.11
5113*d56f51eaSDavid van Moolenbroek * headers).
5114*d56f51eaSDavid van Moolenbroek */
5115*d56f51eaSDavid van Moolenbroek static struct block *
gen_portatom(off,v)5116*d56f51eaSDavid van Moolenbroek gen_portatom(off, v)
5117*d56f51eaSDavid van Moolenbroek int off;
5118*d56f51eaSDavid van Moolenbroek bpf_int32 v;
5119*d56f51eaSDavid van Moolenbroek {
5120*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_TRAN_IPV4, off, BPF_H, v);
5121*d56f51eaSDavid van Moolenbroek }
5122*d56f51eaSDavid van Moolenbroek
5123*d56f51eaSDavid van Moolenbroek static struct block *
gen_portatom6(off,v)5124*d56f51eaSDavid van Moolenbroek gen_portatom6(off, v)
5125*d56f51eaSDavid van Moolenbroek int off;
5126*d56f51eaSDavid van Moolenbroek bpf_int32 v;
5127*d56f51eaSDavid van Moolenbroek {
5128*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_TRAN_IPV6, off, BPF_H, v);
5129*d56f51eaSDavid van Moolenbroek }
5130*d56f51eaSDavid van Moolenbroek
5131*d56f51eaSDavid van Moolenbroek struct block *
gen_portop(port,proto,dir)5132*d56f51eaSDavid van Moolenbroek gen_portop(port, proto, dir)
5133*d56f51eaSDavid van Moolenbroek int port, proto, dir;
5134*d56f51eaSDavid van Moolenbroek {
5135*d56f51eaSDavid van Moolenbroek struct block *b0, *b1, *tmp;
5136*d56f51eaSDavid van Moolenbroek
5137*d56f51eaSDavid van Moolenbroek /* ip proto 'proto' and not a fragment other than the first fragment */
5138*d56f51eaSDavid van Moolenbroek tmp = gen_cmp(OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
5139*d56f51eaSDavid van Moolenbroek b0 = gen_ipfrag();
5140*d56f51eaSDavid van Moolenbroek gen_and(tmp, b0);
5141*d56f51eaSDavid van Moolenbroek
5142*d56f51eaSDavid van Moolenbroek switch (dir) {
5143*d56f51eaSDavid van Moolenbroek case Q_SRC:
5144*d56f51eaSDavid van Moolenbroek b1 = gen_portatom(0, (bpf_int32)port);
5145*d56f51eaSDavid van Moolenbroek break;
5146*d56f51eaSDavid van Moolenbroek
5147*d56f51eaSDavid van Moolenbroek case Q_DST:
5148*d56f51eaSDavid van Moolenbroek b1 = gen_portatom(2, (bpf_int32)port);
5149*d56f51eaSDavid van Moolenbroek break;
5150*d56f51eaSDavid van Moolenbroek
5151*d56f51eaSDavid van Moolenbroek case Q_OR:
5152*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
5153*d56f51eaSDavid van Moolenbroek tmp = gen_portatom(0, (bpf_int32)port);
5154*d56f51eaSDavid van Moolenbroek b1 = gen_portatom(2, (bpf_int32)port);
5155*d56f51eaSDavid van Moolenbroek gen_or(tmp, b1);
5156*d56f51eaSDavid van Moolenbroek break;
5157*d56f51eaSDavid van Moolenbroek
5158*d56f51eaSDavid van Moolenbroek case Q_AND:
5159*d56f51eaSDavid van Moolenbroek tmp = gen_portatom(0, (bpf_int32)port);
5160*d56f51eaSDavid van Moolenbroek b1 = gen_portatom(2, (bpf_int32)port);
5161*d56f51eaSDavid van Moolenbroek gen_and(tmp, b1);
5162*d56f51eaSDavid van Moolenbroek break;
5163*d56f51eaSDavid van Moolenbroek
5164*d56f51eaSDavid van Moolenbroek default:
5165*d56f51eaSDavid van Moolenbroek abort();
5166*d56f51eaSDavid van Moolenbroek }
5167*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
5168*d56f51eaSDavid van Moolenbroek
5169*d56f51eaSDavid van Moolenbroek return b1;
5170*d56f51eaSDavid van Moolenbroek }
5171*d56f51eaSDavid van Moolenbroek
5172*d56f51eaSDavid van Moolenbroek static struct block *
gen_port(port,ip_proto,dir)5173*d56f51eaSDavid van Moolenbroek gen_port(port, ip_proto, dir)
5174*d56f51eaSDavid van Moolenbroek int port;
5175*d56f51eaSDavid van Moolenbroek int ip_proto;
5176*d56f51eaSDavid van Moolenbroek int dir;
5177*d56f51eaSDavid van Moolenbroek {
5178*d56f51eaSDavid van Moolenbroek struct block *b0, *b1, *tmp;
5179*d56f51eaSDavid van Moolenbroek
5180*d56f51eaSDavid van Moolenbroek /*
5181*d56f51eaSDavid van Moolenbroek * ether proto ip
5182*d56f51eaSDavid van Moolenbroek *
5183*d56f51eaSDavid van Moolenbroek * For FDDI, RFC 1188 says that SNAP encapsulation is used,
5184*d56f51eaSDavid van Moolenbroek * not LLC encapsulation with LLCSAP_IP.
5185*d56f51eaSDavid van Moolenbroek *
5186*d56f51eaSDavid van Moolenbroek * For IEEE 802 networks - which includes 802.5 token ring
5187*d56f51eaSDavid van Moolenbroek * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042
5188*d56f51eaSDavid van Moolenbroek * says that SNAP encapsulation is used, not LLC encapsulation
5189*d56f51eaSDavid van Moolenbroek * with LLCSAP_IP.
5190*d56f51eaSDavid van Moolenbroek *
5191*d56f51eaSDavid van Moolenbroek * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and
5192*d56f51eaSDavid van Moolenbroek * RFC 2225 say that SNAP encapsulation is used, not LLC
5193*d56f51eaSDavid van Moolenbroek * encapsulation with LLCSAP_IP.
5194*d56f51eaSDavid van Moolenbroek *
5195*d56f51eaSDavid van Moolenbroek * So we always check for ETHERTYPE_IP.
5196*d56f51eaSDavid van Moolenbroek */
5197*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(ETHERTYPE_IP);
5198*d56f51eaSDavid van Moolenbroek
5199*d56f51eaSDavid van Moolenbroek switch (ip_proto) {
5200*d56f51eaSDavid van Moolenbroek case IPPROTO_UDP:
5201*d56f51eaSDavid van Moolenbroek case IPPROTO_TCP:
5202*d56f51eaSDavid van Moolenbroek case IPPROTO_SCTP:
5203*d56f51eaSDavid van Moolenbroek b1 = gen_portop(port, ip_proto, dir);
5204*d56f51eaSDavid van Moolenbroek break;
5205*d56f51eaSDavid van Moolenbroek
5206*d56f51eaSDavid van Moolenbroek case PROTO_UNDEF:
5207*d56f51eaSDavid van Moolenbroek tmp = gen_portop(port, IPPROTO_TCP, dir);
5208*d56f51eaSDavid van Moolenbroek b1 = gen_portop(port, IPPROTO_UDP, dir);
5209*d56f51eaSDavid van Moolenbroek gen_or(tmp, b1);
5210*d56f51eaSDavid van Moolenbroek tmp = gen_portop(port, IPPROTO_SCTP, dir);
5211*d56f51eaSDavid van Moolenbroek gen_or(tmp, b1);
5212*d56f51eaSDavid van Moolenbroek break;
5213*d56f51eaSDavid van Moolenbroek
5214*d56f51eaSDavid van Moolenbroek default:
5215*d56f51eaSDavid van Moolenbroek abort();
5216*d56f51eaSDavid van Moolenbroek }
5217*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
5218*d56f51eaSDavid van Moolenbroek return b1;
5219*d56f51eaSDavid van Moolenbroek }
5220*d56f51eaSDavid van Moolenbroek
5221*d56f51eaSDavid van Moolenbroek struct block *
gen_portop6(port,proto,dir)5222*d56f51eaSDavid van Moolenbroek gen_portop6(port, proto, dir)
5223*d56f51eaSDavid van Moolenbroek int port, proto, dir;
5224*d56f51eaSDavid van Moolenbroek {
5225*d56f51eaSDavid van Moolenbroek struct block *b0, *b1, *tmp;
5226*d56f51eaSDavid van Moolenbroek
5227*d56f51eaSDavid van Moolenbroek /* ip6 proto 'proto' */
5228*d56f51eaSDavid van Moolenbroek /* XXX - catch the first fragment of a fragmented packet? */
5229*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
5230*d56f51eaSDavid van Moolenbroek
5231*d56f51eaSDavid van Moolenbroek switch (dir) {
5232*d56f51eaSDavid van Moolenbroek case Q_SRC:
5233*d56f51eaSDavid van Moolenbroek b1 = gen_portatom6(0, (bpf_int32)port);
5234*d56f51eaSDavid van Moolenbroek break;
5235*d56f51eaSDavid van Moolenbroek
5236*d56f51eaSDavid van Moolenbroek case Q_DST:
5237*d56f51eaSDavid van Moolenbroek b1 = gen_portatom6(2, (bpf_int32)port);
5238*d56f51eaSDavid van Moolenbroek break;
5239*d56f51eaSDavid van Moolenbroek
5240*d56f51eaSDavid van Moolenbroek case Q_OR:
5241*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
5242*d56f51eaSDavid van Moolenbroek tmp = gen_portatom6(0, (bpf_int32)port);
5243*d56f51eaSDavid van Moolenbroek b1 = gen_portatom6(2, (bpf_int32)port);
5244*d56f51eaSDavid van Moolenbroek gen_or(tmp, b1);
5245*d56f51eaSDavid van Moolenbroek break;
5246*d56f51eaSDavid van Moolenbroek
5247*d56f51eaSDavid van Moolenbroek case Q_AND:
5248*d56f51eaSDavid van Moolenbroek tmp = gen_portatom6(0, (bpf_int32)port);
5249*d56f51eaSDavid van Moolenbroek b1 = gen_portatom6(2, (bpf_int32)port);
5250*d56f51eaSDavid van Moolenbroek gen_and(tmp, b1);
5251*d56f51eaSDavid van Moolenbroek break;
5252*d56f51eaSDavid van Moolenbroek
5253*d56f51eaSDavid van Moolenbroek default:
5254*d56f51eaSDavid van Moolenbroek abort();
5255*d56f51eaSDavid van Moolenbroek }
5256*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
5257*d56f51eaSDavid van Moolenbroek
5258*d56f51eaSDavid van Moolenbroek return b1;
5259*d56f51eaSDavid van Moolenbroek }
5260*d56f51eaSDavid van Moolenbroek
5261*d56f51eaSDavid van Moolenbroek static struct block *
gen_port6(port,ip_proto,dir)5262*d56f51eaSDavid van Moolenbroek gen_port6(port, ip_proto, dir)
5263*d56f51eaSDavid van Moolenbroek int port;
5264*d56f51eaSDavid van Moolenbroek int ip_proto;
5265*d56f51eaSDavid van Moolenbroek int dir;
5266*d56f51eaSDavid van Moolenbroek {
5267*d56f51eaSDavid van Moolenbroek struct block *b0, *b1, *tmp;
5268*d56f51eaSDavid van Moolenbroek
5269*d56f51eaSDavid van Moolenbroek /* link proto ip6 */
5270*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(ETHERTYPE_IPV6);
5271*d56f51eaSDavid van Moolenbroek
5272*d56f51eaSDavid van Moolenbroek switch (ip_proto) {
5273*d56f51eaSDavid van Moolenbroek case IPPROTO_UDP:
5274*d56f51eaSDavid van Moolenbroek case IPPROTO_TCP:
5275*d56f51eaSDavid van Moolenbroek case IPPROTO_SCTP:
5276*d56f51eaSDavid van Moolenbroek b1 = gen_portop6(port, ip_proto, dir);
5277*d56f51eaSDavid van Moolenbroek break;
5278*d56f51eaSDavid van Moolenbroek
5279*d56f51eaSDavid van Moolenbroek case PROTO_UNDEF:
5280*d56f51eaSDavid van Moolenbroek tmp = gen_portop6(port, IPPROTO_TCP, dir);
5281*d56f51eaSDavid van Moolenbroek b1 = gen_portop6(port, IPPROTO_UDP, dir);
5282*d56f51eaSDavid van Moolenbroek gen_or(tmp, b1);
5283*d56f51eaSDavid van Moolenbroek tmp = gen_portop6(port, IPPROTO_SCTP, dir);
5284*d56f51eaSDavid van Moolenbroek gen_or(tmp, b1);
5285*d56f51eaSDavid van Moolenbroek break;
5286*d56f51eaSDavid van Moolenbroek
5287*d56f51eaSDavid van Moolenbroek default:
5288*d56f51eaSDavid van Moolenbroek abort();
5289*d56f51eaSDavid van Moolenbroek }
5290*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
5291*d56f51eaSDavid van Moolenbroek return b1;
5292*d56f51eaSDavid van Moolenbroek }
5293*d56f51eaSDavid van Moolenbroek
5294*d56f51eaSDavid van Moolenbroek /* gen_portrange code */
5295*d56f51eaSDavid van Moolenbroek static struct block *
gen_portrangeatom(off,v1,v2)5296*d56f51eaSDavid van Moolenbroek gen_portrangeatom(off, v1, v2)
5297*d56f51eaSDavid van Moolenbroek int off;
5298*d56f51eaSDavid van Moolenbroek bpf_int32 v1, v2;
5299*d56f51eaSDavid van Moolenbroek {
5300*d56f51eaSDavid van Moolenbroek struct block *b1, *b2;
5301*d56f51eaSDavid van Moolenbroek
5302*d56f51eaSDavid van Moolenbroek if (v1 > v2) {
5303*d56f51eaSDavid van Moolenbroek /*
5304*d56f51eaSDavid van Moolenbroek * Reverse the order of the ports, so v1 is the lower one.
5305*d56f51eaSDavid van Moolenbroek */
5306*d56f51eaSDavid van Moolenbroek bpf_int32 vtemp;
5307*d56f51eaSDavid van Moolenbroek
5308*d56f51eaSDavid van Moolenbroek vtemp = v1;
5309*d56f51eaSDavid van Moolenbroek v1 = v2;
5310*d56f51eaSDavid van Moolenbroek v2 = vtemp;
5311*d56f51eaSDavid van Moolenbroek }
5312*d56f51eaSDavid van Moolenbroek
5313*d56f51eaSDavid van Moolenbroek b1 = gen_cmp_ge(OR_TRAN_IPV4, off, BPF_H, v1);
5314*d56f51eaSDavid van Moolenbroek b2 = gen_cmp_le(OR_TRAN_IPV4, off, BPF_H, v2);
5315*d56f51eaSDavid van Moolenbroek
5316*d56f51eaSDavid van Moolenbroek gen_and(b1, b2);
5317*d56f51eaSDavid van Moolenbroek
5318*d56f51eaSDavid van Moolenbroek return b2;
5319*d56f51eaSDavid van Moolenbroek }
5320*d56f51eaSDavid van Moolenbroek
5321*d56f51eaSDavid van Moolenbroek struct block *
gen_portrangeop(port1,port2,proto,dir)5322*d56f51eaSDavid van Moolenbroek gen_portrangeop(port1, port2, proto, dir)
5323*d56f51eaSDavid van Moolenbroek int port1, port2;
5324*d56f51eaSDavid van Moolenbroek int proto;
5325*d56f51eaSDavid van Moolenbroek int dir;
5326*d56f51eaSDavid van Moolenbroek {
5327*d56f51eaSDavid van Moolenbroek struct block *b0, *b1, *tmp;
5328*d56f51eaSDavid van Moolenbroek
5329*d56f51eaSDavid van Moolenbroek /* ip proto 'proto' and not a fragment other than the first fragment */
5330*d56f51eaSDavid van Moolenbroek tmp = gen_cmp(OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
5331*d56f51eaSDavid van Moolenbroek b0 = gen_ipfrag();
5332*d56f51eaSDavid van Moolenbroek gen_and(tmp, b0);
5333*d56f51eaSDavid van Moolenbroek
5334*d56f51eaSDavid van Moolenbroek switch (dir) {
5335*d56f51eaSDavid van Moolenbroek case Q_SRC:
5336*d56f51eaSDavid van Moolenbroek b1 = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
5337*d56f51eaSDavid van Moolenbroek break;
5338*d56f51eaSDavid van Moolenbroek
5339*d56f51eaSDavid van Moolenbroek case Q_DST:
5340*d56f51eaSDavid van Moolenbroek b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
5341*d56f51eaSDavid van Moolenbroek break;
5342*d56f51eaSDavid van Moolenbroek
5343*d56f51eaSDavid van Moolenbroek case Q_OR:
5344*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
5345*d56f51eaSDavid van Moolenbroek tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
5346*d56f51eaSDavid van Moolenbroek b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
5347*d56f51eaSDavid van Moolenbroek gen_or(tmp, b1);
5348*d56f51eaSDavid van Moolenbroek break;
5349*d56f51eaSDavid van Moolenbroek
5350*d56f51eaSDavid van Moolenbroek case Q_AND:
5351*d56f51eaSDavid van Moolenbroek tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
5352*d56f51eaSDavid van Moolenbroek b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
5353*d56f51eaSDavid van Moolenbroek gen_and(tmp, b1);
5354*d56f51eaSDavid van Moolenbroek break;
5355*d56f51eaSDavid van Moolenbroek
5356*d56f51eaSDavid van Moolenbroek default:
5357*d56f51eaSDavid van Moolenbroek abort();
5358*d56f51eaSDavid van Moolenbroek }
5359*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
5360*d56f51eaSDavid van Moolenbroek
5361*d56f51eaSDavid van Moolenbroek return b1;
5362*d56f51eaSDavid van Moolenbroek }
5363*d56f51eaSDavid van Moolenbroek
5364*d56f51eaSDavid van Moolenbroek static struct block *
gen_portrange(port1,port2,ip_proto,dir)5365*d56f51eaSDavid van Moolenbroek gen_portrange(port1, port2, ip_proto, dir)
5366*d56f51eaSDavid van Moolenbroek int port1, port2;
5367*d56f51eaSDavid van Moolenbroek int ip_proto;
5368*d56f51eaSDavid van Moolenbroek int dir;
5369*d56f51eaSDavid van Moolenbroek {
5370*d56f51eaSDavid van Moolenbroek struct block *b0, *b1, *tmp;
5371*d56f51eaSDavid van Moolenbroek
5372*d56f51eaSDavid van Moolenbroek /* link proto ip */
5373*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(ETHERTYPE_IP);
5374*d56f51eaSDavid van Moolenbroek
5375*d56f51eaSDavid van Moolenbroek switch (ip_proto) {
5376*d56f51eaSDavid van Moolenbroek case IPPROTO_UDP:
5377*d56f51eaSDavid van Moolenbroek case IPPROTO_TCP:
5378*d56f51eaSDavid van Moolenbroek case IPPROTO_SCTP:
5379*d56f51eaSDavid van Moolenbroek b1 = gen_portrangeop(port1, port2, ip_proto, dir);
5380*d56f51eaSDavid van Moolenbroek break;
5381*d56f51eaSDavid van Moolenbroek
5382*d56f51eaSDavid van Moolenbroek case PROTO_UNDEF:
5383*d56f51eaSDavid van Moolenbroek tmp = gen_portrangeop(port1, port2, IPPROTO_TCP, dir);
5384*d56f51eaSDavid van Moolenbroek b1 = gen_portrangeop(port1, port2, IPPROTO_UDP, dir);
5385*d56f51eaSDavid van Moolenbroek gen_or(tmp, b1);
5386*d56f51eaSDavid van Moolenbroek tmp = gen_portrangeop(port1, port2, IPPROTO_SCTP, dir);
5387*d56f51eaSDavid van Moolenbroek gen_or(tmp, b1);
5388*d56f51eaSDavid van Moolenbroek break;
5389*d56f51eaSDavid van Moolenbroek
5390*d56f51eaSDavid van Moolenbroek default:
5391*d56f51eaSDavid van Moolenbroek abort();
5392*d56f51eaSDavid van Moolenbroek }
5393*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
5394*d56f51eaSDavid van Moolenbroek return b1;
5395*d56f51eaSDavid van Moolenbroek }
5396*d56f51eaSDavid van Moolenbroek
5397*d56f51eaSDavid van Moolenbroek static struct block *
gen_portrangeatom6(off,v1,v2)5398*d56f51eaSDavid van Moolenbroek gen_portrangeatom6(off, v1, v2)
5399*d56f51eaSDavid van Moolenbroek int off;
5400*d56f51eaSDavid van Moolenbroek bpf_int32 v1, v2;
5401*d56f51eaSDavid van Moolenbroek {
5402*d56f51eaSDavid van Moolenbroek struct block *b1, *b2;
5403*d56f51eaSDavid van Moolenbroek
5404*d56f51eaSDavid van Moolenbroek if (v1 > v2) {
5405*d56f51eaSDavid van Moolenbroek /*
5406*d56f51eaSDavid van Moolenbroek * Reverse the order of the ports, so v1 is the lower one.
5407*d56f51eaSDavid van Moolenbroek */
5408*d56f51eaSDavid van Moolenbroek bpf_int32 vtemp;
5409*d56f51eaSDavid van Moolenbroek
5410*d56f51eaSDavid van Moolenbroek vtemp = v1;
5411*d56f51eaSDavid van Moolenbroek v1 = v2;
5412*d56f51eaSDavid van Moolenbroek v2 = vtemp;
5413*d56f51eaSDavid van Moolenbroek }
5414*d56f51eaSDavid van Moolenbroek
5415*d56f51eaSDavid van Moolenbroek b1 = gen_cmp_ge(OR_TRAN_IPV6, off, BPF_H, v1);
5416*d56f51eaSDavid van Moolenbroek b2 = gen_cmp_le(OR_TRAN_IPV6, off, BPF_H, v2);
5417*d56f51eaSDavid van Moolenbroek
5418*d56f51eaSDavid van Moolenbroek gen_and(b1, b2);
5419*d56f51eaSDavid van Moolenbroek
5420*d56f51eaSDavid van Moolenbroek return b2;
5421*d56f51eaSDavid van Moolenbroek }
5422*d56f51eaSDavid van Moolenbroek
5423*d56f51eaSDavid van Moolenbroek struct block *
gen_portrangeop6(port1,port2,proto,dir)5424*d56f51eaSDavid van Moolenbroek gen_portrangeop6(port1, port2, proto, dir)
5425*d56f51eaSDavid van Moolenbroek int port1, port2;
5426*d56f51eaSDavid van Moolenbroek int proto;
5427*d56f51eaSDavid van Moolenbroek int dir;
5428*d56f51eaSDavid van Moolenbroek {
5429*d56f51eaSDavid van Moolenbroek struct block *b0, *b1, *tmp;
5430*d56f51eaSDavid van Moolenbroek
5431*d56f51eaSDavid van Moolenbroek /* ip6 proto 'proto' */
5432*d56f51eaSDavid van Moolenbroek /* XXX - catch the first fragment of a fragmented packet? */
5433*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
5434*d56f51eaSDavid van Moolenbroek
5435*d56f51eaSDavid van Moolenbroek switch (dir) {
5436*d56f51eaSDavid van Moolenbroek case Q_SRC:
5437*d56f51eaSDavid van Moolenbroek b1 = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
5438*d56f51eaSDavid van Moolenbroek break;
5439*d56f51eaSDavid van Moolenbroek
5440*d56f51eaSDavid van Moolenbroek case Q_DST:
5441*d56f51eaSDavid van Moolenbroek b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
5442*d56f51eaSDavid van Moolenbroek break;
5443*d56f51eaSDavid van Moolenbroek
5444*d56f51eaSDavid van Moolenbroek case Q_OR:
5445*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
5446*d56f51eaSDavid van Moolenbroek tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
5447*d56f51eaSDavid van Moolenbroek b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
5448*d56f51eaSDavid van Moolenbroek gen_or(tmp, b1);
5449*d56f51eaSDavid van Moolenbroek break;
5450*d56f51eaSDavid van Moolenbroek
5451*d56f51eaSDavid van Moolenbroek case Q_AND:
5452*d56f51eaSDavid van Moolenbroek tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
5453*d56f51eaSDavid van Moolenbroek b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
5454*d56f51eaSDavid van Moolenbroek gen_and(tmp, b1);
5455*d56f51eaSDavid van Moolenbroek break;
5456*d56f51eaSDavid van Moolenbroek
5457*d56f51eaSDavid van Moolenbroek default:
5458*d56f51eaSDavid van Moolenbroek abort();
5459*d56f51eaSDavid van Moolenbroek }
5460*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
5461*d56f51eaSDavid van Moolenbroek
5462*d56f51eaSDavid van Moolenbroek return b1;
5463*d56f51eaSDavid van Moolenbroek }
5464*d56f51eaSDavid van Moolenbroek
5465*d56f51eaSDavid van Moolenbroek static struct block *
gen_portrange6(port1,port2,ip_proto,dir)5466*d56f51eaSDavid van Moolenbroek gen_portrange6(port1, port2, ip_proto, dir)
5467*d56f51eaSDavid van Moolenbroek int port1, port2;
5468*d56f51eaSDavid van Moolenbroek int ip_proto;
5469*d56f51eaSDavid van Moolenbroek int dir;
5470*d56f51eaSDavid van Moolenbroek {
5471*d56f51eaSDavid van Moolenbroek struct block *b0, *b1, *tmp;
5472*d56f51eaSDavid van Moolenbroek
5473*d56f51eaSDavid van Moolenbroek /* link proto ip6 */
5474*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(ETHERTYPE_IPV6);
5475*d56f51eaSDavid van Moolenbroek
5476*d56f51eaSDavid van Moolenbroek switch (ip_proto) {
5477*d56f51eaSDavid van Moolenbroek case IPPROTO_UDP:
5478*d56f51eaSDavid van Moolenbroek case IPPROTO_TCP:
5479*d56f51eaSDavid van Moolenbroek case IPPROTO_SCTP:
5480*d56f51eaSDavid van Moolenbroek b1 = gen_portrangeop6(port1, port2, ip_proto, dir);
5481*d56f51eaSDavid van Moolenbroek break;
5482*d56f51eaSDavid van Moolenbroek
5483*d56f51eaSDavid van Moolenbroek case PROTO_UNDEF:
5484*d56f51eaSDavid van Moolenbroek tmp = gen_portrangeop6(port1, port2, IPPROTO_TCP, dir);
5485*d56f51eaSDavid van Moolenbroek b1 = gen_portrangeop6(port1, port2, IPPROTO_UDP, dir);
5486*d56f51eaSDavid van Moolenbroek gen_or(tmp, b1);
5487*d56f51eaSDavid van Moolenbroek tmp = gen_portrangeop6(port1, port2, IPPROTO_SCTP, dir);
5488*d56f51eaSDavid van Moolenbroek gen_or(tmp, b1);
5489*d56f51eaSDavid van Moolenbroek break;
5490*d56f51eaSDavid van Moolenbroek
5491*d56f51eaSDavid van Moolenbroek default:
5492*d56f51eaSDavid van Moolenbroek abort();
5493*d56f51eaSDavid van Moolenbroek }
5494*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
5495*d56f51eaSDavid van Moolenbroek return b1;
5496*d56f51eaSDavid van Moolenbroek }
5497*d56f51eaSDavid van Moolenbroek
5498*d56f51eaSDavid van Moolenbroek static int
lookup_proto(name,proto)5499*d56f51eaSDavid van Moolenbroek lookup_proto(name, proto)
5500*d56f51eaSDavid van Moolenbroek register const char *name;
5501*d56f51eaSDavid van Moolenbroek register int proto;
5502*d56f51eaSDavid van Moolenbroek {
5503*d56f51eaSDavid van Moolenbroek register int v;
5504*d56f51eaSDavid van Moolenbroek
5505*d56f51eaSDavid van Moolenbroek switch (proto) {
5506*d56f51eaSDavid van Moolenbroek
5507*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
5508*d56f51eaSDavid van Moolenbroek case Q_IP:
5509*d56f51eaSDavid van Moolenbroek case Q_IPV6:
5510*d56f51eaSDavid van Moolenbroek v = pcap_nametoproto(name);
5511*d56f51eaSDavid van Moolenbroek if (v == PROTO_UNDEF)
5512*d56f51eaSDavid van Moolenbroek bpf_error("unknown ip proto '%s'", name);
5513*d56f51eaSDavid van Moolenbroek break;
5514*d56f51eaSDavid van Moolenbroek
5515*d56f51eaSDavid van Moolenbroek case Q_LINK:
5516*d56f51eaSDavid van Moolenbroek /* XXX should look up h/w protocol type based on linktype */
5517*d56f51eaSDavid van Moolenbroek v = pcap_nametoeproto(name);
5518*d56f51eaSDavid van Moolenbroek if (v == PROTO_UNDEF) {
5519*d56f51eaSDavid van Moolenbroek v = pcap_nametollc(name);
5520*d56f51eaSDavid van Moolenbroek if (v == PROTO_UNDEF)
5521*d56f51eaSDavid van Moolenbroek bpf_error("unknown ether proto '%s'", name);
5522*d56f51eaSDavid van Moolenbroek }
5523*d56f51eaSDavid van Moolenbroek break;
5524*d56f51eaSDavid van Moolenbroek
5525*d56f51eaSDavid van Moolenbroek case Q_ISO:
5526*d56f51eaSDavid van Moolenbroek if (strcmp(name, "esis") == 0)
5527*d56f51eaSDavid van Moolenbroek v = ISO9542_ESIS;
5528*d56f51eaSDavid van Moolenbroek else if (strcmp(name, "isis") == 0)
5529*d56f51eaSDavid van Moolenbroek v = ISO10589_ISIS;
5530*d56f51eaSDavid van Moolenbroek else if (strcmp(name, "clnp") == 0)
5531*d56f51eaSDavid van Moolenbroek v = ISO8473_CLNP;
5532*d56f51eaSDavid van Moolenbroek else
5533*d56f51eaSDavid van Moolenbroek bpf_error("unknown osi proto '%s'", name);
5534*d56f51eaSDavid van Moolenbroek break;
5535*d56f51eaSDavid van Moolenbroek
5536*d56f51eaSDavid van Moolenbroek default:
5537*d56f51eaSDavid van Moolenbroek v = PROTO_UNDEF;
5538*d56f51eaSDavid van Moolenbroek break;
5539*d56f51eaSDavid van Moolenbroek }
5540*d56f51eaSDavid van Moolenbroek return v;
5541*d56f51eaSDavid van Moolenbroek }
5542*d56f51eaSDavid van Moolenbroek
5543*d56f51eaSDavid van Moolenbroek #if 0
5544*d56f51eaSDavid van Moolenbroek struct stmt *
5545*d56f51eaSDavid van Moolenbroek gen_joinsp(s, n)
5546*d56f51eaSDavid van Moolenbroek struct stmt **s;
5547*d56f51eaSDavid van Moolenbroek int n;
5548*d56f51eaSDavid van Moolenbroek {
5549*d56f51eaSDavid van Moolenbroek return NULL;
5550*d56f51eaSDavid van Moolenbroek }
5551*d56f51eaSDavid van Moolenbroek #endif
5552*d56f51eaSDavid van Moolenbroek
5553*d56f51eaSDavid van Moolenbroek static struct block *
gen_protochain(v,proto,dir)5554*d56f51eaSDavid van Moolenbroek gen_protochain(v, proto, dir)
5555*d56f51eaSDavid van Moolenbroek int v;
5556*d56f51eaSDavid van Moolenbroek int proto;
5557*d56f51eaSDavid van Moolenbroek int dir;
5558*d56f51eaSDavid van Moolenbroek {
5559*d56f51eaSDavid van Moolenbroek #ifdef NO_PROTOCHAIN
5560*d56f51eaSDavid van Moolenbroek return gen_proto(v, proto, dir);
5561*d56f51eaSDavid van Moolenbroek #else
5562*d56f51eaSDavid van Moolenbroek struct block *b0, *b;
5563*d56f51eaSDavid van Moolenbroek struct slist *s[100];
5564*d56f51eaSDavid van Moolenbroek int fix2, fix3, fix4, fix5;
5565*d56f51eaSDavid van Moolenbroek int ahcheck, again, end;
5566*d56f51eaSDavid van Moolenbroek int i, max;
5567*d56f51eaSDavid van Moolenbroek int reg2 = alloc_reg();
5568*d56f51eaSDavid van Moolenbroek
5569*d56f51eaSDavid van Moolenbroek memset(s, 0, sizeof(s));
5570*d56f51eaSDavid van Moolenbroek fix2 = fix3 = fix4 = fix5 = 0;
5571*d56f51eaSDavid van Moolenbroek
5572*d56f51eaSDavid van Moolenbroek switch (proto) {
5573*d56f51eaSDavid van Moolenbroek case Q_IP:
5574*d56f51eaSDavid van Moolenbroek case Q_IPV6:
5575*d56f51eaSDavid van Moolenbroek break;
5576*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
5577*d56f51eaSDavid van Moolenbroek b0 = gen_protochain(v, Q_IP, dir);
5578*d56f51eaSDavid van Moolenbroek b = gen_protochain(v, Q_IPV6, dir);
5579*d56f51eaSDavid van Moolenbroek gen_or(b0, b);
5580*d56f51eaSDavid van Moolenbroek return b;
5581*d56f51eaSDavid van Moolenbroek default:
5582*d56f51eaSDavid van Moolenbroek bpf_error("bad protocol applied for 'protochain'");
5583*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
5584*d56f51eaSDavid van Moolenbroek }
5585*d56f51eaSDavid van Moolenbroek
5586*d56f51eaSDavid van Moolenbroek /*
5587*d56f51eaSDavid van Moolenbroek * We don't handle variable-length prefixes before the link-layer
5588*d56f51eaSDavid van Moolenbroek * header, or variable-length link-layer headers, here yet.
5589*d56f51eaSDavid van Moolenbroek * We might want to add BPF instructions to do the protochain
5590*d56f51eaSDavid van Moolenbroek * work, to simplify that and, on platforms that have a BPF
5591*d56f51eaSDavid van Moolenbroek * interpreter with the new instructions, let the filtering
5592*d56f51eaSDavid van Moolenbroek * be done in the kernel. (We already require a modified BPF
5593*d56f51eaSDavid van Moolenbroek * engine to do the protochain stuff, to support backward
5594*d56f51eaSDavid van Moolenbroek * branches, and backward branch support is unlikely to appear
5595*d56f51eaSDavid van Moolenbroek * in kernel BPF engines.)
5596*d56f51eaSDavid van Moolenbroek */
5597*d56f51eaSDavid van Moolenbroek if (off_linkpl.is_variable)
5598*d56f51eaSDavid van Moolenbroek bpf_error("'protochain' not supported with variable length headers");
5599*d56f51eaSDavid van Moolenbroek
5600*d56f51eaSDavid van Moolenbroek no_optimize = 1; /*this code is not compatible with optimzer yet */
5601*d56f51eaSDavid van Moolenbroek
5602*d56f51eaSDavid van Moolenbroek /*
5603*d56f51eaSDavid van Moolenbroek * s[0] is a dummy entry to protect other BPF insn from damage
5604*d56f51eaSDavid van Moolenbroek * by s[fix] = foo with uninitialized variable "fix". It is somewhat
5605*d56f51eaSDavid van Moolenbroek * hard to find interdependency made by jump table fixup.
5606*d56f51eaSDavid van Moolenbroek */
5607*d56f51eaSDavid van Moolenbroek i = 0;
5608*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(0); /*dummy*/
5609*d56f51eaSDavid van Moolenbroek i++;
5610*d56f51eaSDavid van Moolenbroek
5611*d56f51eaSDavid van Moolenbroek switch (proto) {
5612*d56f51eaSDavid van Moolenbroek case Q_IP:
5613*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(ETHERTYPE_IP);
5614*d56f51eaSDavid van Moolenbroek
5615*d56f51eaSDavid van Moolenbroek /* A = ip->ip_p */
5616*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
5617*d56f51eaSDavid van Moolenbroek s[i]->s.k = off_linkpl.constant_part + off_nl + 9;
5618*d56f51eaSDavid van Moolenbroek i++;
5619*d56f51eaSDavid van Moolenbroek /* X = ip->ip_hl << 2 */
5620*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
5621*d56f51eaSDavid van Moolenbroek s[i]->s.k = off_linkpl.constant_part + off_nl;
5622*d56f51eaSDavid van Moolenbroek i++;
5623*d56f51eaSDavid van Moolenbroek break;
5624*d56f51eaSDavid van Moolenbroek
5625*d56f51eaSDavid van Moolenbroek case Q_IPV6:
5626*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(ETHERTYPE_IPV6);
5627*d56f51eaSDavid van Moolenbroek
5628*d56f51eaSDavid van Moolenbroek /* A = ip6->ip_nxt */
5629*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
5630*d56f51eaSDavid van Moolenbroek s[i]->s.k = off_linkpl.constant_part + off_nl + 6;
5631*d56f51eaSDavid van Moolenbroek i++;
5632*d56f51eaSDavid van Moolenbroek /* X = sizeof(struct ip6_hdr) */
5633*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_LDX|BPF_IMM);
5634*d56f51eaSDavid van Moolenbroek s[i]->s.k = 40;
5635*d56f51eaSDavid van Moolenbroek i++;
5636*d56f51eaSDavid van Moolenbroek break;
5637*d56f51eaSDavid van Moolenbroek
5638*d56f51eaSDavid van Moolenbroek default:
5639*d56f51eaSDavid van Moolenbroek bpf_error("unsupported proto to gen_protochain");
5640*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
5641*d56f51eaSDavid van Moolenbroek }
5642*d56f51eaSDavid van Moolenbroek
5643*d56f51eaSDavid van Moolenbroek /* again: if (A == v) goto end; else fall through; */
5644*d56f51eaSDavid van Moolenbroek again = i;
5645*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
5646*d56f51eaSDavid van Moolenbroek s[i]->s.k = v;
5647*d56f51eaSDavid van Moolenbroek s[i]->s.jt = NULL; /*later*/
5648*d56f51eaSDavid van Moolenbroek s[i]->s.jf = NULL; /*update in next stmt*/
5649*d56f51eaSDavid van Moolenbroek fix5 = i;
5650*d56f51eaSDavid van Moolenbroek i++;
5651*d56f51eaSDavid van Moolenbroek
5652*d56f51eaSDavid van Moolenbroek #ifndef IPPROTO_NONE
5653*d56f51eaSDavid van Moolenbroek #define IPPROTO_NONE 59
5654*d56f51eaSDavid van Moolenbroek #endif
5655*d56f51eaSDavid van Moolenbroek /* if (A == IPPROTO_NONE) goto end */
5656*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
5657*d56f51eaSDavid van Moolenbroek s[i]->s.jt = NULL; /*later*/
5658*d56f51eaSDavid van Moolenbroek s[i]->s.jf = NULL; /*update in next stmt*/
5659*d56f51eaSDavid van Moolenbroek s[i]->s.k = IPPROTO_NONE;
5660*d56f51eaSDavid van Moolenbroek s[fix5]->s.jf = s[i];
5661*d56f51eaSDavid van Moolenbroek fix2 = i;
5662*d56f51eaSDavid van Moolenbroek i++;
5663*d56f51eaSDavid van Moolenbroek
5664*d56f51eaSDavid van Moolenbroek if (proto == Q_IPV6) {
5665*d56f51eaSDavid van Moolenbroek int v6start, v6end, v6advance, j;
5666*d56f51eaSDavid van Moolenbroek
5667*d56f51eaSDavid van Moolenbroek v6start = i;
5668*d56f51eaSDavid van Moolenbroek /* if (A == IPPROTO_HOPOPTS) goto v6advance */
5669*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
5670*d56f51eaSDavid van Moolenbroek s[i]->s.jt = NULL; /*later*/
5671*d56f51eaSDavid van Moolenbroek s[i]->s.jf = NULL; /*update in next stmt*/
5672*d56f51eaSDavid van Moolenbroek s[i]->s.k = IPPROTO_HOPOPTS;
5673*d56f51eaSDavid van Moolenbroek s[fix2]->s.jf = s[i];
5674*d56f51eaSDavid van Moolenbroek i++;
5675*d56f51eaSDavid van Moolenbroek /* if (A == IPPROTO_DSTOPTS) goto v6advance */
5676*d56f51eaSDavid van Moolenbroek s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
5677*d56f51eaSDavid van Moolenbroek s[i]->s.jt = NULL; /*later*/
5678*d56f51eaSDavid van Moolenbroek s[i]->s.jf = NULL; /*update in next stmt*/
5679*d56f51eaSDavid van Moolenbroek s[i]->s.k = IPPROTO_DSTOPTS;
5680*d56f51eaSDavid van Moolenbroek i++;
5681*d56f51eaSDavid van Moolenbroek /* if (A == IPPROTO_ROUTING) goto v6advance */
5682*d56f51eaSDavid van Moolenbroek s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
5683*d56f51eaSDavid van Moolenbroek s[i]->s.jt = NULL; /*later*/
5684*d56f51eaSDavid van Moolenbroek s[i]->s.jf = NULL; /*update in next stmt*/
5685*d56f51eaSDavid van Moolenbroek s[i]->s.k = IPPROTO_ROUTING;
5686*d56f51eaSDavid van Moolenbroek i++;
5687*d56f51eaSDavid van Moolenbroek /* if (A == IPPROTO_FRAGMENT) goto v6advance; else goto ahcheck; */
5688*d56f51eaSDavid van Moolenbroek s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
5689*d56f51eaSDavid van Moolenbroek s[i]->s.jt = NULL; /*later*/
5690*d56f51eaSDavid van Moolenbroek s[i]->s.jf = NULL; /*later*/
5691*d56f51eaSDavid van Moolenbroek s[i]->s.k = IPPROTO_FRAGMENT;
5692*d56f51eaSDavid van Moolenbroek fix3 = i;
5693*d56f51eaSDavid van Moolenbroek v6end = i;
5694*d56f51eaSDavid van Moolenbroek i++;
5695*d56f51eaSDavid van Moolenbroek
5696*d56f51eaSDavid van Moolenbroek /* v6advance: */
5697*d56f51eaSDavid van Moolenbroek v6advance = i;
5698*d56f51eaSDavid van Moolenbroek
5699*d56f51eaSDavid van Moolenbroek /*
5700*d56f51eaSDavid van Moolenbroek * in short,
5701*d56f51eaSDavid van Moolenbroek * A = P[X + packet head];
5702*d56f51eaSDavid van Moolenbroek * X = X + (P[X + packet head + 1] + 1) * 8;
5703*d56f51eaSDavid van Moolenbroek */
5704*d56f51eaSDavid van Moolenbroek /* A = P[X + packet head] */
5705*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
5706*d56f51eaSDavid van Moolenbroek s[i]->s.k = off_linkpl.constant_part + off_nl;
5707*d56f51eaSDavid van Moolenbroek i++;
5708*d56f51eaSDavid van Moolenbroek /* MEM[reg2] = A */
5709*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_ST);
5710*d56f51eaSDavid van Moolenbroek s[i]->s.k = reg2;
5711*d56f51eaSDavid van Moolenbroek i++;
5712*d56f51eaSDavid van Moolenbroek /* A = P[X + packet head + 1]; */
5713*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
5714*d56f51eaSDavid van Moolenbroek s[i]->s.k = off_linkpl.constant_part + off_nl + 1;
5715*d56f51eaSDavid van Moolenbroek i++;
5716*d56f51eaSDavid van Moolenbroek /* A += 1 */
5717*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
5718*d56f51eaSDavid van Moolenbroek s[i]->s.k = 1;
5719*d56f51eaSDavid van Moolenbroek i++;
5720*d56f51eaSDavid van Moolenbroek /* A *= 8 */
5721*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
5722*d56f51eaSDavid van Moolenbroek s[i]->s.k = 8;
5723*d56f51eaSDavid van Moolenbroek i++;
5724*d56f51eaSDavid van Moolenbroek /* A += X */
5725*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_X);
5726*d56f51eaSDavid van Moolenbroek s[i]->s.k = 0;
5727*d56f51eaSDavid van Moolenbroek i++;
5728*d56f51eaSDavid van Moolenbroek /* X = A; */
5729*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_MISC|BPF_TAX);
5730*d56f51eaSDavid van Moolenbroek i++;
5731*d56f51eaSDavid van Moolenbroek /* A = MEM[reg2] */
5732*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_LD|BPF_MEM);
5733*d56f51eaSDavid van Moolenbroek s[i]->s.k = reg2;
5734*d56f51eaSDavid van Moolenbroek i++;
5735*d56f51eaSDavid van Moolenbroek
5736*d56f51eaSDavid van Moolenbroek /* goto again; (must use BPF_JA for backward jump) */
5737*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_JMP|BPF_JA);
5738*d56f51eaSDavid van Moolenbroek s[i]->s.k = again - i - 1;
5739*d56f51eaSDavid van Moolenbroek s[i - 1]->s.jf = s[i];
5740*d56f51eaSDavid van Moolenbroek i++;
5741*d56f51eaSDavid van Moolenbroek
5742*d56f51eaSDavid van Moolenbroek /* fixup */
5743*d56f51eaSDavid van Moolenbroek for (j = v6start; j <= v6end; j++)
5744*d56f51eaSDavid van Moolenbroek s[j]->s.jt = s[v6advance];
5745*d56f51eaSDavid van Moolenbroek } else {
5746*d56f51eaSDavid van Moolenbroek /* nop */
5747*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
5748*d56f51eaSDavid van Moolenbroek s[i]->s.k = 0;
5749*d56f51eaSDavid van Moolenbroek s[fix2]->s.jf = s[i];
5750*d56f51eaSDavid van Moolenbroek i++;
5751*d56f51eaSDavid van Moolenbroek }
5752*d56f51eaSDavid van Moolenbroek
5753*d56f51eaSDavid van Moolenbroek /* ahcheck: */
5754*d56f51eaSDavid van Moolenbroek ahcheck = i;
5755*d56f51eaSDavid van Moolenbroek /* if (A == IPPROTO_AH) then fall through; else goto end; */
5756*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
5757*d56f51eaSDavid van Moolenbroek s[i]->s.jt = NULL; /*later*/
5758*d56f51eaSDavid van Moolenbroek s[i]->s.jf = NULL; /*later*/
5759*d56f51eaSDavid van Moolenbroek s[i]->s.k = IPPROTO_AH;
5760*d56f51eaSDavid van Moolenbroek if (fix3)
5761*d56f51eaSDavid van Moolenbroek s[fix3]->s.jf = s[ahcheck];
5762*d56f51eaSDavid van Moolenbroek fix4 = i;
5763*d56f51eaSDavid van Moolenbroek i++;
5764*d56f51eaSDavid van Moolenbroek
5765*d56f51eaSDavid van Moolenbroek /*
5766*d56f51eaSDavid van Moolenbroek * in short,
5767*d56f51eaSDavid van Moolenbroek * A = P[X];
5768*d56f51eaSDavid van Moolenbroek * X = X + (P[X + 1] + 2) * 4;
5769*d56f51eaSDavid van Moolenbroek */
5770*d56f51eaSDavid van Moolenbroek /* A = X */
5771*d56f51eaSDavid van Moolenbroek s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA);
5772*d56f51eaSDavid van Moolenbroek i++;
5773*d56f51eaSDavid van Moolenbroek /* A = P[X + packet head]; */
5774*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
5775*d56f51eaSDavid van Moolenbroek s[i]->s.k = off_linkpl.constant_part + off_nl;
5776*d56f51eaSDavid van Moolenbroek i++;
5777*d56f51eaSDavid van Moolenbroek /* MEM[reg2] = A */
5778*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_ST);
5779*d56f51eaSDavid van Moolenbroek s[i]->s.k = reg2;
5780*d56f51eaSDavid van Moolenbroek i++;
5781*d56f51eaSDavid van Moolenbroek /* A = X */
5782*d56f51eaSDavid van Moolenbroek s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA);
5783*d56f51eaSDavid van Moolenbroek i++;
5784*d56f51eaSDavid van Moolenbroek /* A += 1 */
5785*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
5786*d56f51eaSDavid van Moolenbroek s[i]->s.k = 1;
5787*d56f51eaSDavid van Moolenbroek i++;
5788*d56f51eaSDavid van Moolenbroek /* X = A */
5789*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_MISC|BPF_TAX);
5790*d56f51eaSDavid van Moolenbroek i++;
5791*d56f51eaSDavid van Moolenbroek /* A = P[X + packet head] */
5792*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
5793*d56f51eaSDavid van Moolenbroek s[i]->s.k = off_linkpl.constant_part + off_nl;
5794*d56f51eaSDavid van Moolenbroek i++;
5795*d56f51eaSDavid van Moolenbroek /* A += 2 */
5796*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
5797*d56f51eaSDavid van Moolenbroek s[i]->s.k = 2;
5798*d56f51eaSDavid van Moolenbroek i++;
5799*d56f51eaSDavid van Moolenbroek /* A *= 4 */
5800*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
5801*d56f51eaSDavid van Moolenbroek s[i]->s.k = 4;
5802*d56f51eaSDavid van Moolenbroek i++;
5803*d56f51eaSDavid van Moolenbroek /* X = A; */
5804*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_MISC|BPF_TAX);
5805*d56f51eaSDavid van Moolenbroek i++;
5806*d56f51eaSDavid van Moolenbroek /* A = MEM[reg2] */
5807*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_LD|BPF_MEM);
5808*d56f51eaSDavid van Moolenbroek s[i]->s.k = reg2;
5809*d56f51eaSDavid van Moolenbroek i++;
5810*d56f51eaSDavid van Moolenbroek
5811*d56f51eaSDavid van Moolenbroek /* goto again; (must use BPF_JA for backward jump) */
5812*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_JMP|BPF_JA);
5813*d56f51eaSDavid van Moolenbroek s[i]->s.k = again - i - 1;
5814*d56f51eaSDavid van Moolenbroek i++;
5815*d56f51eaSDavid van Moolenbroek
5816*d56f51eaSDavid van Moolenbroek /* end: nop */
5817*d56f51eaSDavid van Moolenbroek end = i;
5818*d56f51eaSDavid van Moolenbroek s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
5819*d56f51eaSDavid van Moolenbroek s[i]->s.k = 0;
5820*d56f51eaSDavid van Moolenbroek s[fix2]->s.jt = s[end];
5821*d56f51eaSDavid van Moolenbroek s[fix4]->s.jf = s[end];
5822*d56f51eaSDavid van Moolenbroek s[fix5]->s.jt = s[end];
5823*d56f51eaSDavid van Moolenbroek i++;
5824*d56f51eaSDavid van Moolenbroek
5825*d56f51eaSDavid van Moolenbroek /*
5826*d56f51eaSDavid van Moolenbroek * make slist chain
5827*d56f51eaSDavid van Moolenbroek */
5828*d56f51eaSDavid van Moolenbroek max = i;
5829*d56f51eaSDavid van Moolenbroek for (i = 0; i < max - 1; i++)
5830*d56f51eaSDavid van Moolenbroek s[i]->next = s[i + 1];
5831*d56f51eaSDavid van Moolenbroek s[max - 1]->next = NULL;
5832*d56f51eaSDavid van Moolenbroek
5833*d56f51eaSDavid van Moolenbroek /*
5834*d56f51eaSDavid van Moolenbroek * emit final check
5835*d56f51eaSDavid van Moolenbroek */
5836*d56f51eaSDavid van Moolenbroek b = new_block(JMP(BPF_JEQ));
5837*d56f51eaSDavid van Moolenbroek b->stmts = s[1]; /*remember, s[0] is dummy*/
5838*d56f51eaSDavid van Moolenbroek b->s.k = v;
5839*d56f51eaSDavid van Moolenbroek
5840*d56f51eaSDavid van Moolenbroek free_reg(reg2);
5841*d56f51eaSDavid van Moolenbroek
5842*d56f51eaSDavid van Moolenbroek gen_and(b0, b);
5843*d56f51eaSDavid van Moolenbroek return b;
5844*d56f51eaSDavid van Moolenbroek #endif
5845*d56f51eaSDavid van Moolenbroek }
5846*d56f51eaSDavid van Moolenbroek
5847*d56f51eaSDavid van Moolenbroek static struct block *
gen_check_802_11_data_frame()5848*d56f51eaSDavid van Moolenbroek gen_check_802_11_data_frame()
5849*d56f51eaSDavid van Moolenbroek {
5850*d56f51eaSDavid van Moolenbroek struct slist *s;
5851*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
5852*d56f51eaSDavid van Moolenbroek
5853*d56f51eaSDavid van Moolenbroek /*
5854*d56f51eaSDavid van Moolenbroek * A data frame has the 0x08 bit (b3) in the frame control field set
5855*d56f51eaSDavid van Moolenbroek * and the 0x04 bit (b2) clear.
5856*d56f51eaSDavid van Moolenbroek */
5857*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 0, BPF_B);
5858*d56f51eaSDavid van Moolenbroek b0 = new_block(JMP(BPF_JSET));
5859*d56f51eaSDavid van Moolenbroek b0->s.k = 0x08;
5860*d56f51eaSDavid van Moolenbroek b0->stmts = s;
5861*d56f51eaSDavid van Moolenbroek
5862*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 0, BPF_B);
5863*d56f51eaSDavid van Moolenbroek b1 = new_block(JMP(BPF_JSET));
5864*d56f51eaSDavid van Moolenbroek b1->s.k = 0x04;
5865*d56f51eaSDavid van Moolenbroek b1->stmts = s;
5866*d56f51eaSDavid van Moolenbroek gen_not(b1);
5867*d56f51eaSDavid van Moolenbroek
5868*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
5869*d56f51eaSDavid van Moolenbroek
5870*d56f51eaSDavid van Moolenbroek return b0;
5871*d56f51eaSDavid van Moolenbroek }
5872*d56f51eaSDavid van Moolenbroek
5873*d56f51eaSDavid van Moolenbroek /*
5874*d56f51eaSDavid van Moolenbroek * Generate code that checks whether the packet is a packet for protocol
5875*d56f51eaSDavid van Moolenbroek * <proto> and whether the type field in that protocol's header has
5876*d56f51eaSDavid van Moolenbroek * the value <v>, e.g. if <proto> is Q_IP, it checks whether it's an
5877*d56f51eaSDavid van Moolenbroek * IP packet and checks the protocol number in the IP header against <v>.
5878*d56f51eaSDavid van Moolenbroek *
5879*d56f51eaSDavid van Moolenbroek * If <proto> is Q_DEFAULT, i.e. just "proto" was specified, it checks
5880*d56f51eaSDavid van Moolenbroek * against Q_IP and Q_IPV6.
5881*d56f51eaSDavid van Moolenbroek */
5882*d56f51eaSDavid van Moolenbroek static struct block *
gen_proto(v,proto,dir)5883*d56f51eaSDavid van Moolenbroek gen_proto(v, proto, dir)
5884*d56f51eaSDavid van Moolenbroek int v;
5885*d56f51eaSDavid van Moolenbroek int proto;
5886*d56f51eaSDavid van Moolenbroek int dir;
5887*d56f51eaSDavid van Moolenbroek {
5888*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
5889*d56f51eaSDavid van Moolenbroek #ifndef CHASE_CHAIN
5890*d56f51eaSDavid van Moolenbroek struct block *b2;
5891*d56f51eaSDavid van Moolenbroek #endif
5892*d56f51eaSDavid van Moolenbroek
5893*d56f51eaSDavid van Moolenbroek if (dir != Q_DEFAULT)
5894*d56f51eaSDavid van Moolenbroek bpf_error("direction applied to 'proto'");
5895*d56f51eaSDavid van Moolenbroek
5896*d56f51eaSDavid van Moolenbroek switch (proto) {
5897*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
5898*d56f51eaSDavid van Moolenbroek b0 = gen_proto(v, Q_IP, dir);
5899*d56f51eaSDavid van Moolenbroek b1 = gen_proto(v, Q_IPV6, dir);
5900*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
5901*d56f51eaSDavid van Moolenbroek return b1;
5902*d56f51eaSDavid van Moolenbroek
5903*d56f51eaSDavid van Moolenbroek case Q_IP:
5904*d56f51eaSDavid van Moolenbroek /*
5905*d56f51eaSDavid van Moolenbroek * For FDDI, RFC 1188 says that SNAP encapsulation is used,
5906*d56f51eaSDavid van Moolenbroek * not LLC encapsulation with LLCSAP_IP.
5907*d56f51eaSDavid van Moolenbroek *
5908*d56f51eaSDavid van Moolenbroek * For IEEE 802 networks - which includes 802.5 token ring
5909*d56f51eaSDavid van Moolenbroek * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042
5910*d56f51eaSDavid van Moolenbroek * says that SNAP encapsulation is used, not LLC encapsulation
5911*d56f51eaSDavid van Moolenbroek * with LLCSAP_IP.
5912*d56f51eaSDavid van Moolenbroek *
5913*d56f51eaSDavid van Moolenbroek * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and
5914*d56f51eaSDavid van Moolenbroek * RFC 2225 say that SNAP encapsulation is used, not LLC
5915*d56f51eaSDavid van Moolenbroek * encapsulation with LLCSAP_IP.
5916*d56f51eaSDavid van Moolenbroek *
5917*d56f51eaSDavid van Moolenbroek * So we always check for ETHERTYPE_IP.
5918*d56f51eaSDavid van Moolenbroek */
5919*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(ETHERTYPE_IP);
5920*d56f51eaSDavid van Moolenbroek #ifndef CHASE_CHAIN
5921*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LINKPL, 9, BPF_B, (bpf_int32)v);
5922*d56f51eaSDavid van Moolenbroek #else
5923*d56f51eaSDavid van Moolenbroek b1 = gen_protochain(v, Q_IP);
5924*d56f51eaSDavid van Moolenbroek #endif
5925*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
5926*d56f51eaSDavid van Moolenbroek return b1;
5927*d56f51eaSDavid van Moolenbroek
5928*d56f51eaSDavid van Moolenbroek case Q_ISO:
5929*d56f51eaSDavid van Moolenbroek switch (linktype) {
5930*d56f51eaSDavid van Moolenbroek
5931*d56f51eaSDavid van Moolenbroek case DLT_FRELAY:
5932*d56f51eaSDavid van Moolenbroek /*
5933*d56f51eaSDavid van Moolenbroek * Frame Relay packets typically have an OSI
5934*d56f51eaSDavid van Moolenbroek * NLPID at the beginning; "gen_linktype(LLCSAP_ISONS)"
5935*d56f51eaSDavid van Moolenbroek * generates code to check for all the OSI
5936*d56f51eaSDavid van Moolenbroek * NLPIDs, so calling it and then adding a check
5937*d56f51eaSDavid van Moolenbroek * for the particular NLPID for which we're
5938*d56f51eaSDavid van Moolenbroek * looking is bogus, as we can just check for
5939*d56f51eaSDavid van Moolenbroek * the NLPID.
5940*d56f51eaSDavid van Moolenbroek *
5941*d56f51eaSDavid van Moolenbroek * What we check for is the NLPID and a frame
5942*d56f51eaSDavid van Moolenbroek * control field value of UI, i.e. 0x03 followed
5943*d56f51eaSDavid van Moolenbroek * by the NLPID.
5944*d56f51eaSDavid van Moolenbroek *
5945*d56f51eaSDavid van Moolenbroek * XXX - assumes a 2-byte Frame Relay header with
5946*d56f51eaSDavid van Moolenbroek * DLCI and flags. What if the address is longer?
5947*d56f51eaSDavid van Moolenbroek *
5948*d56f51eaSDavid van Moolenbroek * XXX - what about SNAP-encapsulated frames?
5949*d56f51eaSDavid van Moolenbroek */
5950*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_LINKHDR, 2, BPF_H, (0x03<<8) | v);
5951*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
5952*d56f51eaSDavid van Moolenbroek break;
5953*d56f51eaSDavid van Moolenbroek
5954*d56f51eaSDavid van Moolenbroek case DLT_C_HDLC:
5955*d56f51eaSDavid van Moolenbroek /*
5956*d56f51eaSDavid van Moolenbroek * Cisco uses an Ethertype lookalike - for OSI,
5957*d56f51eaSDavid van Moolenbroek * it's 0xfefe.
5958*d56f51eaSDavid van Moolenbroek */
5959*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(LLCSAP_ISONS<<8 | LLCSAP_ISONS);
5960*d56f51eaSDavid van Moolenbroek /* OSI in C-HDLC is stuffed with a fudge byte */
5961*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LINKPL_NOSNAP, 1, BPF_B, (long)v);
5962*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
5963*d56f51eaSDavid van Moolenbroek return b1;
5964*d56f51eaSDavid van Moolenbroek
5965*d56f51eaSDavid van Moolenbroek default:
5966*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(LLCSAP_ISONS);
5967*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LINKPL_NOSNAP, 0, BPF_B, (long)v);
5968*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
5969*d56f51eaSDavid van Moolenbroek return b1;
5970*d56f51eaSDavid van Moolenbroek }
5971*d56f51eaSDavid van Moolenbroek
5972*d56f51eaSDavid van Moolenbroek case Q_ISIS:
5973*d56f51eaSDavid van Moolenbroek b0 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
5974*d56f51eaSDavid van Moolenbroek /*
5975*d56f51eaSDavid van Moolenbroek * 4 is the offset of the PDU type relative to the IS-IS
5976*d56f51eaSDavid van Moolenbroek * header.
5977*d56f51eaSDavid van Moolenbroek */
5978*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LINKPL_NOSNAP, 4, BPF_B, (long)v);
5979*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
5980*d56f51eaSDavid van Moolenbroek return b1;
5981*d56f51eaSDavid van Moolenbroek
5982*d56f51eaSDavid van Moolenbroek case Q_ARP:
5983*d56f51eaSDavid van Moolenbroek bpf_error("arp does not encapsulate another protocol");
5984*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
5985*d56f51eaSDavid van Moolenbroek
5986*d56f51eaSDavid van Moolenbroek case Q_RARP:
5987*d56f51eaSDavid van Moolenbroek bpf_error("rarp does not encapsulate another protocol");
5988*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
5989*d56f51eaSDavid van Moolenbroek
5990*d56f51eaSDavid van Moolenbroek case Q_ATALK:
5991*d56f51eaSDavid van Moolenbroek bpf_error("atalk encapsulation is not specifiable");
5992*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
5993*d56f51eaSDavid van Moolenbroek
5994*d56f51eaSDavid van Moolenbroek case Q_DECNET:
5995*d56f51eaSDavid van Moolenbroek bpf_error("decnet encapsulation is not specifiable");
5996*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
5997*d56f51eaSDavid van Moolenbroek
5998*d56f51eaSDavid van Moolenbroek case Q_SCA:
5999*d56f51eaSDavid van Moolenbroek bpf_error("sca does not encapsulate another protocol");
6000*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6001*d56f51eaSDavid van Moolenbroek
6002*d56f51eaSDavid van Moolenbroek case Q_LAT:
6003*d56f51eaSDavid van Moolenbroek bpf_error("lat does not encapsulate another protocol");
6004*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6005*d56f51eaSDavid van Moolenbroek
6006*d56f51eaSDavid van Moolenbroek case Q_MOPRC:
6007*d56f51eaSDavid van Moolenbroek bpf_error("moprc does not encapsulate another protocol");
6008*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6009*d56f51eaSDavid van Moolenbroek
6010*d56f51eaSDavid van Moolenbroek case Q_MOPDL:
6011*d56f51eaSDavid van Moolenbroek bpf_error("mopdl does not encapsulate another protocol");
6012*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6013*d56f51eaSDavid van Moolenbroek
6014*d56f51eaSDavid van Moolenbroek case Q_LINK:
6015*d56f51eaSDavid van Moolenbroek return gen_linktype(v);
6016*d56f51eaSDavid van Moolenbroek
6017*d56f51eaSDavid van Moolenbroek case Q_UDP:
6018*d56f51eaSDavid van Moolenbroek bpf_error("'udp proto' is bogus");
6019*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6020*d56f51eaSDavid van Moolenbroek
6021*d56f51eaSDavid van Moolenbroek case Q_TCP:
6022*d56f51eaSDavid van Moolenbroek bpf_error("'tcp proto' is bogus");
6023*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6024*d56f51eaSDavid van Moolenbroek
6025*d56f51eaSDavid van Moolenbroek case Q_SCTP:
6026*d56f51eaSDavid van Moolenbroek bpf_error("'sctp proto' is bogus");
6027*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6028*d56f51eaSDavid van Moolenbroek
6029*d56f51eaSDavid van Moolenbroek case Q_ICMP:
6030*d56f51eaSDavid van Moolenbroek bpf_error("'icmp proto' is bogus");
6031*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6032*d56f51eaSDavid van Moolenbroek
6033*d56f51eaSDavid van Moolenbroek case Q_IGMP:
6034*d56f51eaSDavid van Moolenbroek bpf_error("'igmp proto' is bogus");
6035*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6036*d56f51eaSDavid van Moolenbroek
6037*d56f51eaSDavid van Moolenbroek case Q_IGRP:
6038*d56f51eaSDavid van Moolenbroek bpf_error("'igrp proto' is bogus");
6039*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6040*d56f51eaSDavid van Moolenbroek
6041*d56f51eaSDavid van Moolenbroek case Q_PIM:
6042*d56f51eaSDavid van Moolenbroek bpf_error("'pim proto' is bogus");
6043*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6044*d56f51eaSDavid van Moolenbroek
6045*d56f51eaSDavid van Moolenbroek case Q_VRRP:
6046*d56f51eaSDavid van Moolenbroek bpf_error("'vrrp proto' is bogus");
6047*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6048*d56f51eaSDavid van Moolenbroek
6049*d56f51eaSDavid van Moolenbroek case Q_CARP:
6050*d56f51eaSDavid van Moolenbroek bpf_error("'carp proto' is bogus");
6051*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6052*d56f51eaSDavid van Moolenbroek
6053*d56f51eaSDavid van Moolenbroek case Q_IPV6:
6054*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(ETHERTYPE_IPV6);
6055*d56f51eaSDavid van Moolenbroek #ifndef CHASE_CHAIN
6056*d56f51eaSDavid van Moolenbroek /*
6057*d56f51eaSDavid van Moolenbroek * Also check for a fragment header before the final
6058*d56f51eaSDavid van Moolenbroek * header.
6059*d56f51eaSDavid van Moolenbroek */
6060*d56f51eaSDavid van Moolenbroek b2 = gen_cmp(OR_LINKPL, 6, BPF_B, IPPROTO_FRAGMENT);
6061*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LINKPL, 40, BPF_B, (bpf_int32)v);
6062*d56f51eaSDavid van Moolenbroek gen_and(b2, b1);
6063*d56f51eaSDavid van Moolenbroek b2 = gen_cmp(OR_LINKPL, 6, BPF_B, (bpf_int32)v);
6064*d56f51eaSDavid van Moolenbroek gen_or(b2, b1);
6065*d56f51eaSDavid van Moolenbroek #else
6066*d56f51eaSDavid van Moolenbroek b1 = gen_protochain(v, Q_IPV6);
6067*d56f51eaSDavid van Moolenbroek #endif
6068*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
6069*d56f51eaSDavid van Moolenbroek return b1;
6070*d56f51eaSDavid van Moolenbroek
6071*d56f51eaSDavid van Moolenbroek case Q_ICMPV6:
6072*d56f51eaSDavid van Moolenbroek bpf_error("'icmp6 proto' is bogus");
6073*d56f51eaSDavid van Moolenbroek
6074*d56f51eaSDavid van Moolenbroek case Q_AH:
6075*d56f51eaSDavid van Moolenbroek bpf_error("'ah proto' is bogus");
6076*d56f51eaSDavid van Moolenbroek
6077*d56f51eaSDavid van Moolenbroek case Q_ESP:
6078*d56f51eaSDavid van Moolenbroek bpf_error("'ah proto' is bogus");
6079*d56f51eaSDavid van Moolenbroek
6080*d56f51eaSDavid van Moolenbroek case Q_STP:
6081*d56f51eaSDavid van Moolenbroek bpf_error("'stp proto' is bogus");
6082*d56f51eaSDavid van Moolenbroek
6083*d56f51eaSDavid van Moolenbroek case Q_IPX:
6084*d56f51eaSDavid van Moolenbroek bpf_error("'ipx proto' is bogus");
6085*d56f51eaSDavid van Moolenbroek
6086*d56f51eaSDavid van Moolenbroek case Q_NETBEUI:
6087*d56f51eaSDavid van Moolenbroek bpf_error("'netbeui proto' is bogus");
6088*d56f51eaSDavid van Moolenbroek
6089*d56f51eaSDavid van Moolenbroek case Q_RADIO:
6090*d56f51eaSDavid van Moolenbroek bpf_error("'radio proto' is bogus");
6091*d56f51eaSDavid van Moolenbroek
6092*d56f51eaSDavid van Moolenbroek default:
6093*d56f51eaSDavid van Moolenbroek abort();
6094*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6095*d56f51eaSDavid van Moolenbroek }
6096*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6097*d56f51eaSDavid van Moolenbroek }
6098*d56f51eaSDavid van Moolenbroek
6099*d56f51eaSDavid van Moolenbroek struct block *
gen_scode(name,q)6100*d56f51eaSDavid van Moolenbroek gen_scode(name, q)
6101*d56f51eaSDavid van Moolenbroek register const char *name;
6102*d56f51eaSDavid van Moolenbroek struct qual q;
6103*d56f51eaSDavid van Moolenbroek {
6104*d56f51eaSDavid van Moolenbroek int proto = q.proto;
6105*d56f51eaSDavid van Moolenbroek int dir = q.dir;
6106*d56f51eaSDavid van Moolenbroek int tproto;
6107*d56f51eaSDavid van Moolenbroek u_char *eaddr;
6108*d56f51eaSDavid van Moolenbroek bpf_u_int32 mask, addr;
6109*d56f51eaSDavid van Moolenbroek #ifndef INET6
6110*d56f51eaSDavid van Moolenbroek bpf_u_int32 **alist;
6111*d56f51eaSDavid van Moolenbroek #else
6112*d56f51eaSDavid van Moolenbroek int tproto6;
6113*d56f51eaSDavid van Moolenbroek struct sockaddr_in *sin4;
6114*d56f51eaSDavid van Moolenbroek struct sockaddr_in6 *sin6;
6115*d56f51eaSDavid van Moolenbroek struct addrinfo *res, *res0;
6116*d56f51eaSDavid van Moolenbroek struct in6_addr mask128;
6117*d56f51eaSDavid van Moolenbroek #endif /*INET6*/
6118*d56f51eaSDavid van Moolenbroek struct block *b, *tmp;
6119*d56f51eaSDavid van Moolenbroek int port, real_proto;
6120*d56f51eaSDavid van Moolenbroek int port1, port2;
6121*d56f51eaSDavid van Moolenbroek
6122*d56f51eaSDavid van Moolenbroek switch (q.addr) {
6123*d56f51eaSDavid van Moolenbroek
6124*d56f51eaSDavid van Moolenbroek case Q_NET:
6125*d56f51eaSDavid van Moolenbroek addr = pcap_nametonetaddr(name);
6126*d56f51eaSDavid van Moolenbroek if (addr == 0)
6127*d56f51eaSDavid van Moolenbroek bpf_error("unknown network '%s'", name);
6128*d56f51eaSDavid van Moolenbroek /* Left justify network addr and calculate its network mask */
6129*d56f51eaSDavid van Moolenbroek mask = 0xffffffff;
6130*d56f51eaSDavid van Moolenbroek while (addr && (addr & 0xff000000) == 0) {
6131*d56f51eaSDavid van Moolenbroek addr <<= 8;
6132*d56f51eaSDavid van Moolenbroek mask <<= 8;
6133*d56f51eaSDavid van Moolenbroek }
6134*d56f51eaSDavid van Moolenbroek return gen_host(addr, mask, proto, dir, q.addr);
6135*d56f51eaSDavid van Moolenbroek
6136*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
6137*d56f51eaSDavid van Moolenbroek case Q_HOST:
6138*d56f51eaSDavid van Moolenbroek if (proto == Q_LINK) {
6139*d56f51eaSDavid van Moolenbroek switch (linktype) {
6140*d56f51eaSDavid van Moolenbroek
6141*d56f51eaSDavid van Moolenbroek case DLT_EN10MB:
6142*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER:
6143*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER_TRANSPARENT:
6144*d56f51eaSDavid van Moolenbroek eaddr = pcap_ether_hostton(name);
6145*d56f51eaSDavid van Moolenbroek if (eaddr == NULL)
6146*d56f51eaSDavid van Moolenbroek bpf_error(
6147*d56f51eaSDavid van Moolenbroek "unknown ether host '%s'", name);
6148*d56f51eaSDavid van Moolenbroek tmp = gen_prevlinkhdr_check();
6149*d56f51eaSDavid van Moolenbroek b = gen_ehostop(eaddr, dir);
6150*d56f51eaSDavid van Moolenbroek if (tmp != NULL)
6151*d56f51eaSDavid van Moolenbroek gen_and(tmp, b);
6152*d56f51eaSDavid van Moolenbroek free(eaddr);
6153*d56f51eaSDavid van Moolenbroek return b;
6154*d56f51eaSDavid van Moolenbroek
6155*d56f51eaSDavid van Moolenbroek case DLT_FDDI:
6156*d56f51eaSDavid van Moolenbroek eaddr = pcap_ether_hostton(name);
6157*d56f51eaSDavid van Moolenbroek if (eaddr == NULL)
6158*d56f51eaSDavid van Moolenbroek bpf_error(
6159*d56f51eaSDavid van Moolenbroek "unknown FDDI host '%s'", name);
6160*d56f51eaSDavid van Moolenbroek b = gen_fhostop(eaddr, dir);
6161*d56f51eaSDavid van Moolenbroek free(eaddr);
6162*d56f51eaSDavid van Moolenbroek return b;
6163*d56f51eaSDavid van Moolenbroek
6164*d56f51eaSDavid van Moolenbroek case DLT_IEEE802:
6165*d56f51eaSDavid van Moolenbroek eaddr = pcap_ether_hostton(name);
6166*d56f51eaSDavid van Moolenbroek if (eaddr == NULL)
6167*d56f51eaSDavid van Moolenbroek bpf_error(
6168*d56f51eaSDavid van Moolenbroek "unknown token ring host '%s'", name);
6169*d56f51eaSDavid van Moolenbroek b = gen_thostop(eaddr, dir);
6170*d56f51eaSDavid van Moolenbroek free(eaddr);
6171*d56f51eaSDavid van Moolenbroek return b;
6172*d56f51eaSDavid van Moolenbroek
6173*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11:
6174*d56f51eaSDavid van Moolenbroek case DLT_PRISM_HEADER:
6175*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO_AVS:
6176*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO:
6177*d56f51eaSDavid van Moolenbroek case DLT_PPI:
6178*d56f51eaSDavid van Moolenbroek eaddr = pcap_ether_hostton(name);
6179*d56f51eaSDavid van Moolenbroek if (eaddr == NULL)
6180*d56f51eaSDavid van Moolenbroek bpf_error(
6181*d56f51eaSDavid van Moolenbroek "unknown 802.11 host '%s'", name);
6182*d56f51eaSDavid van Moolenbroek b = gen_wlanhostop(eaddr, dir);
6183*d56f51eaSDavid van Moolenbroek free(eaddr);
6184*d56f51eaSDavid van Moolenbroek return b;
6185*d56f51eaSDavid van Moolenbroek
6186*d56f51eaSDavid van Moolenbroek case DLT_IP_OVER_FC:
6187*d56f51eaSDavid van Moolenbroek eaddr = pcap_ether_hostton(name);
6188*d56f51eaSDavid van Moolenbroek if (eaddr == NULL)
6189*d56f51eaSDavid van Moolenbroek bpf_error(
6190*d56f51eaSDavid van Moolenbroek "unknown Fibre Channel host '%s'", name);
6191*d56f51eaSDavid van Moolenbroek b = gen_ipfchostop(eaddr, dir);
6192*d56f51eaSDavid van Moolenbroek free(eaddr);
6193*d56f51eaSDavid van Moolenbroek return b;
6194*d56f51eaSDavid van Moolenbroek }
6195*d56f51eaSDavid van Moolenbroek
6196*d56f51eaSDavid van Moolenbroek bpf_error("only ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel supports link-level host name");
6197*d56f51eaSDavid van Moolenbroek } else if (proto == Q_DECNET) {
6198*d56f51eaSDavid van Moolenbroek unsigned short dn_addr = __pcap_nametodnaddr(name);
6199*d56f51eaSDavid van Moolenbroek /*
6200*d56f51eaSDavid van Moolenbroek * I don't think DECNET hosts can be multihomed, so
6201*d56f51eaSDavid van Moolenbroek * there is no need to build up a list of addresses
6202*d56f51eaSDavid van Moolenbroek */
6203*d56f51eaSDavid van Moolenbroek return (gen_host(dn_addr, 0, proto, dir, q.addr));
6204*d56f51eaSDavid van Moolenbroek } else {
6205*d56f51eaSDavid van Moolenbroek #ifndef INET6
6206*d56f51eaSDavid van Moolenbroek alist = pcap_nametoaddr(name);
6207*d56f51eaSDavid van Moolenbroek if (alist == NULL || *alist == NULL)
6208*d56f51eaSDavid van Moolenbroek bpf_error("unknown host '%s'", name);
6209*d56f51eaSDavid van Moolenbroek tproto = proto;
6210*d56f51eaSDavid van Moolenbroek if (off_linktype.constant_part == (u_int)-1 &&
6211*d56f51eaSDavid van Moolenbroek tproto == Q_DEFAULT)
6212*d56f51eaSDavid van Moolenbroek tproto = Q_IP;
6213*d56f51eaSDavid van Moolenbroek b = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr);
6214*d56f51eaSDavid van Moolenbroek while (*alist) {
6215*d56f51eaSDavid van Moolenbroek tmp = gen_host(**alist++, 0xffffffff,
6216*d56f51eaSDavid van Moolenbroek tproto, dir, q.addr);
6217*d56f51eaSDavid van Moolenbroek gen_or(b, tmp);
6218*d56f51eaSDavid van Moolenbroek b = tmp;
6219*d56f51eaSDavid van Moolenbroek }
6220*d56f51eaSDavid van Moolenbroek return b;
6221*d56f51eaSDavid van Moolenbroek #else
6222*d56f51eaSDavid van Moolenbroek memset(&mask128, 0xff, sizeof(mask128));
6223*d56f51eaSDavid van Moolenbroek res0 = res = pcap_nametoaddrinfo(name);
6224*d56f51eaSDavid van Moolenbroek if (res == NULL)
6225*d56f51eaSDavid van Moolenbroek bpf_error("unknown host '%s'", name);
6226*d56f51eaSDavid van Moolenbroek ai = res;
6227*d56f51eaSDavid van Moolenbroek b = tmp = NULL;
6228*d56f51eaSDavid van Moolenbroek tproto = tproto6 = proto;
6229*d56f51eaSDavid van Moolenbroek if (off_linktype.constant_part == (u_int)-1 &&
6230*d56f51eaSDavid van Moolenbroek tproto == Q_DEFAULT) {
6231*d56f51eaSDavid van Moolenbroek tproto = Q_IP;
6232*d56f51eaSDavid van Moolenbroek tproto6 = Q_IPV6;
6233*d56f51eaSDavid van Moolenbroek }
6234*d56f51eaSDavid van Moolenbroek for (res = res0; res; res = res->ai_next) {
6235*d56f51eaSDavid van Moolenbroek switch (res->ai_family) {
6236*d56f51eaSDavid van Moolenbroek case AF_INET:
6237*d56f51eaSDavid van Moolenbroek if (tproto == Q_IPV6)
6238*d56f51eaSDavid van Moolenbroek continue;
6239*d56f51eaSDavid van Moolenbroek
6240*d56f51eaSDavid van Moolenbroek sin4 = (struct sockaddr_in *)
6241*d56f51eaSDavid van Moolenbroek res->ai_addr;
6242*d56f51eaSDavid van Moolenbroek tmp = gen_host(ntohl(sin4->sin_addr.s_addr),
6243*d56f51eaSDavid van Moolenbroek 0xffffffff, tproto, dir, q.addr);
6244*d56f51eaSDavid van Moolenbroek break;
6245*d56f51eaSDavid van Moolenbroek case AF_INET6:
6246*d56f51eaSDavid van Moolenbroek if (tproto6 == Q_IP)
6247*d56f51eaSDavid van Moolenbroek continue;
6248*d56f51eaSDavid van Moolenbroek
6249*d56f51eaSDavid van Moolenbroek sin6 = (struct sockaddr_in6 *)
6250*d56f51eaSDavid van Moolenbroek res->ai_addr;
6251*d56f51eaSDavid van Moolenbroek tmp = gen_host6(&sin6->sin6_addr,
6252*d56f51eaSDavid van Moolenbroek &mask128, tproto6, dir, q.addr);
6253*d56f51eaSDavid van Moolenbroek break;
6254*d56f51eaSDavid van Moolenbroek default:
6255*d56f51eaSDavid van Moolenbroek continue;
6256*d56f51eaSDavid van Moolenbroek }
6257*d56f51eaSDavid van Moolenbroek if (b)
6258*d56f51eaSDavid van Moolenbroek gen_or(b, tmp);
6259*d56f51eaSDavid van Moolenbroek b = tmp;
6260*d56f51eaSDavid van Moolenbroek }
6261*d56f51eaSDavid van Moolenbroek ai = NULL;
6262*d56f51eaSDavid van Moolenbroek freeaddrinfo(res0);
6263*d56f51eaSDavid van Moolenbroek if (b == NULL) {
6264*d56f51eaSDavid van Moolenbroek bpf_error("unknown host '%s'%s", name,
6265*d56f51eaSDavid van Moolenbroek (proto == Q_DEFAULT)
6266*d56f51eaSDavid van Moolenbroek ? ""
6267*d56f51eaSDavid van Moolenbroek : " for specified address family");
6268*d56f51eaSDavid van Moolenbroek }
6269*d56f51eaSDavid van Moolenbroek return b;
6270*d56f51eaSDavid van Moolenbroek #endif /*INET6*/
6271*d56f51eaSDavid van Moolenbroek }
6272*d56f51eaSDavid van Moolenbroek
6273*d56f51eaSDavid van Moolenbroek case Q_PORT:
6274*d56f51eaSDavid van Moolenbroek if (proto != Q_DEFAULT &&
6275*d56f51eaSDavid van Moolenbroek proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
6276*d56f51eaSDavid van Moolenbroek bpf_error("illegal qualifier of 'port'");
6277*d56f51eaSDavid van Moolenbroek if (pcap_nametoport(name, &port, &real_proto) == 0)
6278*d56f51eaSDavid van Moolenbroek bpf_error("unknown port '%s'", name);
6279*d56f51eaSDavid van Moolenbroek if (proto == Q_UDP) {
6280*d56f51eaSDavid van Moolenbroek if (real_proto == IPPROTO_TCP)
6281*d56f51eaSDavid van Moolenbroek bpf_error("port '%s' is tcp", name);
6282*d56f51eaSDavid van Moolenbroek else if (real_proto == IPPROTO_SCTP)
6283*d56f51eaSDavid van Moolenbroek bpf_error("port '%s' is sctp", name);
6284*d56f51eaSDavid van Moolenbroek else
6285*d56f51eaSDavid van Moolenbroek /* override PROTO_UNDEF */
6286*d56f51eaSDavid van Moolenbroek real_proto = IPPROTO_UDP;
6287*d56f51eaSDavid van Moolenbroek }
6288*d56f51eaSDavid van Moolenbroek if (proto == Q_TCP) {
6289*d56f51eaSDavid van Moolenbroek if (real_proto == IPPROTO_UDP)
6290*d56f51eaSDavid van Moolenbroek bpf_error("port '%s' is udp", name);
6291*d56f51eaSDavid van Moolenbroek
6292*d56f51eaSDavid van Moolenbroek else if (real_proto == IPPROTO_SCTP)
6293*d56f51eaSDavid van Moolenbroek bpf_error("port '%s' is sctp", name);
6294*d56f51eaSDavid van Moolenbroek else
6295*d56f51eaSDavid van Moolenbroek /* override PROTO_UNDEF */
6296*d56f51eaSDavid van Moolenbroek real_proto = IPPROTO_TCP;
6297*d56f51eaSDavid van Moolenbroek }
6298*d56f51eaSDavid van Moolenbroek if (proto == Q_SCTP) {
6299*d56f51eaSDavid van Moolenbroek if (real_proto == IPPROTO_UDP)
6300*d56f51eaSDavid van Moolenbroek bpf_error("port '%s' is udp", name);
6301*d56f51eaSDavid van Moolenbroek
6302*d56f51eaSDavid van Moolenbroek else if (real_proto == IPPROTO_TCP)
6303*d56f51eaSDavid van Moolenbroek bpf_error("port '%s' is tcp", name);
6304*d56f51eaSDavid van Moolenbroek else
6305*d56f51eaSDavid van Moolenbroek /* override PROTO_UNDEF */
6306*d56f51eaSDavid van Moolenbroek real_proto = IPPROTO_SCTP;
6307*d56f51eaSDavid van Moolenbroek }
6308*d56f51eaSDavid van Moolenbroek if (port < 0)
6309*d56f51eaSDavid van Moolenbroek bpf_error("illegal port number %d < 0", port);
6310*d56f51eaSDavid van Moolenbroek if (port > 65535)
6311*d56f51eaSDavid van Moolenbroek bpf_error("illegal port number %d > 65535", port);
6312*d56f51eaSDavid van Moolenbroek b = gen_port(port, real_proto, dir);
6313*d56f51eaSDavid van Moolenbroek gen_or(gen_port6(port, real_proto, dir), b);
6314*d56f51eaSDavid van Moolenbroek return b;
6315*d56f51eaSDavid van Moolenbroek
6316*d56f51eaSDavid van Moolenbroek case Q_PORTRANGE:
6317*d56f51eaSDavid van Moolenbroek if (proto != Q_DEFAULT &&
6318*d56f51eaSDavid van Moolenbroek proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
6319*d56f51eaSDavid van Moolenbroek bpf_error("illegal qualifier of 'portrange'");
6320*d56f51eaSDavid van Moolenbroek if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0)
6321*d56f51eaSDavid van Moolenbroek bpf_error("unknown port in range '%s'", name);
6322*d56f51eaSDavid van Moolenbroek if (proto == Q_UDP) {
6323*d56f51eaSDavid van Moolenbroek if (real_proto == IPPROTO_TCP)
6324*d56f51eaSDavid van Moolenbroek bpf_error("port in range '%s' is tcp", name);
6325*d56f51eaSDavid van Moolenbroek else if (real_proto == IPPROTO_SCTP)
6326*d56f51eaSDavid van Moolenbroek bpf_error("port in range '%s' is sctp", name);
6327*d56f51eaSDavid van Moolenbroek else
6328*d56f51eaSDavid van Moolenbroek /* override PROTO_UNDEF */
6329*d56f51eaSDavid van Moolenbroek real_proto = IPPROTO_UDP;
6330*d56f51eaSDavid van Moolenbroek }
6331*d56f51eaSDavid van Moolenbroek if (proto == Q_TCP) {
6332*d56f51eaSDavid van Moolenbroek if (real_proto == IPPROTO_UDP)
6333*d56f51eaSDavid van Moolenbroek bpf_error("port in range '%s' is udp", name);
6334*d56f51eaSDavid van Moolenbroek else if (real_proto == IPPROTO_SCTP)
6335*d56f51eaSDavid van Moolenbroek bpf_error("port in range '%s' is sctp", name);
6336*d56f51eaSDavid van Moolenbroek else
6337*d56f51eaSDavid van Moolenbroek /* override PROTO_UNDEF */
6338*d56f51eaSDavid van Moolenbroek real_proto = IPPROTO_TCP;
6339*d56f51eaSDavid van Moolenbroek }
6340*d56f51eaSDavid van Moolenbroek if (proto == Q_SCTP) {
6341*d56f51eaSDavid van Moolenbroek if (real_proto == IPPROTO_UDP)
6342*d56f51eaSDavid van Moolenbroek bpf_error("port in range '%s' is udp", name);
6343*d56f51eaSDavid van Moolenbroek else if (real_proto == IPPROTO_TCP)
6344*d56f51eaSDavid van Moolenbroek bpf_error("port in range '%s' is tcp", name);
6345*d56f51eaSDavid van Moolenbroek else
6346*d56f51eaSDavid van Moolenbroek /* override PROTO_UNDEF */
6347*d56f51eaSDavid van Moolenbroek real_proto = IPPROTO_SCTP;
6348*d56f51eaSDavid van Moolenbroek }
6349*d56f51eaSDavid van Moolenbroek if (port1 < 0)
6350*d56f51eaSDavid van Moolenbroek bpf_error("illegal port number %d < 0", port1);
6351*d56f51eaSDavid van Moolenbroek if (port1 > 65535)
6352*d56f51eaSDavid van Moolenbroek bpf_error("illegal port number %d > 65535", port1);
6353*d56f51eaSDavid van Moolenbroek if (port2 < 0)
6354*d56f51eaSDavid van Moolenbroek bpf_error("illegal port number %d < 0", port2);
6355*d56f51eaSDavid van Moolenbroek if (port2 > 65535)
6356*d56f51eaSDavid van Moolenbroek bpf_error("illegal port number %d > 65535", port2);
6357*d56f51eaSDavid van Moolenbroek
6358*d56f51eaSDavid van Moolenbroek b = gen_portrange(port1, port2, real_proto, dir);
6359*d56f51eaSDavid van Moolenbroek gen_or(gen_portrange6(port1, port2, real_proto, dir), b);
6360*d56f51eaSDavid van Moolenbroek return b;
6361*d56f51eaSDavid van Moolenbroek
6362*d56f51eaSDavid van Moolenbroek case Q_GATEWAY:
6363*d56f51eaSDavid van Moolenbroek #ifndef INET6
6364*d56f51eaSDavid van Moolenbroek eaddr = pcap_ether_hostton(name);
6365*d56f51eaSDavid van Moolenbroek if (eaddr == NULL)
6366*d56f51eaSDavid van Moolenbroek bpf_error("unknown ether host: %s", name);
6367*d56f51eaSDavid van Moolenbroek
6368*d56f51eaSDavid van Moolenbroek alist = pcap_nametoaddr(name);
6369*d56f51eaSDavid van Moolenbroek if (alist == NULL || *alist == NULL)
6370*d56f51eaSDavid van Moolenbroek bpf_error("unknown host '%s'", name);
6371*d56f51eaSDavid van Moolenbroek b = gen_gateway(eaddr, alist, proto, dir);
6372*d56f51eaSDavid van Moolenbroek free(eaddr);
6373*d56f51eaSDavid van Moolenbroek return b;
6374*d56f51eaSDavid van Moolenbroek #else
6375*d56f51eaSDavid van Moolenbroek bpf_error("'gateway' not supported in this configuration");
6376*d56f51eaSDavid van Moolenbroek #endif /*INET6*/
6377*d56f51eaSDavid van Moolenbroek
6378*d56f51eaSDavid van Moolenbroek case Q_PROTO:
6379*d56f51eaSDavid van Moolenbroek real_proto = lookup_proto(name, proto);
6380*d56f51eaSDavid van Moolenbroek if (real_proto >= 0)
6381*d56f51eaSDavid van Moolenbroek return gen_proto(real_proto, proto, dir);
6382*d56f51eaSDavid van Moolenbroek else
6383*d56f51eaSDavid van Moolenbroek bpf_error("unknown protocol: %s", name);
6384*d56f51eaSDavid van Moolenbroek
6385*d56f51eaSDavid van Moolenbroek case Q_PROTOCHAIN:
6386*d56f51eaSDavid van Moolenbroek real_proto = lookup_proto(name, proto);
6387*d56f51eaSDavid van Moolenbroek if (real_proto >= 0)
6388*d56f51eaSDavid van Moolenbroek return gen_protochain(real_proto, proto, dir);
6389*d56f51eaSDavid van Moolenbroek else
6390*d56f51eaSDavid van Moolenbroek bpf_error("unknown protocol: %s", name);
6391*d56f51eaSDavid van Moolenbroek
6392*d56f51eaSDavid van Moolenbroek case Q_UNDEF:
6393*d56f51eaSDavid van Moolenbroek syntax();
6394*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6395*d56f51eaSDavid van Moolenbroek }
6396*d56f51eaSDavid van Moolenbroek abort();
6397*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6398*d56f51eaSDavid van Moolenbroek }
6399*d56f51eaSDavid van Moolenbroek
6400*d56f51eaSDavid van Moolenbroek struct block *
gen_mcode(s1,s2,masklen,q)6401*d56f51eaSDavid van Moolenbroek gen_mcode(s1, s2, masklen, q)
6402*d56f51eaSDavid van Moolenbroek register const char *s1, *s2;
6403*d56f51eaSDavid van Moolenbroek register unsigned int masklen;
6404*d56f51eaSDavid van Moolenbroek struct qual q;
6405*d56f51eaSDavid van Moolenbroek {
6406*d56f51eaSDavid van Moolenbroek register int nlen, mlen;
6407*d56f51eaSDavid van Moolenbroek bpf_u_int32 n, m;
6408*d56f51eaSDavid van Moolenbroek
6409*d56f51eaSDavid van Moolenbroek nlen = __pcap_atoin(s1, &n);
6410*d56f51eaSDavid van Moolenbroek /* Promote short ipaddr */
6411*d56f51eaSDavid van Moolenbroek n <<= 32 - nlen;
6412*d56f51eaSDavid van Moolenbroek
6413*d56f51eaSDavid van Moolenbroek if (s2 != NULL) {
6414*d56f51eaSDavid van Moolenbroek mlen = __pcap_atoin(s2, &m);
6415*d56f51eaSDavid van Moolenbroek /* Promote short ipaddr */
6416*d56f51eaSDavid van Moolenbroek m <<= 32 - mlen;
6417*d56f51eaSDavid van Moolenbroek if ((n & ~m) != 0)
6418*d56f51eaSDavid van Moolenbroek bpf_error("non-network bits set in \"%s mask %s\"",
6419*d56f51eaSDavid van Moolenbroek s1, s2);
6420*d56f51eaSDavid van Moolenbroek } else {
6421*d56f51eaSDavid van Moolenbroek /* Convert mask len to mask */
6422*d56f51eaSDavid van Moolenbroek if (masklen > 32)
6423*d56f51eaSDavid van Moolenbroek bpf_error("mask length must be <= 32");
6424*d56f51eaSDavid van Moolenbroek if (masklen == 0) {
6425*d56f51eaSDavid van Moolenbroek /*
6426*d56f51eaSDavid van Moolenbroek * X << 32 is not guaranteed by C to be 0; it's
6427*d56f51eaSDavid van Moolenbroek * undefined.
6428*d56f51eaSDavid van Moolenbroek */
6429*d56f51eaSDavid van Moolenbroek m = 0;
6430*d56f51eaSDavid van Moolenbroek } else
6431*d56f51eaSDavid van Moolenbroek m = 0xffffffff << (32 - masklen);
6432*d56f51eaSDavid van Moolenbroek if ((n & ~m) != 0)
6433*d56f51eaSDavid van Moolenbroek bpf_error("non-network bits set in \"%s/%d\"",
6434*d56f51eaSDavid van Moolenbroek s1, masklen);
6435*d56f51eaSDavid van Moolenbroek }
6436*d56f51eaSDavid van Moolenbroek
6437*d56f51eaSDavid van Moolenbroek switch (q.addr) {
6438*d56f51eaSDavid van Moolenbroek
6439*d56f51eaSDavid van Moolenbroek case Q_NET:
6440*d56f51eaSDavid van Moolenbroek return gen_host(n, m, q.proto, q.dir, q.addr);
6441*d56f51eaSDavid van Moolenbroek
6442*d56f51eaSDavid van Moolenbroek default:
6443*d56f51eaSDavid van Moolenbroek bpf_error("Mask syntax for networks only");
6444*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6445*d56f51eaSDavid van Moolenbroek }
6446*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6447*d56f51eaSDavid van Moolenbroek return NULL;
6448*d56f51eaSDavid van Moolenbroek }
6449*d56f51eaSDavid van Moolenbroek
6450*d56f51eaSDavid van Moolenbroek struct block *
gen_ncode(s,v,q)6451*d56f51eaSDavid van Moolenbroek gen_ncode(s, v, q)
6452*d56f51eaSDavid van Moolenbroek register const char *s;
6453*d56f51eaSDavid van Moolenbroek bpf_u_int32 v;
6454*d56f51eaSDavid van Moolenbroek struct qual q;
6455*d56f51eaSDavid van Moolenbroek {
6456*d56f51eaSDavid van Moolenbroek bpf_u_int32 mask;
6457*d56f51eaSDavid van Moolenbroek int proto = q.proto;
6458*d56f51eaSDavid van Moolenbroek int dir = q.dir;
6459*d56f51eaSDavid van Moolenbroek register int vlen;
6460*d56f51eaSDavid van Moolenbroek
6461*d56f51eaSDavid van Moolenbroek if (s == NULL)
6462*d56f51eaSDavid van Moolenbroek vlen = 32;
6463*d56f51eaSDavid van Moolenbroek else if (q.proto == Q_DECNET)
6464*d56f51eaSDavid van Moolenbroek vlen = __pcap_atodn(s, &v);
6465*d56f51eaSDavid van Moolenbroek else
6466*d56f51eaSDavid van Moolenbroek vlen = __pcap_atoin(s, &v);
6467*d56f51eaSDavid van Moolenbroek
6468*d56f51eaSDavid van Moolenbroek switch (q.addr) {
6469*d56f51eaSDavid van Moolenbroek
6470*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
6471*d56f51eaSDavid van Moolenbroek case Q_HOST:
6472*d56f51eaSDavid van Moolenbroek case Q_NET:
6473*d56f51eaSDavid van Moolenbroek if (proto == Q_DECNET)
6474*d56f51eaSDavid van Moolenbroek return gen_host(v, 0, proto, dir, q.addr);
6475*d56f51eaSDavid van Moolenbroek else if (proto == Q_LINK) {
6476*d56f51eaSDavid van Moolenbroek bpf_error("illegal link layer address");
6477*d56f51eaSDavid van Moolenbroek } else {
6478*d56f51eaSDavid van Moolenbroek mask = 0xffffffff;
6479*d56f51eaSDavid van Moolenbroek if (s == NULL && q.addr == Q_NET) {
6480*d56f51eaSDavid van Moolenbroek /* Promote short net number */
6481*d56f51eaSDavid van Moolenbroek while (v && (v & 0xff000000) == 0) {
6482*d56f51eaSDavid van Moolenbroek v <<= 8;
6483*d56f51eaSDavid van Moolenbroek mask <<= 8;
6484*d56f51eaSDavid van Moolenbroek }
6485*d56f51eaSDavid van Moolenbroek } else {
6486*d56f51eaSDavid van Moolenbroek /* Promote short ipaddr */
6487*d56f51eaSDavid van Moolenbroek v <<= 32 - vlen;
6488*d56f51eaSDavid van Moolenbroek mask <<= 32 - vlen;
6489*d56f51eaSDavid van Moolenbroek }
6490*d56f51eaSDavid van Moolenbroek return gen_host(v, mask, proto, dir, q.addr);
6491*d56f51eaSDavid van Moolenbroek }
6492*d56f51eaSDavid van Moolenbroek
6493*d56f51eaSDavid van Moolenbroek case Q_PORT:
6494*d56f51eaSDavid van Moolenbroek if (proto == Q_UDP)
6495*d56f51eaSDavid van Moolenbroek proto = IPPROTO_UDP;
6496*d56f51eaSDavid van Moolenbroek else if (proto == Q_TCP)
6497*d56f51eaSDavid van Moolenbroek proto = IPPROTO_TCP;
6498*d56f51eaSDavid van Moolenbroek else if (proto == Q_SCTP)
6499*d56f51eaSDavid van Moolenbroek proto = IPPROTO_SCTP;
6500*d56f51eaSDavid van Moolenbroek else if (proto == Q_DEFAULT)
6501*d56f51eaSDavid van Moolenbroek proto = PROTO_UNDEF;
6502*d56f51eaSDavid van Moolenbroek else
6503*d56f51eaSDavid van Moolenbroek bpf_error("illegal qualifier of 'port'");
6504*d56f51eaSDavid van Moolenbroek
6505*d56f51eaSDavid van Moolenbroek if (v > 65535)
6506*d56f51eaSDavid van Moolenbroek bpf_error("illegal port number %u > 65535", v);
6507*d56f51eaSDavid van Moolenbroek
6508*d56f51eaSDavid van Moolenbroek {
6509*d56f51eaSDavid van Moolenbroek struct block *b;
6510*d56f51eaSDavid van Moolenbroek b = gen_port((int)v, proto, dir);
6511*d56f51eaSDavid van Moolenbroek gen_or(gen_port6((int)v, proto, dir), b);
6512*d56f51eaSDavid van Moolenbroek return b;
6513*d56f51eaSDavid van Moolenbroek }
6514*d56f51eaSDavid van Moolenbroek
6515*d56f51eaSDavid van Moolenbroek case Q_PORTRANGE:
6516*d56f51eaSDavid van Moolenbroek if (proto == Q_UDP)
6517*d56f51eaSDavid van Moolenbroek proto = IPPROTO_UDP;
6518*d56f51eaSDavid van Moolenbroek else if (proto == Q_TCP)
6519*d56f51eaSDavid van Moolenbroek proto = IPPROTO_TCP;
6520*d56f51eaSDavid van Moolenbroek else if (proto == Q_SCTP)
6521*d56f51eaSDavid van Moolenbroek proto = IPPROTO_SCTP;
6522*d56f51eaSDavid van Moolenbroek else if (proto == Q_DEFAULT)
6523*d56f51eaSDavid van Moolenbroek proto = PROTO_UNDEF;
6524*d56f51eaSDavid van Moolenbroek else
6525*d56f51eaSDavid van Moolenbroek bpf_error("illegal qualifier of 'portrange'");
6526*d56f51eaSDavid van Moolenbroek
6527*d56f51eaSDavid van Moolenbroek if (v > 65535)
6528*d56f51eaSDavid van Moolenbroek bpf_error("illegal port number %u > 65535", v);
6529*d56f51eaSDavid van Moolenbroek
6530*d56f51eaSDavid van Moolenbroek {
6531*d56f51eaSDavid van Moolenbroek struct block *b;
6532*d56f51eaSDavid van Moolenbroek b = gen_portrange((int)v, (int)v, proto, dir);
6533*d56f51eaSDavid van Moolenbroek gen_or(gen_portrange6((int)v, (int)v, proto, dir), b);
6534*d56f51eaSDavid van Moolenbroek return b;
6535*d56f51eaSDavid van Moolenbroek }
6536*d56f51eaSDavid van Moolenbroek
6537*d56f51eaSDavid van Moolenbroek case Q_GATEWAY:
6538*d56f51eaSDavid van Moolenbroek bpf_error("'gateway' requires a name");
6539*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6540*d56f51eaSDavid van Moolenbroek
6541*d56f51eaSDavid van Moolenbroek case Q_PROTO:
6542*d56f51eaSDavid van Moolenbroek return gen_proto((int)v, proto, dir);
6543*d56f51eaSDavid van Moolenbroek
6544*d56f51eaSDavid van Moolenbroek case Q_PROTOCHAIN:
6545*d56f51eaSDavid van Moolenbroek return gen_protochain((int)v, proto, dir);
6546*d56f51eaSDavid van Moolenbroek
6547*d56f51eaSDavid van Moolenbroek case Q_UNDEF:
6548*d56f51eaSDavid van Moolenbroek syntax();
6549*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6550*d56f51eaSDavid van Moolenbroek
6551*d56f51eaSDavid van Moolenbroek default:
6552*d56f51eaSDavid van Moolenbroek abort();
6553*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6554*d56f51eaSDavid van Moolenbroek }
6555*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6556*d56f51eaSDavid van Moolenbroek }
6557*d56f51eaSDavid van Moolenbroek
6558*d56f51eaSDavid van Moolenbroek #ifdef INET6
6559*d56f51eaSDavid van Moolenbroek struct block *
gen_mcode6(s1,s2,masklen,q)6560*d56f51eaSDavid van Moolenbroek gen_mcode6(s1, s2, masklen, q)
6561*d56f51eaSDavid van Moolenbroek register const char *s1, *s2;
6562*d56f51eaSDavid van Moolenbroek register unsigned int masklen;
6563*d56f51eaSDavid van Moolenbroek struct qual q;
6564*d56f51eaSDavid van Moolenbroek {
6565*d56f51eaSDavid van Moolenbroek struct addrinfo *res;
6566*d56f51eaSDavid van Moolenbroek struct in6_addr *addr;
6567*d56f51eaSDavid van Moolenbroek struct in6_addr mask;
6568*d56f51eaSDavid van Moolenbroek struct block *b;
6569*d56f51eaSDavid van Moolenbroek u_int32_t *a, *m;
6570*d56f51eaSDavid van Moolenbroek
6571*d56f51eaSDavid van Moolenbroek if (s2)
6572*d56f51eaSDavid van Moolenbroek bpf_error("no mask %s supported", s2);
6573*d56f51eaSDavid van Moolenbroek
6574*d56f51eaSDavid van Moolenbroek res = pcap_nametoaddrinfo(s1);
6575*d56f51eaSDavid van Moolenbroek if (!res)
6576*d56f51eaSDavid van Moolenbroek bpf_error("invalid ip6 address %s", s1);
6577*d56f51eaSDavid van Moolenbroek ai = res;
6578*d56f51eaSDavid van Moolenbroek if (res->ai_next)
6579*d56f51eaSDavid van Moolenbroek bpf_error("%s resolved to multiple address", s1);
6580*d56f51eaSDavid van Moolenbroek addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
6581*d56f51eaSDavid van Moolenbroek
6582*d56f51eaSDavid van Moolenbroek if ((int)sizeof(mask) * 8 < masklen)
6583*d56f51eaSDavid van Moolenbroek bpf_error("mask length must be <= %u", (unsigned int)(sizeof(mask) * 8));
6584*d56f51eaSDavid van Moolenbroek memset(&mask, 0, sizeof(mask));
6585*d56f51eaSDavid van Moolenbroek memset(&mask, 0xff, masklen / 8);
6586*d56f51eaSDavid van Moolenbroek if (masklen % 8) {
6587*d56f51eaSDavid van Moolenbroek mask.s6_addr[masklen / 8] =
6588*d56f51eaSDavid van Moolenbroek (0xff << (8 - masklen % 8)) & 0xff;
6589*d56f51eaSDavid van Moolenbroek }
6590*d56f51eaSDavid van Moolenbroek
6591*d56f51eaSDavid van Moolenbroek a = (u_int32_t *)addr;
6592*d56f51eaSDavid van Moolenbroek m = (u_int32_t *)&mask;
6593*d56f51eaSDavid van Moolenbroek if ((a[0] & ~m[0]) || (a[1] & ~m[1])
6594*d56f51eaSDavid van Moolenbroek || (a[2] & ~m[2]) || (a[3] & ~m[3])) {
6595*d56f51eaSDavid van Moolenbroek bpf_error("non-network bits set in \"%s/%d\"", s1, masklen);
6596*d56f51eaSDavid van Moolenbroek }
6597*d56f51eaSDavid van Moolenbroek
6598*d56f51eaSDavid van Moolenbroek switch (q.addr) {
6599*d56f51eaSDavid van Moolenbroek
6600*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
6601*d56f51eaSDavid van Moolenbroek case Q_HOST:
6602*d56f51eaSDavid van Moolenbroek if (masklen != 128)
6603*d56f51eaSDavid van Moolenbroek bpf_error("Mask syntax for networks only");
6604*d56f51eaSDavid van Moolenbroek /* FALLTHROUGH */
6605*d56f51eaSDavid van Moolenbroek
6606*d56f51eaSDavid van Moolenbroek case Q_NET:
6607*d56f51eaSDavid van Moolenbroek b = gen_host6(addr, &mask, q.proto, q.dir, q.addr);
6608*d56f51eaSDavid van Moolenbroek ai = NULL;
6609*d56f51eaSDavid van Moolenbroek freeaddrinfo(res);
6610*d56f51eaSDavid van Moolenbroek return b;
6611*d56f51eaSDavid van Moolenbroek
6612*d56f51eaSDavid van Moolenbroek default:
6613*d56f51eaSDavid van Moolenbroek bpf_error("invalid qualifier against IPv6 address");
6614*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6615*d56f51eaSDavid van Moolenbroek }
6616*d56f51eaSDavid van Moolenbroek return NULL;
6617*d56f51eaSDavid van Moolenbroek }
6618*d56f51eaSDavid van Moolenbroek #endif /*INET6*/
6619*d56f51eaSDavid van Moolenbroek
6620*d56f51eaSDavid van Moolenbroek struct block *
gen_ecode(eaddr,q)6621*d56f51eaSDavid van Moolenbroek gen_ecode(eaddr, q)
6622*d56f51eaSDavid van Moolenbroek register const u_char *eaddr;
6623*d56f51eaSDavid van Moolenbroek struct qual q;
6624*d56f51eaSDavid van Moolenbroek {
6625*d56f51eaSDavid van Moolenbroek struct block *b, *tmp;
6626*d56f51eaSDavid van Moolenbroek
6627*d56f51eaSDavid van Moolenbroek if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
6628*d56f51eaSDavid van Moolenbroek switch (linktype) {
6629*d56f51eaSDavid van Moolenbroek case DLT_EN10MB:
6630*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER:
6631*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER_TRANSPARENT:
6632*d56f51eaSDavid van Moolenbroek tmp = gen_prevlinkhdr_check();
6633*d56f51eaSDavid van Moolenbroek b = gen_ehostop(eaddr, (int)q.dir);
6634*d56f51eaSDavid van Moolenbroek if (tmp != NULL)
6635*d56f51eaSDavid van Moolenbroek gen_and(tmp, b);
6636*d56f51eaSDavid van Moolenbroek return b;
6637*d56f51eaSDavid van Moolenbroek case DLT_FDDI:
6638*d56f51eaSDavid van Moolenbroek return gen_fhostop(eaddr, (int)q.dir);
6639*d56f51eaSDavid van Moolenbroek case DLT_IEEE802:
6640*d56f51eaSDavid van Moolenbroek return gen_thostop(eaddr, (int)q.dir);
6641*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11:
6642*d56f51eaSDavid van Moolenbroek case DLT_PRISM_HEADER:
6643*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO_AVS:
6644*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO:
6645*d56f51eaSDavid van Moolenbroek case DLT_PPI:
6646*d56f51eaSDavid van Moolenbroek return gen_wlanhostop(eaddr, (int)q.dir);
6647*d56f51eaSDavid van Moolenbroek case DLT_IP_OVER_FC:
6648*d56f51eaSDavid van Moolenbroek return gen_ipfchostop(eaddr, (int)q.dir);
6649*d56f51eaSDavid van Moolenbroek default:
6650*d56f51eaSDavid van Moolenbroek bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
6651*d56f51eaSDavid van Moolenbroek break;
6652*d56f51eaSDavid van Moolenbroek }
6653*d56f51eaSDavid van Moolenbroek }
6654*d56f51eaSDavid van Moolenbroek bpf_error("ethernet address used in non-ether expression");
6655*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
6656*d56f51eaSDavid van Moolenbroek return NULL;
6657*d56f51eaSDavid van Moolenbroek }
6658*d56f51eaSDavid van Moolenbroek
6659*d56f51eaSDavid van Moolenbroek void
sappend(s0,s1)6660*d56f51eaSDavid van Moolenbroek sappend(s0, s1)
6661*d56f51eaSDavid van Moolenbroek struct slist *s0, *s1;
6662*d56f51eaSDavid van Moolenbroek {
6663*d56f51eaSDavid van Moolenbroek /*
6664*d56f51eaSDavid van Moolenbroek * This is definitely not the best way to do this, but the
6665*d56f51eaSDavid van Moolenbroek * lists will rarely get long.
6666*d56f51eaSDavid van Moolenbroek */
6667*d56f51eaSDavid van Moolenbroek while (s0->next)
6668*d56f51eaSDavid van Moolenbroek s0 = s0->next;
6669*d56f51eaSDavid van Moolenbroek s0->next = s1;
6670*d56f51eaSDavid van Moolenbroek }
6671*d56f51eaSDavid van Moolenbroek
6672*d56f51eaSDavid van Moolenbroek static struct slist *
xfer_to_x(a)6673*d56f51eaSDavid van Moolenbroek xfer_to_x(a)
6674*d56f51eaSDavid van Moolenbroek struct arth *a;
6675*d56f51eaSDavid van Moolenbroek {
6676*d56f51eaSDavid van Moolenbroek struct slist *s;
6677*d56f51eaSDavid van Moolenbroek
6678*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_LDX|BPF_MEM);
6679*d56f51eaSDavid van Moolenbroek s->s.k = a->regno;
6680*d56f51eaSDavid van Moolenbroek return s;
6681*d56f51eaSDavid van Moolenbroek }
6682*d56f51eaSDavid van Moolenbroek
6683*d56f51eaSDavid van Moolenbroek static struct slist *
xfer_to_a(a)6684*d56f51eaSDavid van Moolenbroek xfer_to_a(a)
6685*d56f51eaSDavid van Moolenbroek struct arth *a;
6686*d56f51eaSDavid van Moolenbroek {
6687*d56f51eaSDavid van Moolenbroek struct slist *s;
6688*d56f51eaSDavid van Moolenbroek
6689*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_LD|BPF_MEM);
6690*d56f51eaSDavid van Moolenbroek s->s.k = a->regno;
6691*d56f51eaSDavid van Moolenbroek return s;
6692*d56f51eaSDavid van Moolenbroek }
6693*d56f51eaSDavid van Moolenbroek
6694*d56f51eaSDavid van Moolenbroek /*
6695*d56f51eaSDavid van Moolenbroek * Modify "index" to use the value stored into its register as an
6696*d56f51eaSDavid van Moolenbroek * offset relative to the beginning of the header for the protocol
6697*d56f51eaSDavid van Moolenbroek * "proto", and allocate a register and put an item "size" bytes long
6698*d56f51eaSDavid van Moolenbroek * (1, 2, or 4) at that offset into that register, making it the register
6699*d56f51eaSDavid van Moolenbroek * for "index".
6700*d56f51eaSDavid van Moolenbroek */
6701*d56f51eaSDavid van Moolenbroek struct arth *
gen_load(proto,inst,size)6702*d56f51eaSDavid van Moolenbroek gen_load(proto, inst, size)
6703*d56f51eaSDavid van Moolenbroek int proto;
6704*d56f51eaSDavid van Moolenbroek struct arth *inst;
6705*d56f51eaSDavid van Moolenbroek int size;
6706*d56f51eaSDavid van Moolenbroek {
6707*d56f51eaSDavid van Moolenbroek struct slist *s, *tmp;
6708*d56f51eaSDavid van Moolenbroek struct block *b;
6709*d56f51eaSDavid van Moolenbroek int regno = alloc_reg();
6710*d56f51eaSDavid van Moolenbroek
6711*d56f51eaSDavid van Moolenbroek free_reg(inst->regno);
6712*d56f51eaSDavid van Moolenbroek switch (size) {
6713*d56f51eaSDavid van Moolenbroek
6714*d56f51eaSDavid van Moolenbroek default:
6715*d56f51eaSDavid van Moolenbroek bpf_error("data size must be 1, 2, or 4");
6716*d56f51eaSDavid van Moolenbroek
6717*d56f51eaSDavid van Moolenbroek case 1:
6718*d56f51eaSDavid van Moolenbroek size = BPF_B;
6719*d56f51eaSDavid van Moolenbroek break;
6720*d56f51eaSDavid van Moolenbroek
6721*d56f51eaSDavid van Moolenbroek case 2:
6722*d56f51eaSDavid van Moolenbroek size = BPF_H;
6723*d56f51eaSDavid van Moolenbroek break;
6724*d56f51eaSDavid van Moolenbroek
6725*d56f51eaSDavid van Moolenbroek case 4:
6726*d56f51eaSDavid van Moolenbroek size = BPF_W;
6727*d56f51eaSDavid van Moolenbroek break;
6728*d56f51eaSDavid van Moolenbroek }
6729*d56f51eaSDavid van Moolenbroek switch (proto) {
6730*d56f51eaSDavid van Moolenbroek default:
6731*d56f51eaSDavid van Moolenbroek bpf_error("unsupported index operation");
6732*d56f51eaSDavid van Moolenbroek
6733*d56f51eaSDavid van Moolenbroek case Q_RADIO:
6734*d56f51eaSDavid van Moolenbroek /*
6735*d56f51eaSDavid van Moolenbroek * The offset is relative to the beginning of the packet
6736*d56f51eaSDavid van Moolenbroek * data, if we have a radio header. (If we don't, this
6737*d56f51eaSDavid van Moolenbroek * is an error.)
6738*d56f51eaSDavid van Moolenbroek */
6739*d56f51eaSDavid van Moolenbroek if (linktype != DLT_IEEE802_11_RADIO_AVS &&
6740*d56f51eaSDavid van Moolenbroek linktype != DLT_IEEE802_11_RADIO &&
6741*d56f51eaSDavid van Moolenbroek linktype != DLT_PRISM_HEADER)
6742*d56f51eaSDavid van Moolenbroek bpf_error("radio information not present in capture");
6743*d56f51eaSDavid van Moolenbroek
6744*d56f51eaSDavid van Moolenbroek /*
6745*d56f51eaSDavid van Moolenbroek * Load into the X register the offset computed into the
6746*d56f51eaSDavid van Moolenbroek * register specified by "index".
6747*d56f51eaSDavid van Moolenbroek */
6748*d56f51eaSDavid van Moolenbroek s = xfer_to_x(inst);
6749*d56f51eaSDavid van Moolenbroek
6750*d56f51eaSDavid van Moolenbroek /*
6751*d56f51eaSDavid van Moolenbroek * Load the item at that offset.
6752*d56f51eaSDavid van Moolenbroek */
6753*d56f51eaSDavid van Moolenbroek tmp = new_stmt(BPF_LD|BPF_IND|size);
6754*d56f51eaSDavid van Moolenbroek sappend(s, tmp);
6755*d56f51eaSDavid van Moolenbroek sappend(inst->s, s);
6756*d56f51eaSDavid van Moolenbroek break;
6757*d56f51eaSDavid van Moolenbroek
6758*d56f51eaSDavid van Moolenbroek case Q_LINK:
6759*d56f51eaSDavid van Moolenbroek /*
6760*d56f51eaSDavid van Moolenbroek * The offset is relative to the beginning of
6761*d56f51eaSDavid van Moolenbroek * the link-layer header.
6762*d56f51eaSDavid van Moolenbroek *
6763*d56f51eaSDavid van Moolenbroek * XXX - what about ATM LANE? Should the index be
6764*d56f51eaSDavid van Moolenbroek * relative to the beginning of the AAL5 frame, so
6765*d56f51eaSDavid van Moolenbroek * that 0 refers to the beginning of the LE Control
6766*d56f51eaSDavid van Moolenbroek * field, or relative to the beginning of the LAN
6767*d56f51eaSDavid van Moolenbroek * frame, so that 0 refers, for Ethernet LANE, to
6768*d56f51eaSDavid van Moolenbroek * the beginning of the destination address?
6769*d56f51eaSDavid van Moolenbroek */
6770*d56f51eaSDavid van Moolenbroek s = gen_abs_offset_varpart(&off_linkhdr);
6771*d56f51eaSDavid van Moolenbroek
6772*d56f51eaSDavid van Moolenbroek /*
6773*d56f51eaSDavid van Moolenbroek * If "s" is non-null, it has code to arrange that the
6774*d56f51eaSDavid van Moolenbroek * X register contains the length of the prefix preceding
6775*d56f51eaSDavid van Moolenbroek * the link-layer header. Add to it the offset computed
6776*d56f51eaSDavid van Moolenbroek * into the register specified by "index", and move that
6777*d56f51eaSDavid van Moolenbroek * into the X register. Otherwise, just load into the X
6778*d56f51eaSDavid van Moolenbroek * register the offset computed into the register specified
6779*d56f51eaSDavid van Moolenbroek * by "index".
6780*d56f51eaSDavid van Moolenbroek */
6781*d56f51eaSDavid van Moolenbroek if (s != NULL) {
6782*d56f51eaSDavid van Moolenbroek sappend(s, xfer_to_a(inst));
6783*d56f51eaSDavid van Moolenbroek sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
6784*d56f51eaSDavid van Moolenbroek sappend(s, new_stmt(BPF_MISC|BPF_TAX));
6785*d56f51eaSDavid van Moolenbroek } else
6786*d56f51eaSDavid van Moolenbroek s = xfer_to_x(inst);
6787*d56f51eaSDavid van Moolenbroek
6788*d56f51eaSDavid van Moolenbroek /*
6789*d56f51eaSDavid van Moolenbroek * Load the item at the sum of the offset we've put in the
6790*d56f51eaSDavid van Moolenbroek * X register and the offset of the start of the link
6791*d56f51eaSDavid van Moolenbroek * layer header (which is 0 if the radio header is
6792*d56f51eaSDavid van Moolenbroek * variable-length; that header length is what we put
6793*d56f51eaSDavid van Moolenbroek * into the X register and then added to the index).
6794*d56f51eaSDavid van Moolenbroek */
6795*d56f51eaSDavid van Moolenbroek tmp = new_stmt(BPF_LD|BPF_IND|size);
6796*d56f51eaSDavid van Moolenbroek tmp->s.k = off_linkhdr.constant_part;
6797*d56f51eaSDavid van Moolenbroek sappend(s, tmp);
6798*d56f51eaSDavid van Moolenbroek sappend(inst->s, s);
6799*d56f51eaSDavid van Moolenbroek break;
6800*d56f51eaSDavid van Moolenbroek
6801*d56f51eaSDavid van Moolenbroek case Q_IP:
6802*d56f51eaSDavid van Moolenbroek case Q_ARP:
6803*d56f51eaSDavid van Moolenbroek case Q_RARP:
6804*d56f51eaSDavid van Moolenbroek case Q_ATALK:
6805*d56f51eaSDavid van Moolenbroek case Q_DECNET:
6806*d56f51eaSDavid van Moolenbroek case Q_SCA:
6807*d56f51eaSDavid van Moolenbroek case Q_LAT:
6808*d56f51eaSDavid van Moolenbroek case Q_MOPRC:
6809*d56f51eaSDavid van Moolenbroek case Q_MOPDL:
6810*d56f51eaSDavid van Moolenbroek case Q_IPV6:
6811*d56f51eaSDavid van Moolenbroek /*
6812*d56f51eaSDavid van Moolenbroek * The offset is relative to the beginning of
6813*d56f51eaSDavid van Moolenbroek * the network-layer header.
6814*d56f51eaSDavid van Moolenbroek * XXX - are there any cases where we want
6815*d56f51eaSDavid van Moolenbroek * off_nl_nosnap?
6816*d56f51eaSDavid van Moolenbroek */
6817*d56f51eaSDavid van Moolenbroek s = gen_abs_offset_varpart(&off_linkpl);
6818*d56f51eaSDavid van Moolenbroek
6819*d56f51eaSDavid van Moolenbroek /*
6820*d56f51eaSDavid van Moolenbroek * If "s" is non-null, it has code to arrange that the
6821*d56f51eaSDavid van Moolenbroek * X register contains the variable part of the offset
6822*d56f51eaSDavid van Moolenbroek * of the link-layer payload. Add to it the offset
6823*d56f51eaSDavid van Moolenbroek * computed into the register specified by "index",
6824*d56f51eaSDavid van Moolenbroek * and move that into the X register. Otherwise, just
6825*d56f51eaSDavid van Moolenbroek * load into the X register the offset computed into
6826*d56f51eaSDavid van Moolenbroek * the register specified by "index".
6827*d56f51eaSDavid van Moolenbroek */
6828*d56f51eaSDavid van Moolenbroek if (s != NULL) {
6829*d56f51eaSDavid van Moolenbroek sappend(s, xfer_to_a(inst));
6830*d56f51eaSDavid van Moolenbroek sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
6831*d56f51eaSDavid van Moolenbroek sappend(s, new_stmt(BPF_MISC|BPF_TAX));
6832*d56f51eaSDavid van Moolenbroek } else
6833*d56f51eaSDavid van Moolenbroek s = xfer_to_x(inst);
6834*d56f51eaSDavid van Moolenbroek
6835*d56f51eaSDavid van Moolenbroek /*
6836*d56f51eaSDavid van Moolenbroek * Load the item at the sum of the offset we've put in the
6837*d56f51eaSDavid van Moolenbroek * X register, the offset of the start of the network
6838*d56f51eaSDavid van Moolenbroek * layer header from the beginning of the link-layer
6839*d56f51eaSDavid van Moolenbroek * payload, and the constant part of the offset of the
6840*d56f51eaSDavid van Moolenbroek * start of the link-layer payload.
6841*d56f51eaSDavid van Moolenbroek */
6842*d56f51eaSDavid van Moolenbroek tmp = new_stmt(BPF_LD|BPF_IND|size);
6843*d56f51eaSDavid van Moolenbroek tmp->s.k = off_linkpl.constant_part + off_nl;
6844*d56f51eaSDavid van Moolenbroek sappend(s, tmp);
6845*d56f51eaSDavid van Moolenbroek sappend(inst->s, s);
6846*d56f51eaSDavid van Moolenbroek
6847*d56f51eaSDavid van Moolenbroek /*
6848*d56f51eaSDavid van Moolenbroek * Do the computation only if the packet contains
6849*d56f51eaSDavid van Moolenbroek * the protocol in question.
6850*d56f51eaSDavid van Moolenbroek */
6851*d56f51eaSDavid van Moolenbroek b = gen_proto_abbrev(proto);
6852*d56f51eaSDavid van Moolenbroek if (inst->b)
6853*d56f51eaSDavid van Moolenbroek gen_and(inst->b, b);
6854*d56f51eaSDavid van Moolenbroek inst->b = b;
6855*d56f51eaSDavid van Moolenbroek break;
6856*d56f51eaSDavid van Moolenbroek
6857*d56f51eaSDavid van Moolenbroek case Q_SCTP:
6858*d56f51eaSDavid van Moolenbroek case Q_TCP:
6859*d56f51eaSDavid van Moolenbroek case Q_UDP:
6860*d56f51eaSDavid van Moolenbroek case Q_ICMP:
6861*d56f51eaSDavid van Moolenbroek case Q_IGMP:
6862*d56f51eaSDavid van Moolenbroek case Q_IGRP:
6863*d56f51eaSDavid van Moolenbroek case Q_PIM:
6864*d56f51eaSDavid van Moolenbroek case Q_VRRP:
6865*d56f51eaSDavid van Moolenbroek case Q_CARP:
6866*d56f51eaSDavid van Moolenbroek /*
6867*d56f51eaSDavid van Moolenbroek * The offset is relative to the beginning of
6868*d56f51eaSDavid van Moolenbroek * the transport-layer header.
6869*d56f51eaSDavid van Moolenbroek *
6870*d56f51eaSDavid van Moolenbroek * Load the X register with the length of the IPv4 header
6871*d56f51eaSDavid van Moolenbroek * (plus the offset of the link-layer header, if it's
6872*d56f51eaSDavid van Moolenbroek * a variable-length header), in bytes.
6873*d56f51eaSDavid van Moolenbroek *
6874*d56f51eaSDavid van Moolenbroek * XXX - are there any cases where we want
6875*d56f51eaSDavid van Moolenbroek * off_nl_nosnap?
6876*d56f51eaSDavid van Moolenbroek * XXX - we should, if we're built with
6877*d56f51eaSDavid van Moolenbroek * IPv6 support, generate code to load either
6878*d56f51eaSDavid van Moolenbroek * IPv4, IPv6, or both, as appropriate.
6879*d56f51eaSDavid van Moolenbroek */
6880*d56f51eaSDavid van Moolenbroek s = gen_loadx_iphdrlen();
6881*d56f51eaSDavid van Moolenbroek
6882*d56f51eaSDavid van Moolenbroek /*
6883*d56f51eaSDavid van Moolenbroek * The X register now contains the sum of the variable
6884*d56f51eaSDavid van Moolenbroek * part of the offset of the link-layer payload and the
6885*d56f51eaSDavid van Moolenbroek * length of the network-layer header.
6886*d56f51eaSDavid van Moolenbroek *
6887*d56f51eaSDavid van Moolenbroek * Load into the A register the offset relative to
6888*d56f51eaSDavid van Moolenbroek * the beginning of the transport layer header,
6889*d56f51eaSDavid van Moolenbroek * add the X register to that, move that to the
6890*d56f51eaSDavid van Moolenbroek * X register, and load with an offset from the
6891*d56f51eaSDavid van Moolenbroek * X register equal to the sum of the constant part of
6892*d56f51eaSDavid van Moolenbroek * the offset of the link-layer payload and the offset,
6893*d56f51eaSDavid van Moolenbroek * relative to the beginning of the link-layer payload,
6894*d56f51eaSDavid van Moolenbroek * of the network-layer header.
6895*d56f51eaSDavid van Moolenbroek */
6896*d56f51eaSDavid van Moolenbroek sappend(s, xfer_to_a(inst));
6897*d56f51eaSDavid van Moolenbroek sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
6898*d56f51eaSDavid van Moolenbroek sappend(s, new_stmt(BPF_MISC|BPF_TAX));
6899*d56f51eaSDavid van Moolenbroek sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size));
6900*d56f51eaSDavid van Moolenbroek tmp->s.k = off_linkpl.constant_part + off_nl;
6901*d56f51eaSDavid van Moolenbroek sappend(inst->s, s);
6902*d56f51eaSDavid van Moolenbroek
6903*d56f51eaSDavid van Moolenbroek /*
6904*d56f51eaSDavid van Moolenbroek * Do the computation only if the packet contains
6905*d56f51eaSDavid van Moolenbroek * the protocol in question - which is true only
6906*d56f51eaSDavid van Moolenbroek * if this is an IP datagram and is the first or
6907*d56f51eaSDavid van Moolenbroek * only fragment of that datagram.
6908*d56f51eaSDavid van Moolenbroek */
6909*d56f51eaSDavid van Moolenbroek gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
6910*d56f51eaSDavid van Moolenbroek if (inst->b)
6911*d56f51eaSDavid van Moolenbroek gen_and(inst->b, b);
6912*d56f51eaSDavid van Moolenbroek gen_and(gen_proto_abbrev(Q_IP), b);
6913*d56f51eaSDavid van Moolenbroek inst->b = b;
6914*d56f51eaSDavid van Moolenbroek break;
6915*d56f51eaSDavid van Moolenbroek case Q_ICMPV6:
6916*d56f51eaSDavid van Moolenbroek bpf_error("IPv6 upper-layer protocol is not supported by proto[x]");
6917*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
6918*d56f51eaSDavid van Moolenbroek }
6919*d56f51eaSDavid van Moolenbroek inst->regno = regno;
6920*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_ST);
6921*d56f51eaSDavid van Moolenbroek s->s.k = regno;
6922*d56f51eaSDavid van Moolenbroek sappend(inst->s, s);
6923*d56f51eaSDavid van Moolenbroek
6924*d56f51eaSDavid van Moolenbroek return inst;
6925*d56f51eaSDavid van Moolenbroek }
6926*d56f51eaSDavid van Moolenbroek
6927*d56f51eaSDavid van Moolenbroek struct block *
gen_relation(code,a0,a1,reversed)6928*d56f51eaSDavid van Moolenbroek gen_relation(code, a0, a1, reversed)
6929*d56f51eaSDavid van Moolenbroek int code;
6930*d56f51eaSDavid van Moolenbroek struct arth *a0, *a1;
6931*d56f51eaSDavid van Moolenbroek int reversed;
6932*d56f51eaSDavid van Moolenbroek {
6933*d56f51eaSDavid van Moolenbroek struct slist *s0, *s1, *s2;
6934*d56f51eaSDavid van Moolenbroek struct block *b, *tmp;
6935*d56f51eaSDavid van Moolenbroek
6936*d56f51eaSDavid van Moolenbroek s0 = xfer_to_x(a1);
6937*d56f51eaSDavid van Moolenbroek s1 = xfer_to_a(a0);
6938*d56f51eaSDavid van Moolenbroek if (code == BPF_JEQ) {
6939*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X);
6940*d56f51eaSDavid van Moolenbroek b = new_block(JMP(code));
6941*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
6942*d56f51eaSDavid van Moolenbroek }
6943*d56f51eaSDavid van Moolenbroek else
6944*d56f51eaSDavid van Moolenbroek b = new_block(BPF_JMP|code|BPF_X);
6945*d56f51eaSDavid van Moolenbroek if (reversed)
6946*d56f51eaSDavid van Moolenbroek gen_not(b);
6947*d56f51eaSDavid van Moolenbroek
6948*d56f51eaSDavid van Moolenbroek sappend(s0, s1);
6949*d56f51eaSDavid van Moolenbroek sappend(a1->s, s0);
6950*d56f51eaSDavid van Moolenbroek sappend(a0->s, a1->s);
6951*d56f51eaSDavid van Moolenbroek
6952*d56f51eaSDavid van Moolenbroek b->stmts = a0->s;
6953*d56f51eaSDavid van Moolenbroek
6954*d56f51eaSDavid van Moolenbroek free_reg(a0->regno);
6955*d56f51eaSDavid van Moolenbroek free_reg(a1->regno);
6956*d56f51eaSDavid van Moolenbroek
6957*d56f51eaSDavid van Moolenbroek /* 'and' together protocol checks */
6958*d56f51eaSDavid van Moolenbroek if (a0->b) {
6959*d56f51eaSDavid van Moolenbroek if (a1->b) {
6960*d56f51eaSDavid van Moolenbroek gen_and(a0->b, tmp = a1->b);
6961*d56f51eaSDavid van Moolenbroek }
6962*d56f51eaSDavid van Moolenbroek else
6963*d56f51eaSDavid van Moolenbroek tmp = a0->b;
6964*d56f51eaSDavid van Moolenbroek } else
6965*d56f51eaSDavid van Moolenbroek tmp = a1->b;
6966*d56f51eaSDavid van Moolenbroek
6967*d56f51eaSDavid van Moolenbroek if (tmp)
6968*d56f51eaSDavid van Moolenbroek gen_and(tmp, b);
6969*d56f51eaSDavid van Moolenbroek
6970*d56f51eaSDavid van Moolenbroek return b;
6971*d56f51eaSDavid van Moolenbroek }
6972*d56f51eaSDavid van Moolenbroek
6973*d56f51eaSDavid van Moolenbroek struct arth *
gen_loadlen()6974*d56f51eaSDavid van Moolenbroek gen_loadlen()
6975*d56f51eaSDavid van Moolenbroek {
6976*d56f51eaSDavid van Moolenbroek int regno = alloc_reg();
6977*d56f51eaSDavid van Moolenbroek struct arth *a = (struct arth *)newchunk(sizeof(*a));
6978*d56f51eaSDavid van Moolenbroek struct slist *s;
6979*d56f51eaSDavid van Moolenbroek
6980*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_LD|BPF_LEN);
6981*d56f51eaSDavid van Moolenbroek s->next = new_stmt(BPF_ST);
6982*d56f51eaSDavid van Moolenbroek s->next->s.k = regno;
6983*d56f51eaSDavid van Moolenbroek a->s = s;
6984*d56f51eaSDavid van Moolenbroek a->regno = regno;
6985*d56f51eaSDavid van Moolenbroek
6986*d56f51eaSDavid van Moolenbroek return a;
6987*d56f51eaSDavid van Moolenbroek }
6988*d56f51eaSDavid van Moolenbroek
6989*d56f51eaSDavid van Moolenbroek struct arth *
gen_loadi(val)6990*d56f51eaSDavid van Moolenbroek gen_loadi(val)
6991*d56f51eaSDavid van Moolenbroek int val;
6992*d56f51eaSDavid van Moolenbroek {
6993*d56f51eaSDavid van Moolenbroek struct arth *a;
6994*d56f51eaSDavid van Moolenbroek struct slist *s;
6995*d56f51eaSDavid van Moolenbroek int reg;
6996*d56f51eaSDavid van Moolenbroek
6997*d56f51eaSDavid van Moolenbroek a = (struct arth *)newchunk(sizeof(*a));
6998*d56f51eaSDavid van Moolenbroek
6999*d56f51eaSDavid van Moolenbroek reg = alloc_reg();
7000*d56f51eaSDavid van Moolenbroek
7001*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_LD|BPF_IMM);
7002*d56f51eaSDavid van Moolenbroek s->s.k = val;
7003*d56f51eaSDavid van Moolenbroek s->next = new_stmt(BPF_ST);
7004*d56f51eaSDavid van Moolenbroek s->next->s.k = reg;
7005*d56f51eaSDavid van Moolenbroek a->s = s;
7006*d56f51eaSDavid van Moolenbroek a->regno = reg;
7007*d56f51eaSDavid van Moolenbroek
7008*d56f51eaSDavid van Moolenbroek return a;
7009*d56f51eaSDavid van Moolenbroek }
7010*d56f51eaSDavid van Moolenbroek
7011*d56f51eaSDavid van Moolenbroek struct arth *
gen_neg(a)7012*d56f51eaSDavid van Moolenbroek gen_neg(a)
7013*d56f51eaSDavid van Moolenbroek struct arth *a;
7014*d56f51eaSDavid van Moolenbroek {
7015*d56f51eaSDavid van Moolenbroek struct slist *s;
7016*d56f51eaSDavid van Moolenbroek
7017*d56f51eaSDavid van Moolenbroek s = xfer_to_a(a);
7018*d56f51eaSDavid van Moolenbroek sappend(a->s, s);
7019*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_ALU|BPF_NEG);
7020*d56f51eaSDavid van Moolenbroek s->s.k = 0;
7021*d56f51eaSDavid van Moolenbroek sappend(a->s, s);
7022*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_ST);
7023*d56f51eaSDavid van Moolenbroek s->s.k = a->regno;
7024*d56f51eaSDavid van Moolenbroek sappend(a->s, s);
7025*d56f51eaSDavid van Moolenbroek
7026*d56f51eaSDavid van Moolenbroek return a;
7027*d56f51eaSDavid van Moolenbroek }
7028*d56f51eaSDavid van Moolenbroek
7029*d56f51eaSDavid van Moolenbroek struct arth *
gen_arth(code,a0,a1)7030*d56f51eaSDavid van Moolenbroek gen_arth(code, a0, a1)
7031*d56f51eaSDavid van Moolenbroek int code;
7032*d56f51eaSDavid van Moolenbroek struct arth *a0, *a1;
7033*d56f51eaSDavid van Moolenbroek {
7034*d56f51eaSDavid van Moolenbroek struct slist *s0, *s1, *s2;
7035*d56f51eaSDavid van Moolenbroek
7036*d56f51eaSDavid van Moolenbroek s0 = xfer_to_x(a1);
7037*d56f51eaSDavid van Moolenbroek s1 = xfer_to_a(a0);
7038*d56f51eaSDavid van Moolenbroek s2 = new_stmt(BPF_ALU|BPF_X|code);
7039*d56f51eaSDavid van Moolenbroek
7040*d56f51eaSDavid van Moolenbroek sappend(s1, s2);
7041*d56f51eaSDavid van Moolenbroek sappend(s0, s1);
7042*d56f51eaSDavid van Moolenbroek sappend(a1->s, s0);
7043*d56f51eaSDavid van Moolenbroek sappend(a0->s, a1->s);
7044*d56f51eaSDavid van Moolenbroek
7045*d56f51eaSDavid van Moolenbroek free_reg(a0->regno);
7046*d56f51eaSDavid van Moolenbroek free_reg(a1->regno);
7047*d56f51eaSDavid van Moolenbroek
7048*d56f51eaSDavid van Moolenbroek s0 = new_stmt(BPF_ST);
7049*d56f51eaSDavid van Moolenbroek a0->regno = s0->s.k = alloc_reg();
7050*d56f51eaSDavid van Moolenbroek sappend(a0->s, s0);
7051*d56f51eaSDavid van Moolenbroek
7052*d56f51eaSDavid van Moolenbroek return a0;
7053*d56f51eaSDavid van Moolenbroek }
7054*d56f51eaSDavid van Moolenbroek
7055*d56f51eaSDavid van Moolenbroek /*
7056*d56f51eaSDavid van Moolenbroek * Here we handle simple allocation of the scratch registers.
7057*d56f51eaSDavid van Moolenbroek * If too many registers are alloc'd, the allocator punts.
7058*d56f51eaSDavid van Moolenbroek */
7059*d56f51eaSDavid van Moolenbroek static int regused[BPF_MEMWORDS];
7060*d56f51eaSDavid van Moolenbroek static int curreg;
7061*d56f51eaSDavid van Moolenbroek
7062*d56f51eaSDavid van Moolenbroek /*
7063*d56f51eaSDavid van Moolenbroek * Initialize the table of used registers and the current register.
7064*d56f51eaSDavid van Moolenbroek */
7065*d56f51eaSDavid van Moolenbroek static void
init_regs()7066*d56f51eaSDavid van Moolenbroek init_regs()
7067*d56f51eaSDavid van Moolenbroek {
7068*d56f51eaSDavid van Moolenbroek curreg = 0;
7069*d56f51eaSDavid van Moolenbroek memset(regused, 0, sizeof regused);
7070*d56f51eaSDavid van Moolenbroek }
7071*d56f51eaSDavid van Moolenbroek
7072*d56f51eaSDavid van Moolenbroek /*
7073*d56f51eaSDavid van Moolenbroek * Return the next free register.
7074*d56f51eaSDavid van Moolenbroek */
7075*d56f51eaSDavid van Moolenbroek static int
alloc_reg()7076*d56f51eaSDavid van Moolenbroek alloc_reg()
7077*d56f51eaSDavid van Moolenbroek {
7078*d56f51eaSDavid van Moolenbroek int n = BPF_MEMWORDS;
7079*d56f51eaSDavid van Moolenbroek
7080*d56f51eaSDavid van Moolenbroek while (--n >= 0) {
7081*d56f51eaSDavid van Moolenbroek if (regused[curreg])
7082*d56f51eaSDavid van Moolenbroek curreg = (curreg + 1) % BPF_MEMWORDS;
7083*d56f51eaSDavid van Moolenbroek else {
7084*d56f51eaSDavid van Moolenbroek regused[curreg] = 1;
7085*d56f51eaSDavid van Moolenbroek return curreg;
7086*d56f51eaSDavid van Moolenbroek }
7087*d56f51eaSDavid van Moolenbroek }
7088*d56f51eaSDavid van Moolenbroek bpf_error("too many registers needed to evaluate expression");
7089*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7090*d56f51eaSDavid van Moolenbroek return 0;
7091*d56f51eaSDavid van Moolenbroek }
7092*d56f51eaSDavid van Moolenbroek
7093*d56f51eaSDavid van Moolenbroek /*
7094*d56f51eaSDavid van Moolenbroek * Return a register to the table so it can
7095*d56f51eaSDavid van Moolenbroek * be used later.
7096*d56f51eaSDavid van Moolenbroek */
7097*d56f51eaSDavid van Moolenbroek static void
free_reg(n)7098*d56f51eaSDavid van Moolenbroek free_reg(n)
7099*d56f51eaSDavid van Moolenbroek int n;
7100*d56f51eaSDavid van Moolenbroek {
7101*d56f51eaSDavid van Moolenbroek regused[n] = 0;
7102*d56f51eaSDavid van Moolenbroek }
7103*d56f51eaSDavid van Moolenbroek
7104*d56f51eaSDavid van Moolenbroek static struct block *
gen_len(jmp,n)7105*d56f51eaSDavid van Moolenbroek gen_len(jmp, n)
7106*d56f51eaSDavid van Moolenbroek int jmp, n;
7107*d56f51eaSDavid van Moolenbroek {
7108*d56f51eaSDavid van Moolenbroek struct slist *s;
7109*d56f51eaSDavid van Moolenbroek struct block *b;
7110*d56f51eaSDavid van Moolenbroek
7111*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_LD|BPF_LEN);
7112*d56f51eaSDavid van Moolenbroek b = new_block(JMP(jmp));
7113*d56f51eaSDavid van Moolenbroek b->stmts = s;
7114*d56f51eaSDavid van Moolenbroek b->s.k = n;
7115*d56f51eaSDavid van Moolenbroek
7116*d56f51eaSDavid van Moolenbroek return b;
7117*d56f51eaSDavid van Moolenbroek }
7118*d56f51eaSDavid van Moolenbroek
7119*d56f51eaSDavid van Moolenbroek struct block *
gen_greater(n)7120*d56f51eaSDavid van Moolenbroek gen_greater(n)
7121*d56f51eaSDavid van Moolenbroek int n;
7122*d56f51eaSDavid van Moolenbroek {
7123*d56f51eaSDavid van Moolenbroek return gen_len(BPF_JGE, n);
7124*d56f51eaSDavid van Moolenbroek }
7125*d56f51eaSDavid van Moolenbroek
7126*d56f51eaSDavid van Moolenbroek /*
7127*d56f51eaSDavid van Moolenbroek * Actually, this is less than or equal.
7128*d56f51eaSDavid van Moolenbroek */
7129*d56f51eaSDavid van Moolenbroek struct block *
gen_less(n)7130*d56f51eaSDavid van Moolenbroek gen_less(n)
7131*d56f51eaSDavid van Moolenbroek int n;
7132*d56f51eaSDavid van Moolenbroek {
7133*d56f51eaSDavid van Moolenbroek struct block *b;
7134*d56f51eaSDavid van Moolenbroek
7135*d56f51eaSDavid van Moolenbroek b = gen_len(BPF_JGT, n);
7136*d56f51eaSDavid van Moolenbroek gen_not(b);
7137*d56f51eaSDavid van Moolenbroek
7138*d56f51eaSDavid van Moolenbroek return b;
7139*d56f51eaSDavid van Moolenbroek }
7140*d56f51eaSDavid van Moolenbroek
7141*d56f51eaSDavid van Moolenbroek /*
7142*d56f51eaSDavid van Moolenbroek * This is for "byte {idx} {op} {val}"; "idx" is treated as relative to
7143*d56f51eaSDavid van Moolenbroek * the beginning of the link-layer header.
7144*d56f51eaSDavid van Moolenbroek * XXX - that means you can't test values in the radiotap header, but
7145*d56f51eaSDavid van Moolenbroek * as that header is difficult if not impossible to parse generally
7146*d56f51eaSDavid van Moolenbroek * without a loop, that might not be a severe problem. A new keyword
7147*d56f51eaSDavid van Moolenbroek * "radio" could be added for that, although what you'd really want
7148*d56f51eaSDavid van Moolenbroek * would be a way of testing particular radio header values, which
7149*d56f51eaSDavid van Moolenbroek * would generate code appropriate to the radio header in question.
7150*d56f51eaSDavid van Moolenbroek */
7151*d56f51eaSDavid van Moolenbroek struct block *
gen_byteop(op,idx,val)7152*d56f51eaSDavid van Moolenbroek gen_byteop(op, idx, val)
7153*d56f51eaSDavid van Moolenbroek int op, idx, val;
7154*d56f51eaSDavid van Moolenbroek {
7155*d56f51eaSDavid van Moolenbroek struct block *b;
7156*d56f51eaSDavid van Moolenbroek struct slist *s;
7157*d56f51eaSDavid van Moolenbroek
7158*d56f51eaSDavid van Moolenbroek switch (op) {
7159*d56f51eaSDavid van Moolenbroek default:
7160*d56f51eaSDavid van Moolenbroek abort();
7161*d56f51eaSDavid van Moolenbroek
7162*d56f51eaSDavid van Moolenbroek case '=':
7163*d56f51eaSDavid van Moolenbroek return gen_cmp(OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
7164*d56f51eaSDavid van Moolenbroek
7165*d56f51eaSDavid van Moolenbroek case '<':
7166*d56f51eaSDavid van Moolenbroek b = gen_cmp_lt(OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
7167*d56f51eaSDavid van Moolenbroek return b;
7168*d56f51eaSDavid van Moolenbroek
7169*d56f51eaSDavid van Moolenbroek case '>':
7170*d56f51eaSDavid van Moolenbroek b = gen_cmp_gt(OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
7171*d56f51eaSDavid van Moolenbroek return b;
7172*d56f51eaSDavid van Moolenbroek
7173*d56f51eaSDavid van Moolenbroek case '|':
7174*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_ALU|BPF_OR|BPF_K);
7175*d56f51eaSDavid van Moolenbroek break;
7176*d56f51eaSDavid van Moolenbroek
7177*d56f51eaSDavid van Moolenbroek case '&':
7178*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
7179*d56f51eaSDavid van Moolenbroek break;
7180*d56f51eaSDavid van Moolenbroek }
7181*d56f51eaSDavid van Moolenbroek s->s.k = val;
7182*d56f51eaSDavid van Moolenbroek b = new_block(JMP(BPF_JEQ));
7183*d56f51eaSDavid van Moolenbroek b->stmts = s;
7184*d56f51eaSDavid van Moolenbroek gen_not(b);
7185*d56f51eaSDavid van Moolenbroek
7186*d56f51eaSDavid van Moolenbroek return b;
7187*d56f51eaSDavid van Moolenbroek }
7188*d56f51eaSDavid van Moolenbroek
7189*d56f51eaSDavid van Moolenbroek static u_char abroadcast[] = { 0x0 };
7190*d56f51eaSDavid van Moolenbroek
7191*d56f51eaSDavid van Moolenbroek struct block *
gen_broadcast(proto)7192*d56f51eaSDavid van Moolenbroek gen_broadcast(proto)
7193*d56f51eaSDavid van Moolenbroek int proto;
7194*d56f51eaSDavid van Moolenbroek {
7195*d56f51eaSDavid van Moolenbroek bpf_u_int32 hostmask;
7196*d56f51eaSDavid van Moolenbroek struct block *b0, *b1, *b2;
7197*d56f51eaSDavid van Moolenbroek static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
7198*d56f51eaSDavid van Moolenbroek
7199*d56f51eaSDavid van Moolenbroek switch (proto) {
7200*d56f51eaSDavid van Moolenbroek
7201*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
7202*d56f51eaSDavid van Moolenbroek case Q_LINK:
7203*d56f51eaSDavid van Moolenbroek switch (linktype) {
7204*d56f51eaSDavid van Moolenbroek case DLT_ARCNET:
7205*d56f51eaSDavid van Moolenbroek case DLT_ARCNET_LINUX:
7206*d56f51eaSDavid van Moolenbroek return gen_ahostop(abroadcast, Q_DST);
7207*d56f51eaSDavid van Moolenbroek case DLT_EN10MB:
7208*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER:
7209*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER_TRANSPARENT:
7210*d56f51eaSDavid van Moolenbroek b1 = gen_prevlinkhdr_check();
7211*d56f51eaSDavid van Moolenbroek b0 = gen_ehostop(ebroadcast, Q_DST);
7212*d56f51eaSDavid van Moolenbroek if (b1 != NULL)
7213*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
7214*d56f51eaSDavid van Moolenbroek return b0;
7215*d56f51eaSDavid van Moolenbroek case DLT_FDDI:
7216*d56f51eaSDavid van Moolenbroek return gen_fhostop(ebroadcast, Q_DST);
7217*d56f51eaSDavid van Moolenbroek case DLT_IEEE802:
7218*d56f51eaSDavid van Moolenbroek return gen_thostop(ebroadcast, Q_DST);
7219*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11:
7220*d56f51eaSDavid van Moolenbroek case DLT_PRISM_HEADER:
7221*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO_AVS:
7222*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO:
7223*d56f51eaSDavid van Moolenbroek case DLT_PPI:
7224*d56f51eaSDavid van Moolenbroek return gen_wlanhostop(ebroadcast, Q_DST);
7225*d56f51eaSDavid van Moolenbroek case DLT_IP_OVER_FC:
7226*d56f51eaSDavid van Moolenbroek return gen_ipfchostop(ebroadcast, Q_DST);
7227*d56f51eaSDavid van Moolenbroek default:
7228*d56f51eaSDavid van Moolenbroek bpf_error("not a broadcast link");
7229*d56f51eaSDavid van Moolenbroek }
7230*d56f51eaSDavid van Moolenbroek break;
7231*d56f51eaSDavid van Moolenbroek
7232*d56f51eaSDavid van Moolenbroek case Q_IP:
7233*d56f51eaSDavid van Moolenbroek /*
7234*d56f51eaSDavid van Moolenbroek * We treat a netmask of PCAP_NETMASK_UNKNOWN (0xffffffff)
7235*d56f51eaSDavid van Moolenbroek * as an indication that we don't know the netmask, and fail
7236*d56f51eaSDavid van Moolenbroek * in that case.
7237*d56f51eaSDavid van Moolenbroek */
7238*d56f51eaSDavid van Moolenbroek if (netmask == PCAP_NETMASK_UNKNOWN)
7239*d56f51eaSDavid van Moolenbroek bpf_error("netmask not known, so 'ip broadcast' not supported");
7240*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(ETHERTYPE_IP);
7241*d56f51eaSDavid van Moolenbroek hostmask = ~netmask;
7242*d56f51eaSDavid van Moolenbroek b1 = gen_mcmp(OR_LINKPL, 16, BPF_W, (bpf_int32)0, hostmask);
7243*d56f51eaSDavid van Moolenbroek b2 = gen_mcmp(OR_LINKPL, 16, BPF_W,
7244*d56f51eaSDavid van Moolenbroek (bpf_int32)(~0 & hostmask), hostmask);
7245*d56f51eaSDavid van Moolenbroek gen_or(b1, b2);
7246*d56f51eaSDavid van Moolenbroek gen_and(b0, b2);
7247*d56f51eaSDavid van Moolenbroek return b2;
7248*d56f51eaSDavid van Moolenbroek }
7249*d56f51eaSDavid van Moolenbroek bpf_error("only link-layer/IP broadcast filters supported");
7250*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7251*d56f51eaSDavid van Moolenbroek return NULL;
7252*d56f51eaSDavid van Moolenbroek }
7253*d56f51eaSDavid van Moolenbroek
7254*d56f51eaSDavid van Moolenbroek /*
7255*d56f51eaSDavid van Moolenbroek * Generate code to test the low-order bit of a MAC address (that's
7256*d56f51eaSDavid van Moolenbroek * the bottom bit of the *first* byte).
7257*d56f51eaSDavid van Moolenbroek */
7258*d56f51eaSDavid van Moolenbroek static struct block *
gen_mac_multicast(offset)7259*d56f51eaSDavid van Moolenbroek gen_mac_multicast(offset)
7260*d56f51eaSDavid van Moolenbroek int offset;
7261*d56f51eaSDavid van Moolenbroek {
7262*d56f51eaSDavid van Moolenbroek register struct block *b0;
7263*d56f51eaSDavid van Moolenbroek register struct slist *s;
7264*d56f51eaSDavid van Moolenbroek
7265*d56f51eaSDavid van Moolenbroek /* link[offset] & 1 != 0 */
7266*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, offset, BPF_B);
7267*d56f51eaSDavid van Moolenbroek b0 = new_block(JMP(BPF_JSET));
7268*d56f51eaSDavid van Moolenbroek b0->s.k = 1;
7269*d56f51eaSDavid van Moolenbroek b0->stmts = s;
7270*d56f51eaSDavid van Moolenbroek return b0;
7271*d56f51eaSDavid van Moolenbroek }
7272*d56f51eaSDavid van Moolenbroek
7273*d56f51eaSDavid van Moolenbroek struct block *
gen_multicast(proto)7274*d56f51eaSDavid van Moolenbroek gen_multicast(proto)
7275*d56f51eaSDavid van Moolenbroek int proto;
7276*d56f51eaSDavid van Moolenbroek {
7277*d56f51eaSDavid van Moolenbroek register struct block *b0, *b1, *b2;
7278*d56f51eaSDavid van Moolenbroek register struct slist *s;
7279*d56f51eaSDavid van Moolenbroek
7280*d56f51eaSDavid van Moolenbroek switch (proto) {
7281*d56f51eaSDavid van Moolenbroek
7282*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
7283*d56f51eaSDavid van Moolenbroek case Q_LINK:
7284*d56f51eaSDavid van Moolenbroek switch (linktype) {
7285*d56f51eaSDavid van Moolenbroek case DLT_ARCNET:
7286*d56f51eaSDavid van Moolenbroek case DLT_ARCNET_LINUX:
7287*d56f51eaSDavid van Moolenbroek /* all ARCnet multicasts use the same address */
7288*d56f51eaSDavid van Moolenbroek return gen_ahostop(abroadcast, Q_DST);
7289*d56f51eaSDavid van Moolenbroek case DLT_EN10MB:
7290*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER:
7291*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER_TRANSPARENT:
7292*d56f51eaSDavid van Moolenbroek b1 = gen_prevlinkhdr_check();
7293*d56f51eaSDavid van Moolenbroek /* ether[0] & 1 != 0 */
7294*d56f51eaSDavid van Moolenbroek b0 = gen_mac_multicast(0);
7295*d56f51eaSDavid van Moolenbroek if (b1 != NULL)
7296*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
7297*d56f51eaSDavid van Moolenbroek return b0;
7298*d56f51eaSDavid van Moolenbroek case DLT_FDDI:
7299*d56f51eaSDavid van Moolenbroek /*
7300*d56f51eaSDavid van Moolenbroek * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX
7301*d56f51eaSDavid van Moolenbroek *
7302*d56f51eaSDavid van Moolenbroek * XXX - was that referring to bit-order issues?
7303*d56f51eaSDavid van Moolenbroek */
7304*d56f51eaSDavid van Moolenbroek /* fddi[1] & 1 != 0 */
7305*d56f51eaSDavid van Moolenbroek return gen_mac_multicast(1);
7306*d56f51eaSDavid van Moolenbroek case DLT_IEEE802:
7307*d56f51eaSDavid van Moolenbroek /* tr[2] & 1 != 0 */
7308*d56f51eaSDavid van Moolenbroek return gen_mac_multicast(2);
7309*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11:
7310*d56f51eaSDavid van Moolenbroek case DLT_PRISM_HEADER:
7311*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO_AVS:
7312*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO:
7313*d56f51eaSDavid van Moolenbroek case DLT_PPI:
7314*d56f51eaSDavid van Moolenbroek /*
7315*d56f51eaSDavid van Moolenbroek * Oh, yuk.
7316*d56f51eaSDavid van Moolenbroek *
7317*d56f51eaSDavid van Moolenbroek * For control frames, there is no DA.
7318*d56f51eaSDavid van Moolenbroek *
7319*d56f51eaSDavid van Moolenbroek * For management frames, DA is at an
7320*d56f51eaSDavid van Moolenbroek * offset of 4 from the beginning of
7321*d56f51eaSDavid van Moolenbroek * the packet.
7322*d56f51eaSDavid van Moolenbroek *
7323*d56f51eaSDavid van Moolenbroek * For data frames, DA is at an offset
7324*d56f51eaSDavid van Moolenbroek * of 4 from the beginning of the packet
7325*d56f51eaSDavid van Moolenbroek * if To DS is clear and at an offset of
7326*d56f51eaSDavid van Moolenbroek * 16 from the beginning of the packet
7327*d56f51eaSDavid van Moolenbroek * if To DS is set.
7328*d56f51eaSDavid van Moolenbroek */
7329*d56f51eaSDavid van Moolenbroek
7330*d56f51eaSDavid van Moolenbroek /*
7331*d56f51eaSDavid van Moolenbroek * Generate the tests to be done for data frames.
7332*d56f51eaSDavid van Moolenbroek *
7333*d56f51eaSDavid van Moolenbroek * First, check for To DS set, i.e. "link[1] & 0x01".
7334*d56f51eaSDavid van Moolenbroek */
7335*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 1, BPF_B);
7336*d56f51eaSDavid van Moolenbroek b1 = new_block(JMP(BPF_JSET));
7337*d56f51eaSDavid van Moolenbroek b1->s.k = 0x01; /* To DS */
7338*d56f51eaSDavid van Moolenbroek b1->stmts = s;
7339*d56f51eaSDavid van Moolenbroek
7340*d56f51eaSDavid van Moolenbroek /*
7341*d56f51eaSDavid van Moolenbroek * If To DS is set, the DA is at 16.
7342*d56f51eaSDavid van Moolenbroek */
7343*d56f51eaSDavid van Moolenbroek b0 = gen_mac_multicast(16);
7344*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
7345*d56f51eaSDavid van Moolenbroek
7346*d56f51eaSDavid van Moolenbroek /*
7347*d56f51eaSDavid van Moolenbroek * Now, check for To DS not set, i.e. check
7348*d56f51eaSDavid van Moolenbroek * "!(link[1] & 0x01)".
7349*d56f51eaSDavid van Moolenbroek */
7350*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 1, BPF_B);
7351*d56f51eaSDavid van Moolenbroek b2 = new_block(JMP(BPF_JSET));
7352*d56f51eaSDavid van Moolenbroek b2->s.k = 0x01; /* To DS */
7353*d56f51eaSDavid van Moolenbroek b2->stmts = s;
7354*d56f51eaSDavid van Moolenbroek gen_not(b2);
7355*d56f51eaSDavid van Moolenbroek
7356*d56f51eaSDavid van Moolenbroek /*
7357*d56f51eaSDavid van Moolenbroek * If To DS is not set, the DA is at 4.
7358*d56f51eaSDavid van Moolenbroek */
7359*d56f51eaSDavid van Moolenbroek b1 = gen_mac_multicast(4);
7360*d56f51eaSDavid van Moolenbroek gen_and(b2, b1);
7361*d56f51eaSDavid van Moolenbroek
7362*d56f51eaSDavid van Moolenbroek /*
7363*d56f51eaSDavid van Moolenbroek * Now OR together the last two checks. That gives
7364*d56f51eaSDavid van Moolenbroek * the complete set of checks for data frames.
7365*d56f51eaSDavid van Moolenbroek */
7366*d56f51eaSDavid van Moolenbroek gen_or(b1, b0);
7367*d56f51eaSDavid van Moolenbroek
7368*d56f51eaSDavid van Moolenbroek /*
7369*d56f51eaSDavid van Moolenbroek * Now check for a data frame.
7370*d56f51eaSDavid van Moolenbroek * I.e, check "link[0] & 0x08".
7371*d56f51eaSDavid van Moolenbroek */
7372*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 0, BPF_B);
7373*d56f51eaSDavid van Moolenbroek b1 = new_block(JMP(BPF_JSET));
7374*d56f51eaSDavid van Moolenbroek b1->s.k = 0x08;
7375*d56f51eaSDavid van Moolenbroek b1->stmts = s;
7376*d56f51eaSDavid van Moolenbroek
7377*d56f51eaSDavid van Moolenbroek /*
7378*d56f51eaSDavid van Moolenbroek * AND that with the checks done for data frames.
7379*d56f51eaSDavid van Moolenbroek */
7380*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
7381*d56f51eaSDavid van Moolenbroek
7382*d56f51eaSDavid van Moolenbroek /*
7383*d56f51eaSDavid van Moolenbroek * If the high-order bit of the type value is 0, this
7384*d56f51eaSDavid van Moolenbroek * is a management frame.
7385*d56f51eaSDavid van Moolenbroek * I.e, check "!(link[0] & 0x08)".
7386*d56f51eaSDavid van Moolenbroek */
7387*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 0, BPF_B);
7388*d56f51eaSDavid van Moolenbroek b2 = new_block(JMP(BPF_JSET));
7389*d56f51eaSDavid van Moolenbroek b2->s.k = 0x08;
7390*d56f51eaSDavid van Moolenbroek b2->stmts = s;
7391*d56f51eaSDavid van Moolenbroek gen_not(b2);
7392*d56f51eaSDavid van Moolenbroek
7393*d56f51eaSDavid van Moolenbroek /*
7394*d56f51eaSDavid van Moolenbroek * For management frames, the DA is at 4.
7395*d56f51eaSDavid van Moolenbroek */
7396*d56f51eaSDavid van Moolenbroek b1 = gen_mac_multicast(4);
7397*d56f51eaSDavid van Moolenbroek gen_and(b2, b1);
7398*d56f51eaSDavid van Moolenbroek
7399*d56f51eaSDavid van Moolenbroek /*
7400*d56f51eaSDavid van Moolenbroek * OR that with the checks done for data frames.
7401*d56f51eaSDavid van Moolenbroek * That gives the checks done for management and
7402*d56f51eaSDavid van Moolenbroek * data frames.
7403*d56f51eaSDavid van Moolenbroek */
7404*d56f51eaSDavid van Moolenbroek gen_or(b1, b0);
7405*d56f51eaSDavid van Moolenbroek
7406*d56f51eaSDavid van Moolenbroek /*
7407*d56f51eaSDavid van Moolenbroek * If the low-order bit of the type value is 1,
7408*d56f51eaSDavid van Moolenbroek * this is either a control frame or a frame
7409*d56f51eaSDavid van Moolenbroek * with a reserved type, and thus not a
7410*d56f51eaSDavid van Moolenbroek * frame with an SA.
7411*d56f51eaSDavid van Moolenbroek *
7412*d56f51eaSDavid van Moolenbroek * I.e., check "!(link[0] & 0x04)".
7413*d56f51eaSDavid van Moolenbroek */
7414*d56f51eaSDavid van Moolenbroek s = gen_load_a(OR_LINKHDR, 0, BPF_B);
7415*d56f51eaSDavid van Moolenbroek b1 = new_block(JMP(BPF_JSET));
7416*d56f51eaSDavid van Moolenbroek b1->s.k = 0x04;
7417*d56f51eaSDavid van Moolenbroek b1->stmts = s;
7418*d56f51eaSDavid van Moolenbroek gen_not(b1);
7419*d56f51eaSDavid van Moolenbroek
7420*d56f51eaSDavid van Moolenbroek /*
7421*d56f51eaSDavid van Moolenbroek * AND that with the checks for data and management
7422*d56f51eaSDavid van Moolenbroek * frames.
7423*d56f51eaSDavid van Moolenbroek */
7424*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
7425*d56f51eaSDavid van Moolenbroek return b0;
7426*d56f51eaSDavid van Moolenbroek case DLT_IP_OVER_FC:
7427*d56f51eaSDavid van Moolenbroek b0 = gen_mac_multicast(2);
7428*d56f51eaSDavid van Moolenbroek return b0;
7429*d56f51eaSDavid van Moolenbroek default:
7430*d56f51eaSDavid van Moolenbroek break;
7431*d56f51eaSDavid van Moolenbroek }
7432*d56f51eaSDavid van Moolenbroek /* Link not known to support multicasts */
7433*d56f51eaSDavid van Moolenbroek break;
7434*d56f51eaSDavid van Moolenbroek
7435*d56f51eaSDavid van Moolenbroek case Q_IP:
7436*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(ETHERTYPE_IP);
7437*d56f51eaSDavid van Moolenbroek b1 = gen_cmp_ge(OR_LINKPL, 16, BPF_B, (bpf_int32)224);
7438*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
7439*d56f51eaSDavid van Moolenbroek return b1;
7440*d56f51eaSDavid van Moolenbroek
7441*d56f51eaSDavid van Moolenbroek case Q_IPV6:
7442*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(ETHERTYPE_IPV6);
7443*d56f51eaSDavid van Moolenbroek b1 = gen_cmp(OR_LINKPL, 24, BPF_B, (bpf_int32)255);
7444*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
7445*d56f51eaSDavid van Moolenbroek return b1;
7446*d56f51eaSDavid van Moolenbroek }
7447*d56f51eaSDavid van Moolenbroek bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
7448*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7449*d56f51eaSDavid van Moolenbroek return NULL;
7450*d56f51eaSDavid van Moolenbroek }
7451*d56f51eaSDavid van Moolenbroek
7452*d56f51eaSDavid van Moolenbroek /*
7453*d56f51eaSDavid van Moolenbroek * Filter on inbound (dir == 0) or outbound (dir == 1) traffic.
7454*d56f51eaSDavid van Moolenbroek * Outbound traffic is sent by this machine, while inbound traffic is
7455*d56f51eaSDavid van Moolenbroek * sent by a remote machine (and may include packets destined for a
7456*d56f51eaSDavid van Moolenbroek * unicast or multicast link-layer address we are not subscribing to).
7457*d56f51eaSDavid van Moolenbroek * These are the same definitions implemented by pcap_setdirection().
7458*d56f51eaSDavid van Moolenbroek * Capturing only unicast traffic destined for this host is probably
7459*d56f51eaSDavid van Moolenbroek * better accomplished using a higher-layer filter.
7460*d56f51eaSDavid van Moolenbroek */
7461*d56f51eaSDavid van Moolenbroek struct block *
gen_inbound(dir)7462*d56f51eaSDavid van Moolenbroek gen_inbound(dir)
7463*d56f51eaSDavid van Moolenbroek int dir;
7464*d56f51eaSDavid van Moolenbroek {
7465*d56f51eaSDavid van Moolenbroek register struct block *b0;
7466*d56f51eaSDavid van Moolenbroek
7467*d56f51eaSDavid van Moolenbroek /*
7468*d56f51eaSDavid van Moolenbroek * Only some data link types support inbound/outbound qualifiers.
7469*d56f51eaSDavid van Moolenbroek */
7470*d56f51eaSDavid van Moolenbroek switch (linktype) {
7471*d56f51eaSDavid van Moolenbroek case DLT_SLIP:
7472*d56f51eaSDavid van Moolenbroek b0 = gen_relation(BPF_JEQ,
7473*d56f51eaSDavid van Moolenbroek gen_load(Q_LINK, gen_loadi(0), 1),
7474*d56f51eaSDavid van Moolenbroek gen_loadi(0),
7475*d56f51eaSDavid van Moolenbroek dir);
7476*d56f51eaSDavid van Moolenbroek break;
7477*d56f51eaSDavid van Moolenbroek
7478*d56f51eaSDavid van Moolenbroek case DLT_IPNET:
7479*d56f51eaSDavid van Moolenbroek if (dir) {
7480*d56f51eaSDavid van Moolenbroek /* match outgoing packets */
7481*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKHDR, 2, BPF_H, IPNET_OUTBOUND);
7482*d56f51eaSDavid van Moolenbroek } else {
7483*d56f51eaSDavid van Moolenbroek /* match incoming packets */
7484*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKHDR, 2, BPF_H, IPNET_INBOUND);
7485*d56f51eaSDavid van Moolenbroek }
7486*d56f51eaSDavid van Moolenbroek break;
7487*d56f51eaSDavid van Moolenbroek
7488*d56f51eaSDavid van Moolenbroek case DLT_LINUX_SLL:
7489*d56f51eaSDavid van Moolenbroek /* match outgoing packets */
7490*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKHDR, 0, BPF_H, LINUX_SLL_OUTGOING);
7491*d56f51eaSDavid van Moolenbroek if (!dir) {
7492*d56f51eaSDavid van Moolenbroek /* to filter on inbound traffic, invert the match */
7493*d56f51eaSDavid van Moolenbroek gen_not(b0);
7494*d56f51eaSDavid van Moolenbroek }
7495*d56f51eaSDavid van Moolenbroek break;
7496*d56f51eaSDavid van Moolenbroek
7497*d56f51eaSDavid van Moolenbroek #ifdef HAVE_NET_PFVAR_H
7498*d56f51eaSDavid van Moolenbroek case DLT_PFLOG:
7499*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, dir), BPF_B,
7500*d56f51eaSDavid van Moolenbroek (bpf_int32)((dir == 0) ? PF_IN : PF_OUT));
7501*d56f51eaSDavid van Moolenbroek break;
7502*d56f51eaSDavid van Moolenbroek #endif
7503*d56f51eaSDavid van Moolenbroek
7504*d56f51eaSDavid van Moolenbroek case DLT_PPP_PPPD:
7505*d56f51eaSDavid van Moolenbroek if (dir) {
7506*d56f51eaSDavid van Moolenbroek /* match outgoing packets */
7507*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKHDR, 0, BPF_B, PPP_PPPD_OUT);
7508*d56f51eaSDavid van Moolenbroek } else {
7509*d56f51eaSDavid van Moolenbroek /* match incoming packets */
7510*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKHDR, 0, BPF_B, PPP_PPPD_IN);
7511*d56f51eaSDavid van Moolenbroek }
7512*d56f51eaSDavid van Moolenbroek break;
7513*d56f51eaSDavid van Moolenbroek
7514*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_MFR:
7515*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_MLFR:
7516*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_MLPPP:
7517*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ATM1:
7518*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ATM2:
7519*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_PPPOE:
7520*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_PPPOE_ATM:
7521*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_GGSN:
7522*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ES:
7523*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_MONITOR:
7524*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_SERVICES:
7525*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ETHER:
7526*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_PPP:
7527*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_FRELAY:
7528*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_CHDLC:
7529*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_VP:
7530*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ST:
7531*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ISM:
7532*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_VS:
7533*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_SRX_E2E:
7534*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_FIBRECHANNEL:
7535*d56f51eaSDavid van Moolenbroek case DLT_JUNIPER_ATM_CEMIC:
7536*d56f51eaSDavid van Moolenbroek
7537*d56f51eaSDavid van Moolenbroek /* juniper flags (including direction) are stored
7538*d56f51eaSDavid van Moolenbroek * the byte after the 3-byte magic number */
7539*d56f51eaSDavid van Moolenbroek if (dir) {
7540*d56f51eaSDavid van Moolenbroek /* match outgoing packets */
7541*d56f51eaSDavid van Moolenbroek b0 = gen_mcmp(OR_LINKHDR, 3, BPF_B, 0, 0x01);
7542*d56f51eaSDavid van Moolenbroek } else {
7543*d56f51eaSDavid van Moolenbroek /* match incoming packets */
7544*d56f51eaSDavid van Moolenbroek b0 = gen_mcmp(OR_LINKHDR, 3, BPF_B, 1, 0x01);
7545*d56f51eaSDavid van Moolenbroek }
7546*d56f51eaSDavid van Moolenbroek break;
7547*d56f51eaSDavid van Moolenbroek
7548*d56f51eaSDavid van Moolenbroek default:
7549*d56f51eaSDavid van Moolenbroek /*
7550*d56f51eaSDavid van Moolenbroek * If we have packet meta-data indicating a direction,
7551*d56f51eaSDavid van Moolenbroek * check it, otherwise give up as this link-layer type
7552*d56f51eaSDavid van Moolenbroek * has nothing in the packet data.
7553*d56f51eaSDavid van Moolenbroek */
7554*d56f51eaSDavid van Moolenbroek #if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
7555*d56f51eaSDavid van Moolenbroek /*
7556*d56f51eaSDavid van Moolenbroek * This is Linux with PF_PACKET support.
7557*d56f51eaSDavid van Moolenbroek * If this is a *live* capture, we can look at
7558*d56f51eaSDavid van Moolenbroek * special meta-data in the filter expression;
7559*d56f51eaSDavid van Moolenbroek * if it's a savefile, we can't.
7560*d56f51eaSDavid van Moolenbroek */
7561*d56f51eaSDavid van Moolenbroek if (bpf_pcap->rfile != NULL) {
7562*d56f51eaSDavid van Moolenbroek /* We have a FILE *, so this is a savefile */
7563*d56f51eaSDavid van Moolenbroek bpf_error("inbound/outbound not supported on linktype %d when reading savefiles",
7564*d56f51eaSDavid van Moolenbroek linktype);
7565*d56f51eaSDavid van Moolenbroek b0 = NULL;
7566*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7567*d56f51eaSDavid van Moolenbroek }
7568*d56f51eaSDavid van Moolenbroek /* match outgoing packets */
7569*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKHDR, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H,
7570*d56f51eaSDavid van Moolenbroek PACKET_OUTGOING);
7571*d56f51eaSDavid van Moolenbroek if (!dir) {
7572*d56f51eaSDavid van Moolenbroek /* to filter on inbound traffic, invert the match */
7573*d56f51eaSDavid van Moolenbroek gen_not(b0);
7574*d56f51eaSDavid van Moolenbroek }
7575*d56f51eaSDavid van Moolenbroek #else /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
7576*d56f51eaSDavid van Moolenbroek bpf_error("inbound/outbound not supported on linktype %d",
7577*d56f51eaSDavid van Moolenbroek linktype);
7578*d56f51eaSDavid van Moolenbroek b0 = NULL;
7579*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7580*d56f51eaSDavid van Moolenbroek #endif /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
7581*d56f51eaSDavid van Moolenbroek }
7582*d56f51eaSDavid van Moolenbroek return (b0);
7583*d56f51eaSDavid van Moolenbroek }
7584*d56f51eaSDavid van Moolenbroek
7585*d56f51eaSDavid van Moolenbroek #ifdef HAVE_NET_PFVAR_H
7586*d56f51eaSDavid van Moolenbroek /* PF firewall log matched interface */
7587*d56f51eaSDavid van Moolenbroek struct block *
gen_pf_ifname(const char * ifname)7588*d56f51eaSDavid van Moolenbroek gen_pf_ifname(const char *ifname)
7589*d56f51eaSDavid van Moolenbroek {
7590*d56f51eaSDavid van Moolenbroek struct block *b0;
7591*d56f51eaSDavid van Moolenbroek u_int len, off;
7592*d56f51eaSDavid van Moolenbroek
7593*d56f51eaSDavid van Moolenbroek if (linktype != DLT_PFLOG) {
7594*d56f51eaSDavid van Moolenbroek bpf_error("ifname supported only on PF linktype");
7595*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7596*d56f51eaSDavid van Moolenbroek }
7597*d56f51eaSDavid van Moolenbroek len = sizeof(((struct pfloghdr *)0)->ifname);
7598*d56f51eaSDavid van Moolenbroek off = offsetof(struct pfloghdr, ifname);
7599*d56f51eaSDavid van Moolenbroek if (strlen(ifname) >= len) {
7600*d56f51eaSDavid van Moolenbroek bpf_error("ifname interface names can only be %d characters",
7601*d56f51eaSDavid van Moolenbroek len-1);
7602*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7603*d56f51eaSDavid van Moolenbroek }
7604*d56f51eaSDavid van Moolenbroek b0 = gen_bcmp(OR_LINKHDR, off, strlen(ifname), (const u_char *)ifname);
7605*d56f51eaSDavid van Moolenbroek return (b0);
7606*d56f51eaSDavid van Moolenbroek }
7607*d56f51eaSDavid van Moolenbroek
7608*d56f51eaSDavid van Moolenbroek /* PF firewall log ruleset name */
7609*d56f51eaSDavid van Moolenbroek struct block *
gen_pf_ruleset(char * ruleset)7610*d56f51eaSDavid van Moolenbroek gen_pf_ruleset(char *ruleset)
7611*d56f51eaSDavid van Moolenbroek {
7612*d56f51eaSDavid van Moolenbroek struct block *b0;
7613*d56f51eaSDavid van Moolenbroek
7614*d56f51eaSDavid van Moolenbroek if (linktype != DLT_PFLOG) {
7615*d56f51eaSDavid van Moolenbroek bpf_error("ruleset supported only on PF linktype");
7616*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7617*d56f51eaSDavid van Moolenbroek }
7618*d56f51eaSDavid van Moolenbroek
7619*d56f51eaSDavid van Moolenbroek if (strlen(ruleset) >= sizeof(((struct pfloghdr *)0)->ruleset)) {
7620*d56f51eaSDavid van Moolenbroek bpf_error("ruleset names can only be %ld characters",
7621*d56f51eaSDavid van Moolenbroek (long)(sizeof(((struct pfloghdr *)0)->ruleset) - 1));
7622*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7623*d56f51eaSDavid van Moolenbroek }
7624*d56f51eaSDavid van Moolenbroek
7625*d56f51eaSDavid van Moolenbroek b0 = gen_bcmp(OR_LINKHDR, offsetof(struct pfloghdr, ruleset),
7626*d56f51eaSDavid van Moolenbroek strlen(ruleset), (const u_char *)ruleset);
7627*d56f51eaSDavid van Moolenbroek return (b0);
7628*d56f51eaSDavid van Moolenbroek }
7629*d56f51eaSDavid van Moolenbroek
7630*d56f51eaSDavid van Moolenbroek /* PF firewall log rule number */
7631*d56f51eaSDavid van Moolenbroek struct block *
gen_pf_rnr(int rnr)7632*d56f51eaSDavid van Moolenbroek gen_pf_rnr(int rnr)
7633*d56f51eaSDavid van Moolenbroek {
7634*d56f51eaSDavid van Moolenbroek struct block *b0;
7635*d56f51eaSDavid van Moolenbroek
7636*d56f51eaSDavid van Moolenbroek if (linktype != DLT_PFLOG) {
7637*d56f51eaSDavid van Moolenbroek bpf_error("rnr supported only on PF linktype");
7638*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7639*d56f51eaSDavid van Moolenbroek }
7640*d56f51eaSDavid van Moolenbroek
7641*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, rulenr), BPF_W,
7642*d56f51eaSDavid van Moolenbroek (bpf_int32)rnr);
7643*d56f51eaSDavid van Moolenbroek return (b0);
7644*d56f51eaSDavid van Moolenbroek }
7645*d56f51eaSDavid van Moolenbroek
7646*d56f51eaSDavid van Moolenbroek /* PF firewall log sub-rule number */
7647*d56f51eaSDavid van Moolenbroek struct block *
gen_pf_srnr(int srnr)7648*d56f51eaSDavid van Moolenbroek gen_pf_srnr(int srnr)
7649*d56f51eaSDavid van Moolenbroek {
7650*d56f51eaSDavid van Moolenbroek struct block *b0;
7651*d56f51eaSDavid van Moolenbroek
7652*d56f51eaSDavid van Moolenbroek if (linktype != DLT_PFLOG) {
7653*d56f51eaSDavid van Moolenbroek bpf_error("srnr supported only on PF linktype");
7654*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7655*d56f51eaSDavid van Moolenbroek }
7656*d56f51eaSDavid van Moolenbroek
7657*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, subrulenr), BPF_W,
7658*d56f51eaSDavid van Moolenbroek (bpf_int32)srnr);
7659*d56f51eaSDavid van Moolenbroek return (b0);
7660*d56f51eaSDavid van Moolenbroek }
7661*d56f51eaSDavid van Moolenbroek
7662*d56f51eaSDavid van Moolenbroek /* PF firewall log reason code */
7663*d56f51eaSDavid van Moolenbroek struct block *
gen_pf_reason(int reason)7664*d56f51eaSDavid van Moolenbroek gen_pf_reason(int reason)
7665*d56f51eaSDavid van Moolenbroek {
7666*d56f51eaSDavid van Moolenbroek struct block *b0;
7667*d56f51eaSDavid van Moolenbroek
7668*d56f51eaSDavid van Moolenbroek if (linktype != DLT_PFLOG) {
7669*d56f51eaSDavid van Moolenbroek bpf_error("reason supported only on PF linktype");
7670*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7671*d56f51eaSDavid van Moolenbroek }
7672*d56f51eaSDavid van Moolenbroek
7673*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, reason), BPF_B,
7674*d56f51eaSDavid van Moolenbroek (bpf_int32)reason);
7675*d56f51eaSDavid van Moolenbroek return (b0);
7676*d56f51eaSDavid van Moolenbroek }
7677*d56f51eaSDavid van Moolenbroek
7678*d56f51eaSDavid van Moolenbroek /* PF firewall log action */
7679*d56f51eaSDavid van Moolenbroek struct block *
gen_pf_action(int action)7680*d56f51eaSDavid van Moolenbroek gen_pf_action(int action)
7681*d56f51eaSDavid van Moolenbroek {
7682*d56f51eaSDavid van Moolenbroek struct block *b0;
7683*d56f51eaSDavid van Moolenbroek
7684*d56f51eaSDavid van Moolenbroek if (linktype != DLT_PFLOG) {
7685*d56f51eaSDavid van Moolenbroek bpf_error("action supported only on PF linktype");
7686*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7687*d56f51eaSDavid van Moolenbroek }
7688*d56f51eaSDavid van Moolenbroek
7689*d56f51eaSDavid van Moolenbroek b0 = gen_cmp(OR_LINKHDR, offsetof(struct pfloghdr, action), BPF_B,
7690*d56f51eaSDavid van Moolenbroek (bpf_int32)action);
7691*d56f51eaSDavid van Moolenbroek return (b0);
7692*d56f51eaSDavid van Moolenbroek }
7693*d56f51eaSDavid van Moolenbroek #else /* !HAVE_NET_PFVAR_H */
7694*d56f51eaSDavid van Moolenbroek struct block *
gen_pf_ifname(const char * ifname)7695*d56f51eaSDavid van Moolenbroek gen_pf_ifname(const char *ifname)
7696*d56f51eaSDavid van Moolenbroek {
7697*d56f51eaSDavid van Moolenbroek bpf_error("libpcap was compiled without pf support");
7698*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7699*d56f51eaSDavid van Moolenbroek return (NULL);
7700*d56f51eaSDavid van Moolenbroek }
7701*d56f51eaSDavid van Moolenbroek
7702*d56f51eaSDavid van Moolenbroek struct block *
gen_pf_ruleset(char * ruleset)7703*d56f51eaSDavid van Moolenbroek gen_pf_ruleset(char *ruleset)
7704*d56f51eaSDavid van Moolenbroek {
7705*d56f51eaSDavid van Moolenbroek bpf_error("libpcap was compiled on a machine without pf support");
7706*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7707*d56f51eaSDavid van Moolenbroek return (NULL);
7708*d56f51eaSDavid van Moolenbroek }
7709*d56f51eaSDavid van Moolenbroek
7710*d56f51eaSDavid van Moolenbroek struct block *
gen_pf_rnr(int rnr)7711*d56f51eaSDavid van Moolenbroek gen_pf_rnr(int rnr)
7712*d56f51eaSDavid van Moolenbroek {
7713*d56f51eaSDavid van Moolenbroek bpf_error("libpcap was compiled on a machine without pf support");
7714*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7715*d56f51eaSDavid van Moolenbroek return (NULL);
7716*d56f51eaSDavid van Moolenbroek }
7717*d56f51eaSDavid van Moolenbroek
7718*d56f51eaSDavid van Moolenbroek struct block *
gen_pf_srnr(int srnr)7719*d56f51eaSDavid van Moolenbroek gen_pf_srnr(int srnr)
7720*d56f51eaSDavid van Moolenbroek {
7721*d56f51eaSDavid van Moolenbroek bpf_error("libpcap was compiled on a machine without pf support");
7722*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7723*d56f51eaSDavid van Moolenbroek return (NULL);
7724*d56f51eaSDavid van Moolenbroek }
7725*d56f51eaSDavid van Moolenbroek
7726*d56f51eaSDavid van Moolenbroek struct block *
gen_pf_reason(int reason)7727*d56f51eaSDavid van Moolenbroek gen_pf_reason(int reason)
7728*d56f51eaSDavid van Moolenbroek {
7729*d56f51eaSDavid van Moolenbroek bpf_error("libpcap was compiled on a machine without pf support");
7730*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7731*d56f51eaSDavid van Moolenbroek return (NULL);
7732*d56f51eaSDavid van Moolenbroek }
7733*d56f51eaSDavid van Moolenbroek
7734*d56f51eaSDavid van Moolenbroek struct block *
gen_pf_action(int action)7735*d56f51eaSDavid van Moolenbroek gen_pf_action(int action)
7736*d56f51eaSDavid van Moolenbroek {
7737*d56f51eaSDavid van Moolenbroek bpf_error("libpcap was compiled on a machine without pf support");
7738*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7739*d56f51eaSDavid van Moolenbroek return (NULL);
7740*d56f51eaSDavid van Moolenbroek }
7741*d56f51eaSDavid van Moolenbroek #endif /* HAVE_NET_PFVAR_H */
7742*d56f51eaSDavid van Moolenbroek
7743*d56f51eaSDavid van Moolenbroek /* IEEE 802.11 wireless header */
7744*d56f51eaSDavid van Moolenbroek struct block *
gen_p80211_type(int type,int mask)7745*d56f51eaSDavid van Moolenbroek gen_p80211_type(int type, int mask)
7746*d56f51eaSDavid van Moolenbroek {
7747*d56f51eaSDavid van Moolenbroek struct block *b0;
7748*d56f51eaSDavid van Moolenbroek
7749*d56f51eaSDavid van Moolenbroek switch (linktype) {
7750*d56f51eaSDavid van Moolenbroek
7751*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11:
7752*d56f51eaSDavid van Moolenbroek case DLT_PRISM_HEADER:
7753*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO_AVS:
7754*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO:
7755*d56f51eaSDavid van Moolenbroek b0 = gen_mcmp(OR_LINKHDR, 0, BPF_B, (bpf_int32)type,
7756*d56f51eaSDavid van Moolenbroek (bpf_int32)mask);
7757*d56f51eaSDavid van Moolenbroek break;
7758*d56f51eaSDavid van Moolenbroek
7759*d56f51eaSDavid van Moolenbroek default:
7760*d56f51eaSDavid van Moolenbroek bpf_error("802.11 link-layer types supported only on 802.11");
7761*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7762*d56f51eaSDavid van Moolenbroek }
7763*d56f51eaSDavid van Moolenbroek
7764*d56f51eaSDavid van Moolenbroek return (b0);
7765*d56f51eaSDavid van Moolenbroek }
7766*d56f51eaSDavid van Moolenbroek
7767*d56f51eaSDavid van Moolenbroek struct block *
gen_p80211_fcdir(int fcdir)7768*d56f51eaSDavid van Moolenbroek gen_p80211_fcdir(int fcdir)
7769*d56f51eaSDavid van Moolenbroek {
7770*d56f51eaSDavid van Moolenbroek struct block *b0;
7771*d56f51eaSDavid van Moolenbroek
7772*d56f51eaSDavid van Moolenbroek switch (linktype) {
7773*d56f51eaSDavid van Moolenbroek
7774*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11:
7775*d56f51eaSDavid van Moolenbroek case DLT_PRISM_HEADER:
7776*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO_AVS:
7777*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO:
7778*d56f51eaSDavid van Moolenbroek break;
7779*d56f51eaSDavid van Moolenbroek
7780*d56f51eaSDavid van Moolenbroek default:
7781*d56f51eaSDavid van Moolenbroek bpf_error("frame direction supported only with 802.11 headers");
7782*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7783*d56f51eaSDavid van Moolenbroek }
7784*d56f51eaSDavid van Moolenbroek
7785*d56f51eaSDavid van Moolenbroek b0 = gen_mcmp(OR_LINKHDR, 1, BPF_B, (bpf_int32)fcdir,
7786*d56f51eaSDavid van Moolenbroek (bpf_u_int32)IEEE80211_FC1_DIR_MASK);
7787*d56f51eaSDavid van Moolenbroek
7788*d56f51eaSDavid van Moolenbroek return (b0);
7789*d56f51eaSDavid van Moolenbroek }
7790*d56f51eaSDavid van Moolenbroek
7791*d56f51eaSDavid van Moolenbroek struct block *
gen_acode(eaddr,q)7792*d56f51eaSDavid van Moolenbroek gen_acode(eaddr, q)
7793*d56f51eaSDavid van Moolenbroek register const u_char *eaddr;
7794*d56f51eaSDavid van Moolenbroek struct qual q;
7795*d56f51eaSDavid van Moolenbroek {
7796*d56f51eaSDavid van Moolenbroek switch (linktype) {
7797*d56f51eaSDavid van Moolenbroek
7798*d56f51eaSDavid van Moolenbroek case DLT_ARCNET:
7799*d56f51eaSDavid van Moolenbroek case DLT_ARCNET_LINUX:
7800*d56f51eaSDavid van Moolenbroek if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) &&
7801*d56f51eaSDavid van Moolenbroek q.proto == Q_LINK)
7802*d56f51eaSDavid van Moolenbroek return (gen_ahostop(eaddr, (int)q.dir));
7803*d56f51eaSDavid van Moolenbroek else {
7804*d56f51eaSDavid van Moolenbroek bpf_error("ARCnet address used in non-arc expression");
7805*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7806*d56f51eaSDavid van Moolenbroek }
7807*d56f51eaSDavid van Moolenbroek break;
7808*d56f51eaSDavid van Moolenbroek
7809*d56f51eaSDavid van Moolenbroek default:
7810*d56f51eaSDavid van Moolenbroek bpf_error("aid supported only on ARCnet");
7811*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7812*d56f51eaSDavid van Moolenbroek }
7813*d56f51eaSDavid van Moolenbroek bpf_error("ARCnet address used in non-arc expression");
7814*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7815*d56f51eaSDavid van Moolenbroek return NULL;
7816*d56f51eaSDavid van Moolenbroek }
7817*d56f51eaSDavid van Moolenbroek
7818*d56f51eaSDavid van Moolenbroek static struct block *
gen_ahostop(eaddr,dir)7819*d56f51eaSDavid van Moolenbroek gen_ahostop(eaddr, dir)
7820*d56f51eaSDavid van Moolenbroek register const u_char *eaddr;
7821*d56f51eaSDavid van Moolenbroek register int dir;
7822*d56f51eaSDavid van Moolenbroek {
7823*d56f51eaSDavid van Moolenbroek register struct block *b0, *b1;
7824*d56f51eaSDavid van Moolenbroek
7825*d56f51eaSDavid van Moolenbroek switch (dir) {
7826*d56f51eaSDavid van Moolenbroek /* src comes first, different from Ethernet */
7827*d56f51eaSDavid van Moolenbroek case Q_SRC:
7828*d56f51eaSDavid van Moolenbroek return gen_bcmp(OR_LINKHDR, 0, 1, eaddr);
7829*d56f51eaSDavid van Moolenbroek
7830*d56f51eaSDavid van Moolenbroek case Q_DST:
7831*d56f51eaSDavid van Moolenbroek return gen_bcmp(OR_LINKHDR, 1, 1, eaddr);
7832*d56f51eaSDavid van Moolenbroek
7833*d56f51eaSDavid van Moolenbroek case Q_AND:
7834*d56f51eaSDavid van Moolenbroek b0 = gen_ahostop(eaddr, Q_SRC);
7835*d56f51eaSDavid van Moolenbroek b1 = gen_ahostop(eaddr, Q_DST);
7836*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
7837*d56f51eaSDavid van Moolenbroek return b1;
7838*d56f51eaSDavid van Moolenbroek
7839*d56f51eaSDavid van Moolenbroek case Q_DEFAULT:
7840*d56f51eaSDavid van Moolenbroek case Q_OR:
7841*d56f51eaSDavid van Moolenbroek b0 = gen_ahostop(eaddr, Q_SRC);
7842*d56f51eaSDavid van Moolenbroek b1 = gen_ahostop(eaddr, Q_DST);
7843*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
7844*d56f51eaSDavid van Moolenbroek return b1;
7845*d56f51eaSDavid van Moolenbroek
7846*d56f51eaSDavid van Moolenbroek case Q_ADDR1:
7847*d56f51eaSDavid van Moolenbroek bpf_error("'addr1' is only supported on 802.11");
7848*d56f51eaSDavid van Moolenbroek break;
7849*d56f51eaSDavid van Moolenbroek
7850*d56f51eaSDavid van Moolenbroek case Q_ADDR2:
7851*d56f51eaSDavid van Moolenbroek bpf_error("'addr2' is only supported on 802.11");
7852*d56f51eaSDavid van Moolenbroek break;
7853*d56f51eaSDavid van Moolenbroek
7854*d56f51eaSDavid van Moolenbroek case Q_ADDR3:
7855*d56f51eaSDavid van Moolenbroek bpf_error("'addr3' is only supported on 802.11");
7856*d56f51eaSDavid van Moolenbroek break;
7857*d56f51eaSDavid van Moolenbroek
7858*d56f51eaSDavid van Moolenbroek case Q_ADDR4:
7859*d56f51eaSDavid van Moolenbroek bpf_error("'addr4' is only supported on 802.11");
7860*d56f51eaSDavid van Moolenbroek break;
7861*d56f51eaSDavid van Moolenbroek
7862*d56f51eaSDavid van Moolenbroek case Q_RA:
7863*d56f51eaSDavid van Moolenbroek bpf_error("'ra' is only supported on 802.11");
7864*d56f51eaSDavid van Moolenbroek break;
7865*d56f51eaSDavid van Moolenbroek
7866*d56f51eaSDavid van Moolenbroek case Q_TA:
7867*d56f51eaSDavid van Moolenbroek bpf_error("'ta' is only supported on 802.11");
7868*d56f51eaSDavid van Moolenbroek break;
7869*d56f51eaSDavid van Moolenbroek }
7870*d56f51eaSDavid van Moolenbroek abort();
7871*d56f51eaSDavid van Moolenbroek /* NOTREACHED */
7872*d56f51eaSDavid van Moolenbroek }
7873*d56f51eaSDavid van Moolenbroek
7874*d56f51eaSDavid van Moolenbroek #if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
7875*d56f51eaSDavid van Moolenbroek static struct block *
gen_vlan_bpf_extensions(int vlan_num)7876*d56f51eaSDavid van Moolenbroek gen_vlan_bpf_extensions(int vlan_num)
7877*d56f51eaSDavid van Moolenbroek {
7878*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
7879*d56f51eaSDavid van Moolenbroek struct slist *s;
7880*d56f51eaSDavid van Moolenbroek
7881*d56f51eaSDavid van Moolenbroek /* generate new filter code based on extracting packet
7882*d56f51eaSDavid van Moolenbroek * metadata */
7883*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
7884*d56f51eaSDavid van Moolenbroek s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT;
7885*d56f51eaSDavid van Moolenbroek
7886*d56f51eaSDavid van Moolenbroek b0 = new_block(JMP(BPF_JEQ));
7887*d56f51eaSDavid van Moolenbroek b0->stmts = s;
7888*d56f51eaSDavid van Moolenbroek b0->s.k = 1;
7889*d56f51eaSDavid van Moolenbroek
7890*d56f51eaSDavid van Moolenbroek if (vlan_num >= 0) {
7891*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_LD|BPF_B|BPF_ABS);
7892*d56f51eaSDavid van Moolenbroek s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG;
7893*d56f51eaSDavid van Moolenbroek
7894*d56f51eaSDavid van Moolenbroek b1 = new_block(JMP(BPF_JEQ));
7895*d56f51eaSDavid van Moolenbroek b1->stmts = s;
7896*d56f51eaSDavid van Moolenbroek b1->s.k = (bpf_int32) vlan_num;
7897*d56f51eaSDavid van Moolenbroek
7898*d56f51eaSDavid van Moolenbroek gen_and(b0,b1);
7899*d56f51eaSDavid van Moolenbroek b0 = b1;
7900*d56f51eaSDavid van Moolenbroek }
7901*d56f51eaSDavid van Moolenbroek
7902*d56f51eaSDavid van Moolenbroek return b0;
7903*d56f51eaSDavid van Moolenbroek }
7904*d56f51eaSDavid van Moolenbroek #endif
7905*d56f51eaSDavid van Moolenbroek
7906*d56f51eaSDavid van Moolenbroek static struct block *
gen_vlan_no_bpf_extensions(int vlan_num)7907*d56f51eaSDavid van Moolenbroek gen_vlan_no_bpf_extensions(int vlan_num)
7908*d56f51eaSDavid van Moolenbroek {
7909*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
7910*d56f51eaSDavid van Moolenbroek
7911*d56f51eaSDavid van Moolenbroek /* check for VLAN, including QinQ */
7912*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(ETHERTYPE_8021Q);
7913*d56f51eaSDavid van Moolenbroek b1 = gen_linktype(ETHERTYPE_8021QINQ);
7914*d56f51eaSDavid van Moolenbroek gen_or(b0,b1);
7915*d56f51eaSDavid van Moolenbroek b0 = b1;
7916*d56f51eaSDavid van Moolenbroek
7917*d56f51eaSDavid van Moolenbroek /* If a specific VLAN is requested, check VLAN id */
7918*d56f51eaSDavid van Moolenbroek if (vlan_num >= 0) {
7919*d56f51eaSDavid van Moolenbroek b1 = gen_mcmp(OR_LINKPL, 0, BPF_H,
7920*d56f51eaSDavid van Moolenbroek (bpf_int32)vlan_num, 0x0fff);
7921*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
7922*d56f51eaSDavid van Moolenbroek b0 = b1;
7923*d56f51eaSDavid van Moolenbroek }
7924*d56f51eaSDavid van Moolenbroek
7925*d56f51eaSDavid van Moolenbroek /*
7926*d56f51eaSDavid van Moolenbroek * The payload follows the full header, including the
7927*d56f51eaSDavid van Moolenbroek * VLAN tags, so skip past this VLAN tag.
7928*d56f51eaSDavid van Moolenbroek */
7929*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part += 4;
7930*d56f51eaSDavid van Moolenbroek
7931*d56f51eaSDavid van Moolenbroek /*
7932*d56f51eaSDavid van Moolenbroek * The link-layer type information follows the VLAN tags, so
7933*d56f51eaSDavid van Moolenbroek * skip past this VLAN tag.
7934*d56f51eaSDavid van Moolenbroek */
7935*d56f51eaSDavid van Moolenbroek off_linktype.constant_part += 4;
7936*d56f51eaSDavid van Moolenbroek
7937*d56f51eaSDavid van Moolenbroek return b0;
7938*d56f51eaSDavid van Moolenbroek }
7939*d56f51eaSDavid van Moolenbroek
7940*d56f51eaSDavid van Moolenbroek /*
7941*d56f51eaSDavid van Moolenbroek * support IEEE 802.1Q VLAN trunk over ethernet
7942*d56f51eaSDavid van Moolenbroek */
7943*d56f51eaSDavid van Moolenbroek struct block *
gen_vlan(vlan_num)7944*d56f51eaSDavid van Moolenbroek gen_vlan(vlan_num)
7945*d56f51eaSDavid van Moolenbroek int vlan_num;
7946*d56f51eaSDavid van Moolenbroek {
7947*d56f51eaSDavid van Moolenbroek struct block *b0;
7948*d56f51eaSDavid van Moolenbroek
7949*d56f51eaSDavid van Moolenbroek /* can't check for VLAN-encapsulated packets inside MPLS */
7950*d56f51eaSDavid van Moolenbroek if (label_stack_depth > 0)
7951*d56f51eaSDavid van Moolenbroek bpf_error("no VLAN match after MPLS");
7952*d56f51eaSDavid van Moolenbroek
7953*d56f51eaSDavid van Moolenbroek /*
7954*d56f51eaSDavid van Moolenbroek * Check for a VLAN packet, and then change the offsets to point
7955*d56f51eaSDavid van Moolenbroek * to the type and data fields within the VLAN packet. Just
7956*d56f51eaSDavid van Moolenbroek * increment the offsets, so that we can support a hierarchy, e.g.
7957*d56f51eaSDavid van Moolenbroek * "vlan 300 && vlan 200" to capture VLAN 200 encapsulated within
7958*d56f51eaSDavid van Moolenbroek * VLAN 100.
7959*d56f51eaSDavid van Moolenbroek *
7960*d56f51eaSDavid van Moolenbroek * XXX - this is a bit of a kludge. If we were to split the
7961*d56f51eaSDavid van Moolenbroek * compiler into a parser that parses an expression and
7962*d56f51eaSDavid van Moolenbroek * generates an expression tree, and a code generator that
7963*d56f51eaSDavid van Moolenbroek * takes an expression tree (which could come from our
7964*d56f51eaSDavid van Moolenbroek * parser or from some other parser) and generates BPF code,
7965*d56f51eaSDavid van Moolenbroek * we could perhaps make the offsets parameters of routines
7966*d56f51eaSDavid van Moolenbroek * and, in the handler for an "AND" node, pass to subnodes
7967*d56f51eaSDavid van Moolenbroek * other than the VLAN node the adjusted offsets.
7968*d56f51eaSDavid van Moolenbroek *
7969*d56f51eaSDavid van Moolenbroek * This would mean that "vlan" would, instead of changing the
7970*d56f51eaSDavid van Moolenbroek * behavior of *all* tests after it, change only the behavior
7971*d56f51eaSDavid van Moolenbroek * of tests ANDed with it. That would change the documented
7972*d56f51eaSDavid van Moolenbroek * semantics of "vlan", which might break some expressions.
7973*d56f51eaSDavid van Moolenbroek * However, it would mean that "(vlan and ip) or ip" would check
7974*d56f51eaSDavid van Moolenbroek * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
7975*d56f51eaSDavid van Moolenbroek * checking only for VLAN-encapsulated IP, so that could still
7976*d56f51eaSDavid van Moolenbroek * be considered worth doing; it wouldn't break expressions
7977*d56f51eaSDavid van Moolenbroek * that are of the form "vlan and ..." or "vlan N and ...",
7978*d56f51eaSDavid van Moolenbroek * which I suspect are the most common expressions involving
7979*d56f51eaSDavid van Moolenbroek * "vlan". "vlan or ..." doesn't necessarily do what the user
7980*d56f51eaSDavid van Moolenbroek * would really want, now, as all the "or ..." tests would
7981*d56f51eaSDavid van Moolenbroek * be done assuming a VLAN, even though the "or" could be viewed
7982*d56f51eaSDavid van Moolenbroek * as meaning "or, if this isn't a VLAN packet...".
7983*d56f51eaSDavid van Moolenbroek */
7984*d56f51eaSDavid van Moolenbroek switch (linktype) {
7985*d56f51eaSDavid van Moolenbroek
7986*d56f51eaSDavid van Moolenbroek case DLT_EN10MB:
7987*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER:
7988*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER_TRANSPARENT:
7989*d56f51eaSDavid van Moolenbroek #if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
7990*d56f51eaSDavid van Moolenbroek /* Verify that this is the outer part of the packet and
7991*d56f51eaSDavid van Moolenbroek * not encapsulated somehow. */
7992*d56f51eaSDavid van Moolenbroek if (vlan_stack_depth == 0 && !off_linkhdr.is_variable &&
7993*d56f51eaSDavid van Moolenbroek off_linkhdr.constant_part ==
7994*d56f51eaSDavid van Moolenbroek off_outermostlinkhdr.constant_part) {
7995*d56f51eaSDavid van Moolenbroek /*
7996*d56f51eaSDavid van Moolenbroek * Do we need special VLAN handling?
7997*d56f51eaSDavid van Moolenbroek */
7998*d56f51eaSDavid van Moolenbroek if (bpf_pcap->bpf_codegen_flags & BPF_SPECIAL_VLAN_HANDLING)
7999*d56f51eaSDavid van Moolenbroek b0 = gen_vlan_bpf_extensions(vlan_num);
8000*d56f51eaSDavid van Moolenbroek else
8001*d56f51eaSDavid van Moolenbroek b0 = gen_vlan_no_bpf_extensions(vlan_num);
8002*d56f51eaSDavid van Moolenbroek } else
8003*d56f51eaSDavid van Moolenbroek #endif
8004*d56f51eaSDavid van Moolenbroek b0 = gen_vlan_no_bpf_extensions(vlan_num);
8005*d56f51eaSDavid van Moolenbroek break;
8006*d56f51eaSDavid van Moolenbroek
8007*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11:
8008*d56f51eaSDavid van Moolenbroek case DLT_PRISM_HEADER:
8009*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO_AVS:
8010*d56f51eaSDavid van Moolenbroek case DLT_IEEE802_11_RADIO:
8011*d56f51eaSDavid van Moolenbroek b0 = gen_vlan_no_bpf_extensions(vlan_num);
8012*d56f51eaSDavid van Moolenbroek break;
8013*d56f51eaSDavid van Moolenbroek
8014*d56f51eaSDavid van Moolenbroek default:
8015*d56f51eaSDavid van Moolenbroek bpf_error("no VLAN support for data link type %d",
8016*d56f51eaSDavid van Moolenbroek linktype);
8017*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
8018*d56f51eaSDavid van Moolenbroek }
8019*d56f51eaSDavid van Moolenbroek
8020*d56f51eaSDavid van Moolenbroek vlan_stack_depth++;
8021*d56f51eaSDavid van Moolenbroek
8022*d56f51eaSDavid van Moolenbroek return (b0);
8023*d56f51eaSDavid van Moolenbroek }
8024*d56f51eaSDavid van Moolenbroek
8025*d56f51eaSDavid van Moolenbroek /*
8026*d56f51eaSDavid van Moolenbroek * support for MPLS
8027*d56f51eaSDavid van Moolenbroek */
8028*d56f51eaSDavid van Moolenbroek struct block *
gen_mpls(label_num)8029*d56f51eaSDavid van Moolenbroek gen_mpls(label_num)
8030*d56f51eaSDavid van Moolenbroek int label_num;
8031*d56f51eaSDavid van Moolenbroek {
8032*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
8033*d56f51eaSDavid van Moolenbroek
8034*d56f51eaSDavid van Moolenbroek if (label_stack_depth > 0) {
8035*d56f51eaSDavid van Moolenbroek /* just match the bottom-of-stack bit clear */
8036*d56f51eaSDavid van Moolenbroek b0 = gen_mcmp(OR_PREVMPLSHDR, 2, BPF_B, 0, 0x01);
8037*d56f51eaSDavid van Moolenbroek } else {
8038*d56f51eaSDavid van Moolenbroek /*
8039*d56f51eaSDavid van Moolenbroek * We're not in an MPLS stack yet, so check the link-layer
8040*d56f51eaSDavid van Moolenbroek * type against MPLS.
8041*d56f51eaSDavid van Moolenbroek */
8042*d56f51eaSDavid van Moolenbroek switch (linktype) {
8043*d56f51eaSDavid van Moolenbroek
8044*d56f51eaSDavid van Moolenbroek case DLT_C_HDLC: /* fall through */
8045*d56f51eaSDavid van Moolenbroek case DLT_EN10MB:
8046*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER:
8047*d56f51eaSDavid van Moolenbroek case DLT_NETANALYZER_TRANSPARENT:
8048*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(ETHERTYPE_MPLS);
8049*d56f51eaSDavid van Moolenbroek break;
8050*d56f51eaSDavid van Moolenbroek
8051*d56f51eaSDavid van Moolenbroek case DLT_PPP:
8052*d56f51eaSDavid van Moolenbroek b0 = gen_linktype(PPP_MPLS_UCAST);
8053*d56f51eaSDavid van Moolenbroek break;
8054*d56f51eaSDavid van Moolenbroek
8055*d56f51eaSDavid van Moolenbroek /* FIXME add other DLT_s ...
8056*d56f51eaSDavid van Moolenbroek * for Frame-Relay/and ATM this may get messy due to SNAP headers
8057*d56f51eaSDavid van Moolenbroek * leave it for now */
8058*d56f51eaSDavid van Moolenbroek
8059*d56f51eaSDavid van Moolenbroek default:
8060*d56f51eaSDavid van Moolenbroek bpf_error("no MPLS support for data link type %d",
8061*d56f51eaSDavid van Moolenbroek linktype);
8062*d56f51eaSDavid van Moolenbroek b0 = NULL;
8063*d56f51eaSDavid van Moolenbroek /*NOTREACHED*/
8064*d56f51eaSDavid van Moolenbroek break;
8065*d56f51eaSDavid van Moolenbroek }
8066*d56f51eaSDavid van Moolenbroek }
8067*d56f51eaSDavid van Moolenbroek
8068*d56f51eaSDavid van Moolenbroek /* If a specific MPLS label is requested, check it */
8069*d56f51eaSDavid van Moolenbroek if (label_num >= 0) {
8070*d56f51eaSDavid van Moolenbroek label_num = label_num << 12; /* label is shifted 12 bits on the wire */
8071*d56f51eaSDavid van Moolenbroek b1 = gen_mcmp(OR_LINKPL, 0, BPF_W, (bpf_int32)label_num,
8072*d56f51eaSDavid van Moolenbroek 0xfffff000); /* only compare the first 20 bits */
8073*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
8074*d56f51eaSDavid van Moolenbroek b0 = b1;
8075*d56f51eaSDavid van Moolenbroek }
8076*d56f51eaSDavid van Moolenbroek
8077*d56f51eaSDavid van Moolenbroek /*
8078*d56f51eaSDavid van Moolenbroek * Change the offsets to point to the type and data fields within
8079*d56f51eaSDavid van Moolenbroek * the MPLS packet. Just increment the offsets, so that we
8080*d56f51eaSDavid van Moolenbroek * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to
8081*d56f51eaSDavid van Moolenbroek * capture packets with an outer label of 100000 and an inner
8082*d56f51eaSDavid van Moolenbroek * label of 1024.
8083*d56f51eaSDavid van Moolenbroek *
8084*d56f51eaSDavid van Moolenbroek * Increment the MPLS stack depth as well; this indicates that
8085*d56f51eaSDavid van Moolenbroek * we're checking MPLS-encapsulated headers, to make sure higher
8086*d56f51eaSDavid van Moolenbroek * level code generators don't try to match against IP-related
8087*d56f51eaSDavid van Moolenbroek * protocols such as Q_ARP, Q_RARP etc.
8088*d56f51eaSDavid van Moolenbroek *
8089*d56f51eaSDavid van Moolenbroek * XXX - this is a bit of a kludge. See comments in gen_vlan().
8090*d56f51eaSDavid van Moolenbroek */
8091*d56f51eaSDavid van Moolenbroek off_nl_nosnap += 4;
8092*d56f51eaSDavid van Moolenbroek off_nl += 4;
8093*d56f51eaSDavid van Moolenbroek label_stack_depth++;
8094*d56f51eaSDavid van Moolenbroek return (b0);
8095*d56f51eaSDavid van Moolenbroek }
8096*d56f51eaSDavid van Moolenbroek
8097*d56f51eaSDavid van Moolenbroek /*
8098*d56f51eaSDavid van Moolenbroek * Support PPPOE discovery and session.
8099*d56f51eaSDavid van Moolenbroek */
8100*d56f51eaSDavid van Moolenbroek struct block *
gen_pppoed()8101*d56f51eaSDavid van Moolenbroek gen_pppoed()
8102*d56f51eaSDavid van Moolenbroek {
8103*d56f51eaSDavid van Moolenbroek /* check for PPPoE discovery */
8104*d56f51eaSDavid van Moolenbroek return gen_linktype((bpf_int32)ETHERTYPE_PPPOED);
8105*d56f51eaSDavid van Moolenbroek }
8106*d56f51eaSDavid van Moolenbroek
8107*d56f51eaSDavid van Moolenbroek struct block *
gen_pppoes(sess_num)8108*d56f51eaSDavid van Moolenbroek gen_pppoes(sess_num)
8109*d56f51eaSDavid van Moolenbroek int sess_num;
8110*d56f51eaSDavid van Moolenbroek {
8111*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
8112*d56f51eaSDavid van Moolenbroek
8113*d56f51eaSDavid van Moolenbroek /*
8114*d56f51eaSDavid van Moolenbroek * Test against the PPPoE session link-layer type.
8115*d56f51eaSDavid van Moolenbroek */
8116*d56f51eaSDavid van Moolenbroek b0 = gen_linktype((bpf_int32)ETHERTYPE_PPPOES);
8117*d56f51eaSDavid van Moolenbroek
8118*d56f51eaSDavid van Moolenbroek /* If a specific session is requested, check PPPoE session id */
8119*d56f51eaSDavid van Moolenbroek if (sess_num >= 0) {
8120*d56f51eaSDavid van Moolenbroek b1 = gen_mcmp(OR_LINKPL, 0, BPF_W,
8121*d56f51eaSDavid van Moolenbroek (bpf_int32)sess_num, 0x0000ffff);
8122*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
8123*d56f51eaSDavid van Moolenbroek b0 = b1;
8124*d56f51eaSDavid van Moolenbroek }
8125*d56f51eaSDavid van Moolenbroek
8126*d56f51eaSDavid van Moolenbroek /*
8127*d56f51eaSDavid van Moolenbroek * Change the offsets to point to the type and data fields within
8128*d56f51eaSDavid van Moolenbroek * the PPP packet, and note that this is PPPoE rather than
8129*d56f51eaSDavid van Moolenbroek * raw PPP.
8130*d56f51eaSDavid van Moolenbroek *
8131*d56f51eaSDavid van Moolenbroek * XXX - this is a bit of a kludge. If we were to split the
8132*d56f51eaSDavid van Moolenbroek * compiler into a parser that parses an expression and
8133*d56f51eaSDavid van Moolenbroek * generates an expression tree, and a code generator that
8134*d56f51eaSDavid van Moolenbroek * takes an expression tree (which could come from our
8135*d56f51eaSDavid van Moolenbroek * parser or from some other parser) and generates BPF code,
8136*d56f51eaSDavid van Moolenbroek * we could perhaps make the offsets parameters of routines
8137*d56f51eaSDavid van Moolenbroek * and, in the handler for an "AND" node, pass to subnodes
8138*d56f51eaSDavid van Moolenbroek * other than the PPPoE node the adjusted offsets.
8139*d56f51eaSDavid van Moolenbroek *
8140*d56f51eaSDavid van Moolenbroek * This would mean that "pppoes" would, instead of changing the
8141*d56f51eaSDavid van Moolenbroek * behavior of *all* tests after it, change only the behavior
8142*d56f51eaSDavid van Moolenbroek * of tests ANDed with it. That would change the documented
8143*d56f51eaSDavid van Moolenbroek * semantics of "pppoes", which might break some expressions.
8144*d56f51eaSDavid van Moolenbroek * However, it would mean that "(pppoes and ip) or ip" would check
8145*d56f51eaSDavid van Moolenbroek * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
8146*d56f51eaSDavid van Moolenbroek * checking only for VLAN-encapsulated IP, so that could still
8147*d56f51eaSDavid van Moolenbroek * be considered worth doing; it wouldn't break expressions
8148*d56f51eaSDavid van Moolenbroek * that are of the form "pppoes and ..." which I suspect are the
8149*d56f51eaSDavid van Moolenbroek * most common expressions involving "pppoes". "pppoes or ..."
8150*d56f51eaSDavid van Moolenbroek * doesn't necessarily do what the user would really want, now,
8151*d56f51eaSDavid van Moolenbroek * as all the "or ..." tests would be done assuming PPPoE, even
8152*d56f51eaSDavid van Moolenbroek * though the "or" could be viewed as meaning "or, if this isn't
8153*d56f51eaSDavid van Moolenbroek * a PPPoE packet...".
8154*d56f51eaSDavid van Moolenbroek *
8155*d56f51eaSDavid van Moolenbroek * The "network-layer" protocol is PPPoE, which has a 6-byte
8156*d56f51eaSDavid van Moolenbroek * PPPoE header, followed by a PPP packet.
8157*d56f51eaSDavid van Moolenbroek *
8158*d56f51eaSDavid van Moolenbroek * There is no HDLC encapsulation for the PPP packet (it's
8159*d56f51eaSDavid van Moolenbroek * encapsulated in PPPoES instead), so the link-layer type
8160*d56f51eaSDavid van Moolenbroek * starts at the first byte of the PPP packet. For PPPoE,
8161*d56f51eaSDavid van Moolenbroek * that offset is relative to the beginning of the total
8162*d56f51eaSDavid van Moolenbroek * link-layer payload, including any 802.2 LLC header, so
8163*d56f51eaSDavid van Moolenbroek * it's 6 bytes past off_nl.
8164*d56f51eaSDavid van Moolenbroek */
8165*d56f51eaSDavid van Moolenbroek PUSH_LINKHDR(DLT_PPP, off_linkpl.is_variable,
8166*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part + off_nl + 6, /* 6 bytes past the PPPoE header */
8167*d56f51eaSDavid van Moolenbroek off_linkpl.reg);
8168*d56f51eaSDavid van Moolenbroek
8169*d56f51eaSDavid van Moolenbroek off_linktype = off_linkhdr;
8170*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = off_linkhdr.constant_part + 2;
8171*d56f51eaSDavid van Moolenbroek
8172*d56f51eaSDavid van Moolenbroek off_nl = 0;
8173*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 0; /* no 802.2 LLC */
8174*d56f51eaSDavid van Moolenbroek
8175*d56f51eaSDavid van Moolenbroek return b0;
8176*d56f51eaSDavid van Moolenbroek }
8177*d56f51eaSDavid van Moolenbroek
8178*d56f51eaSDavid van Moolenbroek /* Check that this is Geneve and the VNI is correct if
8179*d56f51eaSDavid van Moolenbroek * specified. Parameterized to handle both IPv4 and IPv6. */
8180*d56f51eaSDavid van Moolenbroek static struct block *
gen_geneve_check(struct block * (* gen_portfn)(int,int,int),enum e_offrel offrel,int vni)8181*d56f51eaSDavid van Moolenbroek gen_geneve_check(struct block *(*gen_portfn)(int, int, int),
8182*d56f51eaSDavid van Moolenbroek enum e_offrel offrel, int vni)
8183*d56f51eaSDavid van Moolenbroek {
8184*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
8185*d56f51eaSDavid van Moolenbroek
8186*d56f51eaSDavid van Moolenbroek b0 = gen_portfn(GENEVE_PORT, IPPROTO_UDP, Q_DST);
8187*d56f51eaSDavid van Moolenbroek
8188*d56f51eaSDavid van Moolenbroek /* Check that we are operating on version 0. Otherwise, we
8189*d56f51eaSDavid van Moolenbroek * can't decode the rest of the fields. The version is 2 bits
8190*d56f51eaSDavid van Moolenbroek * in the first byte of the Geneve header. */
8191*d56f51eaSDavid van Moolenbroek b1 = gen_mcmp(offrel, 8, BPF_B, (bpf_int32)0, 0xc0);
8192*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
8193*d56f51eaSDavid van Moolenbroek b0 = b1;
8194*d56f51eaSDavid van Moolenbroek
8195*d56f51eaSDavid van Moolenbroek if (vni >= 0) {
8196*d56f51eaSDavid van Moolenbroek vni <<= 8; /* VNI is in the upper 3 bytes */
8197*d56f51eaSDavid van Moolenbroek b1 = gen_mcmp(offrel, 12, BPF_W, (bpf_int32)vni,
8198*d56f51eaSDavid van Moolenbroek 0xffffff00);
8199*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
8200*d56f51eaSDavid van Moolenbroek b0 = b1;
8201*d56f51eaSDavid van Moolenbroek }
8202*d56f51eaSDavid van Moolenbroek
8203*d56f51eaSDavid van Moolenbroek return b0;
8204*d56f51eaSDavid van Moolenbroek }
8205*d56f51eaSDavid van Moolenbroek
8206*d56f51eaSDavid van Moolenbroek /* The IPv4 and IPv6 Geneve checks need to do two things:
8207*d56f51eaSDavid van Moolenbroek * - Verify that this actually is Geneve with the right VNI.
8208*d56f51eaSDavid van Moolenbroek * - Place the IP header length (plus variable link prefix if
8209*d56f51eaSDavid van Moolenbroek * needed) into register A to be used later to compute
8210*d56f51eaSDavid van Moolenbroek * the inner packet offsets. */
8211*d56f51eaSDavid van Moolenbroek static struct block *
gen_geneve4(int vni)8212*d56f51eaSDavid van Moolenbroek gen_geneve4(int vni)
8213*d56f51eaSDavid van Moolenbroek {
8214*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
8215*d56f51eaSDavid van Moolenbroek struct slist *s, *s1;
8216*d56f51eaSDavid van Moolenbroek
8217*d56f51eaSDavid van Moolenbroek b0 = gen_geneve_check(gen_port, OR_TRAN_IPV4, vni);
8218*d56f51eaSDavid van Moolenbroek
8219*d56f51eaSDavid van Moolenbroek /* Load the IP header length into A. */
8220*d56f51eaSDavid van Moolenbroek s = gen_loadx_iphdrlen();
8221*d56f51eaSDavid van Moolenbroek
8222*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_MISC|BPF_TXA);
8223*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8224*d56f51eaSDavid van Moolenbroek
8225*d56f51eaSDavid van Moolenbroek /* Forcibly append these statements to the true condition
8226*d56f51eaSDavid van Moolenbroek * of the protocol check by creating a new block that is
8227*d56f51eaSDavid van Moolenbroek * always true and ANDing them. */
8228*d56f51eaSDavid van Moolenbroek b1 = new_block(BPF_JMP|BPF_JEQ|BPF_X);
8229*d56f51eaSDavid van Moolenbroek b1->stmts = s;
8230*d56f51eaSDavid van Moolenbroek b1->s.k = 0;
8231*d56f51eaSDavid van Moolenbroek
8232*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
8233*d56f51eaSDavid van Moolenbroek
8234*d56f51eaSDavid van Moolenbroek return b1;
8235*d56f51eaSDavid van Moolenbroek }
8236*d56f51eaSDavid van Moolenbroek
8237*d56f51eaSDavid van Moolenbroek static struct block *
gen_geneve6(int vni)8238*d56f51eaSDavid van Moolenbroek gen_geneve6(int vni)
8239*d56f51eaSDavid van Moolenbroek {
8240*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
8241*d56f51eaSDavid van Moolenbroek struct slist *s, *s1;
8242*d56f51eaSDavid van Moolenbroek
8243*d56f51eaSDavid van Moolenbroek b0 = gen_geneve_check(gen_port6, OR_TRAN_IPV6, vni);
8244*d56f51eaSDavid van Moolenbroek
8245*d56f51eaSDavid van Moolenbroek /* Load the IP header length. We need to account for a
8246*d56f51eaSDavid van Moolenbroek * variable length link prefix if there is one. */
8247*d56f51eaSDavid van Moolenbroek s = gen_abs_offset_varpart(&off_linkpl);
8248*d56f51eaSDavid van Moolenbroek if (s) {
8249*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_LD|BPF_IMM);
8250*d56f51eaSDavid van Moolenbroek s1->s.k = 40;
8251*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8252*d56f51eaSDavid van Moolenbroek
8253*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_X);
8254*d56f51eaSDavid van Moolenbroek s1->s.k = 0;
8255*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8256*d56f51eaSDavid van Moolenbroek } else {
8257*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_LD|BPF_IMM);
8258*d56f51eaSDavid van Moolenbroek s->s.k = 40;;
8259*d56f51eaSDavid van Moolenbroek }
8260*d56f51eaSDavid van Moolenbroek
8261*d56f51eaSDavid van Moolenbroek /* Forcibly append these statements to the true condition
8262*d56f51eaSDavid van Moolenbroek * of the protocol check by creating a new block that is
8263*d56f51eaSDavid van Moolenbroek * always true and ANDing them. */
8264*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_MISC|BPF_TAX);
8265*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8266*d56f51eaSDavid van Moolenbroek
8267*d56f51eaSDavid van Moolenbroek b1 = new_block(BPF_JMP|BPF_JEQ|BPF_X);
8268*d56f51eaSDavid van Moolenbroek b1->stmts = s;
8269*d56f51eaSDavid van Moolenbroek b1->s.k = 0;
8270*d56f51eaSDavid van Moolenbroek
8271*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
8272*d56f51eaSDavid van Moolenbroek
8273*d56f51eaSDavid van Moolenbroek return b1;
8274*d56f51eaSDavid van Moolenbroek }
8275*d56f51eaSDavid van Moolenbroek
8276*d56f51eaSDavid van Moolenbroek /* We need to store three values based on the Geneve header::
8277*d56f51eaSDavid van Moolenbroek * - The offset of the linktype.
8278*d56f51eaSDavid van Moolenbroek * - The offset of the end of the Geneve header.
8279*d56f51eaSDavid van Moolenbroek * - The offset of the end of the encapsulated MAC header. */
8280*d56f51eaSDavid van Moolenbroek static struct slist *
gen_geneve_offsets(void)8281*d56f51eaSDavid van Moolenbroek gen_geneve_offsets(void)
8282*d56f51eaSDavid van Moolenbroek {
8283*d56f51eaSDavid van Moolenbroek struct slist *s, *s1, *s_proto;
8284*d56f51eaSDavid van Moolenbroek
8285*d56f51eaSDavid van Moolenbroek /* First we need to calculate the offset of the Geneve header
8286*d56f51eaSDavid van Moolenbroek * itself. This is composed of the IP header previously calculated
8287*d56f51eaSDavid van Moolenbroek * (include any variable link prefix) and stored in A plus the
8288*d56f51eaSDavid van Moolenbroek * fixed sized headers (fixed link prefix, MAC length, and UDP
8289*d56f51eaSDavid van Moolenbroek * header). */
8290*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
8291*d56f51eaSDavid van Moolenbroek s->s.k = off_linkpl.constant_part + off_nl + 8;
8292*d56f51eaSDavid van Moolenbroek
8293*d56f51eaSDavid van Moolenbroek /* Stash this in X since we'll need it later. */
8294*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_MISC|BPF_TAX);
8295*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8296*d56f51eaSDavid van Moolenbroek
8297*d56f51eaSDavid van Moolenbroek /* The EtherType in Geneve is 2 bytes in. Calculate this and
8298*d56f51eaSDavid van Moolenbroek * store it. */
8299*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
8300*d56f51eaSDavid van Moolenbroek s1->s.k = 2;
8301*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8302*d56f51eaSDavid van Moolenbroek
8303*d56f51eaSDavid van Moolenbroek off_linktype.reg = alloc_reg();
8304*d56f51eaSDavid van Moolenbroek off_linktype.is_variable = 1;
8305*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = 0;
8306*d56f51eaSDavid van Moolenbroek
8307*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_ST);
8308*d56f51eaSDavid van Moolenbroek s1->s.k = off_linktype.reg;
8309*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8310*d56f51eaSDavid van Moolenbroek
8311*d56f51eaSDavid van Moolenbroek /* Load the Geneve option length and mask and shift to get the
8312*d56f51eaSDavid van Moolenbroek * number of bytes. It is stored in the first byte of the Geneve
8313*d56f51eaSDavid van Moolenbroek * header. */
8314*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_LD|BPF_IND|BPF_B);
8315*d56f51eaSDavid van Moolenbroek s1->s.k = 0;
8316*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8317*d56f51eaSDavid van Moolenbroek
8318*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
8319*d56f51eaSDavid van Moolenbroek s1->s.k = 0x3f;
8320*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8321*d56f51eaSDavid van Moolenbroek
8322*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
8323*d56f51eaSDavid van Moolenbroek s1->s.k = 4;
8324*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8325*d56f51eaSDavid van Moolenbroek
8326*d56f51eaSDavid van Moolenbroek /* Add in the rest of the Geneve base header. */
8327*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
8328*d56f51eaSDavid van Moolenbroek s1->s.k = 8;
8329*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8330*d56f51eaSDavid van Moolenbroek
8331*d56f51eaSDavid van Moolenbroek /* Add the Geneve header length to its offset and store. */
8332*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_X);
8333*d56f51eaSDavid van Moolenbroek s1->s.k = 0;
8334*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8335*d56f51eaSDavid van Moolenbroek
8336*d56f51eaSDavid van Moolenbroek /* Set the encapsulated type as Ethernet. Even though we may
8337*d56f51eaSDavid van Moolenbroek * not actually have Ethernet inside there are two reasons this
8338*d56f51eaSDavid van Moolenbroek * is useful:
8339*d56f51eaSDavid van Moolenbroek * - The linktype field is always in EtherType format regardless
8340*d56f51eaSDavid van Moolenbroek * of whether it is in Geneve or an inner Ethernet frame.
8341*d56f51eaSDavid van Moolenbroek * - The only link layer that we have specific support for is
8342*d56f51eaSDavid van Moolenbroek * Ethernet. We will confirm that the packet actually is
8343*d56f51eaSDavid van Moolenbroek * Ethernet at runtime before executing these checks. */
8344*d56f51eaSDavid van Moolenbroek PUSH_LINKHDR(DLT_EN10MB, 1, 0, alloc_reg());
8345*d56f51eaSDavid van Moolenbroek
8346*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_ST);
8347*d56f51eaSDavid van Moolenbroek s1->s.k = off_linkhdr.reg;
8348*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8349*d56f51eaSDavid van Moolenbroek
8350*d56f51eaSDavid van Moolenbroek /* Calculate whether we have an Ethernet header or just raw IP/
8351*d56f51eaSDavid van Moolenbroek * MPLS/etc. If we have Ethernet, advance the end of the MAC offset
8352*d56f51eaSDavid van Moolenbroek * and linktype by 14 bytes so that the network header can be found
8353*d56f51eaSDavid van Moolenbroek * seamlessly. Otherwise, keep what we've calculated already. */
8354*d56f51eaSDavid van Moolenbroek
8355*d56f51eaSDavid van Moolenbroek /* We have a bare jmp so we can't use the optimizer. */
8356*d56f51eaSDavid van Moolenbroek no_optimize = 1;
8357*d56f51eaSDavid van Moolenbroek
8358*d56f51eaSDavid van Moolenbroek /* Load the EtherType in the Geneve header, 2 bytes in. */
8359*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_LD|BPF_IND|BPF_H);
8360*d56f51eaSDavid van Moolenbroek s1->s.k = 2;
8361*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8362*d56f51eaSDavid van Moolenbroek
8363*d56f51eaSDavid van Moolenbroek /* Load X with the end of the Geneve header. */
8364*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_LDX|BPF_MEM);
8365*d56f51eaSDavid van Moolenbroek s1->s.k = off_linkhdr.reg;
8366*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8367*d56f51eaSDavid van Moolenbroek
8368*d56f51eaSDavid van Moolenbroek /* Check if the EtherType is Transparent Ethernet Bridging. At the
8369*d56f51eaSDavid van Moolenbroek * end of this check, we should have the total length in X. In
8370*d56f51eaSDavid van Moolenbroek * the non-Ethernet case, it's already there. */
8371*d56f51eaSDavid van Moolenbroek s_proto = new_stmt(JMP(BPF_JEQ));
8372*d56f51eaSDavid van Moolenbroek s_proto->s.k = ETHERTYPE_TEB;
8373*d56f51eaSDavid van Moolenbroek sappend(s, s_proto);
8374*d56f51eaSDavid van Moolenbroek
8375*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_MISC|BPF_TXA);
8376*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8377*d56f51eaSDavid van Moolenbroek s_proto->s.jt = s1;
8378*d56f51eaSDavid van Moolenbroek
8379*d56f51eaSDavid van Moolenbroek /* Since this is Ethernet, use the EtherType of the payload
8380*d56f51eaSDavid van Moolenbroek * directly as the linktype. Overwrite what we already have. */
8381*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
8382*d56f51eaSDavid van Moolenbroek s1->s.k = 12;
8383*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8384*d56f51eaSDavid van Moolenbroek
8385*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_ST);
8386*d56f51eaSDavid van Moolenbroek s1->s.k = off_linktype.reg;
8387*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8388*d56f51eaSDavid van Moolenbroek
8389*d56f51eaSDavid van Moolenbroek /* Advance two bytes further to get the end of the Ethernet
8390*d56f51eaSDavid van Moolenbroek * header. */
8391*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
8392*d56f51eaSDavid van Moolenbroek s1->s.k = 2;
8393*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8394*d56f51eaSDavid van Moolenbroek
8395*d56f51eaSDavid van Moolenbroek /* Move the result to X. */
8396*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_MISC|BPF_TAX);
8397*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8398*d56f51eaSDavid van Moolenbroek
8399*d56f51eaSDavid van Moolenbroek /* Store the final result of our linkpl calculation. */
8400*d56f51eaSDavid van Moolenbroek off_linkpl.reg = alloc_reg();
8401*d56f51eaSDavid van Moolenbroek off_linkpl.is_variable = 1;
8402*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = 0;
8403*d56f51eaSDavid van Moolenbroek
8404*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_STX);
8405*d56f51eaSDavid van Moolenbroek s1->s.k = off_linkpl.reg;
8406*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8407*d56f51eaSDavid van Moolenbroek s_proto->s.jf = s1;
8408*d56f51eaSDavid van Moolenbroek
8409*d56f51eaSDavid van Moolenbroek off_nl = 0;
8410*d56f51eaSDavid van Moolenbroek
8411*d56f51eaSDavid van Moolenbroek return s;
8412*d56f51eaSDavid van Moolenbroek }
8413*d56f51eaSDavid van Moolenbroek
8414*d56f51eaSDavid van Moolenbroek /* Check to see if this is a Geneve packet. */
8415*d56f51eaSDavid van Moolenbroek struct block *
gen_geneve(int vni)8416*d56f51eaSDavid van Moolenbroek gen_geneve(int vni)
8417*d56f51eaSDavid van Moolenbroek {
8418*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
8419*d56f51eaSDavid van Moolenbroek struct slist *s;
8420*d56f51eaSDavid van Moolenbroek
8421*d56f51eaSDavid van Moolenbroek b0 = gen_geneve4(vni);
8422*d56f51eaSDavid van Moolenbroek b1 = gen_geneve6(vni);
8423*d56f51eaSDavid van Moolenbroek
8424*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
8425*d56f51eaSDavid van Moolenbroek b0 = b1;
8426*d56f51eaSDavid van Moolenbroek
8427*d56f51eaSDavid van Moolenbroek /* Later filters should act on the payload of the Geneve frame,
8428*d56f51eaSDavid van Moolenbroek * update all of the header pointers. Attach this code so that
8429*d56f51eaSDavid van Moolenbroek * it gets executed in the event that the Geneve filter matches. */
8430*d56f51eaSDavid van Moolenbroek s = gen_geneve_offsets();
8431*d56f51eaSDavid van Moolenbroek
8432*d56f51eaSDavid van Moolenbroek b1 = gen_true();
8433*d56f51eaSDavid van Moolenbroek sappend(s, b1->stmts);
8434*d56f51eaSDavid van Moolenbroek b1->stmts = s;
8435*d56f51eaSDavid van Moolenbroek
8436*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
8437*d56f51eaSDavid van Moolenbroek
8438*d56f51eaSDavid van Moolenbroek is_geneve = 1;
8439*d56f51eaSDavid van Moolenbroek
8440*d56f51eaSDavid van Moolenbroek return b1;
8441*d56f51eaSDavid van Moolenbroek }
8442*d56f51eaSDavid van Moolenbroek
8443*d56f51eaSDavid van Moolenbroek /* Check that the encapsulated frame has a link layer header
8444*d56f51eaSDavid van Moolenbroek * for Ethernet filters. */
8445*d56f51eaSDavid van Moolenbroek static struct block *
gen_geneve_ll_check()8446*d56f51eaSDavid van Moolenbroek gen_geneve_ll_check()
8447*d56f51eaSDavid van Moolenbroek {
8448*d56f51eaSDavid van Moolenbroek struct block *b0;
8449*d56f51eaSDavid van Moolenbroek struct slist *s, *s1;
8450*d56f51eaSDavid van Moolenbroek
8451*d56f51eaSDavid van Moolenbroek /* The easiest way to see if there is a link layer present
8452*d56f51eaSDavid van Moolenbroek * is to check if the link layer header and payload are not
8453*d56f51eaSDavid van Moolenbroek * the same. */
8454*d56f51eaSDavid van Moolenbroek
8455*d56f51eaSDavid van Moolenbroek /* Geneve always generates pure variable offsets so we can
8456*d56f51eaSDavid van Moolenbroek * compare only the registers. */
8457*d56f51eaSDavid van Moolenbroek s = new_stmt(BPF_LD|BPF_MEM);
8458*d56f51eaSDavid van Moolenbroek s->s.k = off_linkhdr.reg;
8459*d56f51eaSDavid van Moolenbroek
8460*d56f51eaSDavid van Moolenbroek s1 = new_stmt(BPF_LDX|BPF_MEM);
8461*d56f51eaSDavid van Moolenbroek s1->s.k = off_linkpl.reg;
8462*d56f51eaSDavid van Moolenbroek sappend(s, s1);
8463*d56f51eaSDavid van Moolenbroek
8464*d56f51eaSDavid van Moolenbroek b0 = new_block(BPF_JMP|BPF_JEQ|BPF_X);
8465*d56f51eaSDavid van Moolenbroek b0->stmts = s;
8466*d56f51eaSDavid van Moolenbroek b0->s.k = 0;
8467*d56f51eaSDavid van Moolenbroek gen_not(b0);
8468*d56f51eaSDavid van Moolenbroek
8469*d56f51eaSDavid van Moolenbroek return b0;
8470*d56f51eaSDavid van Moolenbroek }
8471*d56f51eaSDavid van Moolenbroek
8472*d56f51eaSDavid van Moolenbroek struct block *
gen_atmfield_code(atmfield,jvalue,jtype,reverse)8473*d56f51eaSDavid van Moolenbroek gen_atmfield_code(atmfield, jvalue, jtype, reverse)
8474*d56f51eaSDavid van Moolenbroek int atmfield;
8475*d56f51eaSDavid van Moolenbroek bpf_int32 jvalue;
8476*d56f51eaSDavid van Moolenbroek bpf_u_int32 jtype;
8477*d56f51eaSDavid van Moolenbroek int reverse;
8478*d56f51eaSDavid van Moolenbroek {
8479*d56f51eaSDavid van Moolenbroek struct block *b0;
8480*d56f51eaSDavid van Moolenbroek
8481*d56f51eaSDavid van Moolenbroek switch (atmfield) {
8482*d56f51eaSDavid van Moolenbroek
8483*d56f51eaSDavid van Moolenbroek case A_VPI:
8484*d56f51eaSDavid van Moolenbroek if (!is_atm)
8485*d56f51eaSDavid van Moolenbroek bpf_error("'vpi' supported only on raw ATM");
8486*d56f51eaSDavid van Moolenbroek if (off_vpi == (u_int)-1)
8487*d56f51eaSDavid van Moolenbroek abort();
8488*d56f51eaSDavid van Moolenbroek b0 = gen_ncmp(OR_LINKHDR, off_vpi, BPF_B, 0xffffffff, jtype,
8489*d56f51eaSDavid van Moolenbroek reverse, jvalue);
8490*d56f51eaSDavid van Moolenbroek break;
8491*d56f51eaSDavid van Moolenbroek
8492*d56f51eaSDavid van Moolenbroek case A_VCI:
8493*d56f51eaSDavid van Moolenbroek if (!is_atm)
8494*d56f51eaSDavid van Moolenbroek bpf_error("'vci' supported only on raw ATM");
8495*d56f51eaSDavid van Moolenbroek if (off_vci == (u_int)-1)
8496*d56f51eaSDavid van Moolenbroek abort();
8497*d56f51eaSDavid van Moolenbroek b0 = gen_ncmp(OR_LINKHDR, off_vci, BPF_H, 0xffffffff, jtype,
8498*d56f51eaSDavid van Moolenbroek reverse, jvalue);
8499*d56f51eaSDavid van Moolenbroek break;
8500*d56f51eaSDavid van Moolenbroek
8501*d56f51eaSDavid van Moolenbroek case A_PROTOTYPE:
8502*d56f51eaSDavid van Moolenbroek if (off_proto == (u_int)-1)
8503*d56f51eaSDavid van Moolenbroek abort(); /* XXX - this isn't on FreeBSD */
8504*d56f51eaSDavid van Moolenbroek b0 = gen_ncmp(OR_LINKHDR, off_proto, BPF_B, 0x0f, jtype,
8505*d56f51eaSDavid van Moolenbroek reverse, jvalue);
8506*d56f51eaSDavid van Moolenbroek break;
8507*d56f51eaSDavid van Moolenbroek
8508*d56f51eaSDavid van Moolenbroek case A_MSGTYPE:
8509*d56f51eaSDavid van Moolenbroek if (off_payload == (u_int)-1)
8510*d56f51eaSDavid van Moolenbroek abort();
8511*d56f51eaSDavid van Moolenbroek b0 = gen_ncmp(OR_LINKHDR, off_payload + MSG_TYPE_POS, BPF_B,
8512*d56f51eaSDavid van Moolenbroek 0xffffffff, jtype, reverse, jvalue);
8513*d56f51eaSDavid van Moolenbroek break;
8514*d56f51eaSDavid van Moolenbroek
8515*d56f51eaSDavid van Moolenbroek case A_CALLREFTYPE:
8516*d56f51eaSDavid van Moolenbroek if (!is_atm)
8517*d56f51eaSDavid van Moolenbroek bpf_error("'callref' supported only on raw ATM");
8518*d56f51eaSDavid van Moolenbroek if (off_proto == (u_int)-1)
8519*d56f51eaSDavid van Moolenbroek abort();
8520*d56f51eaSDavid van Moolenbroek b0 = gen_ncmp(OR_LINKHDR, off_proto, BPF_B, 0xffffffff,
8521*d56f51eaSDavid van Moolenbroek jtype, reverse, jvalue);
8522*d56f51eaSDavid van Moolenbroek break;
8523*d56f51eaSDavid van Moolenbroek
8524*d56f51eaSDavid van Moolenbroek default:
8525*d56f51eaSDavid van Moolenbroek abort();
8526*d56f51eaSDavid van Moolenbroek }
8527*d56f51eaSDavid van Moolenbroek return b0;
8528*d56f51eaSDavid van Moolenbroek }
8529*d56f51eaSDavid van Moolenbroek
8530*d56f51eaSDavid van Moolenbroek struct block *
gen_atmtype_abbrev(type)8531*d56f51eaSDavid van Moolenbroek gen_atmtype_abbrev(type)
8532*d56f51eaSDavid van Moolenbroek int type;
8533*d56f51eaSDavid van Moolenbroek {
8534*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
8535*d56f51eaSDavid van Moolenbroek
8536*d56f51eaSDavid van Moolenbroek switch (type) {
8537*d56f51eaSDavid van Moolenbroek
8538*d56f51eaSDavid van Moolenbroek case A_METAC:
8539*d56f51eaSDavid van Moolenbroek /* Get all packets in Meta signalling Circuit */
8540*d56f51eaSDavid van Moolenbroek if (!is_atm)
8541*d56f51eaSDavid van Moolenbroek bpf_error("'metac' supported only on raw ATM");
8542*d56f51eaSDavid van Moolenbroek b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8543*d56f51eaSDavid van Moolenbroek b1 = gen_atmfield_code(A_VCI, 1, BPF_JEQ, 0);
8544*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
8545*d56f51eaSDavid van Moolenbroek break;
8546*d56f51eaSDavid van Moolenbroek
8547*d56f51eaSDavid van Moolenbroek case A_BCC:
8548*d56f51eaSDavid van Moolenbroek /* Get all packets in Broadcast Circuit*/
8549*d56f51eaSDavid van Moolenbroek if (!is_atm)
8550*d56f51eaSDavid van Moolenbroek bpf_error("'bcc' supported only on raw ATM");
8551*d56f51eaSDavid van Moolenbroek b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8552*d56f51eaSDavid van Moolenbroek b1 = gen_atmfield_code(A_VCI, 2, BPF_JEQ, 0);
8553*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
8554*d56f51eaSDavid van Moolenbroek break;
8555*d56f51eaSDavid van Moolenbroek
8556*d56f51eaSDavid van Moolenbroek case A_OAMF4SC:
8557*d56f51eaSDavid van Moolenbroek /* Get all cells in Segment OAM F4 circuit*/
8558*d56f51eaSDavid van Moolenbroek if (!is_atm)
8559*d56f51eaSDavid van Moolenbroek bpf_error("'oam4sc' supported only on raw ATM");
8560*d56f51eaSDavid van Moolenbroek b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8561*d56f51eaSDavid van Moolenbroek b1 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
8562*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
8563*d56f51eaSDavid van Moolenbroek break;
8564*d56f51eaSDavid van Moolenbroek
8565*d56f51eaSDavid van Moolenbroek case A_OAMF4EC:
8566*d56f51eaSDavid van Moolenbroek /* Get all cells in End-to-End OAM F4 Circuit*/
8567*d56f51eaSDavid van Moolenbroek if (!is_atm)
8568*d56f51eaSDavid van Moolenbroek bpf_error("'oam4ec' supported only on raw ATM");
8569*d56f51eaSDavid van Moolenbroek b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8570*d56f51eaSDavid van Moolenbroek b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0);
8571*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
8572*d56f51eaSDavid van Moolenbroek break;
8573*d56f51eaSDavid van Moolenbroek
8574*d56f51eaSDavid van Moolenbroek case A_SC:
8575*d56f51eaSDavid van Moolenbroek /* Get all packets in connection Signalling Circuit */
8576*d56f51eaSDavid van Moolenbroek if (!is_atm)
8577*d56f51eaSDavid van Moolenbroek bpf_error("'sc' supported only on raw ATM");
8578*d56f51eaSDavid van Moolenbroek b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8579*d56f51eaSDavid van Moolenbroek b1 = gen_atmfield_code(A_VCI, 5, BPF_JEQ, 0);
8580*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
8581*d56f51eaSDavid van Moolenbroek break;
8582*d56f51eaSDavid van Moolenbroek
8583*d56f51eaSDavid van Moolenbroek case A_ILMIC:
8584*d56f51eaSDavid van Moolenbroek /* Get all packets in ILMI Circuit */
8585*d56f51eaSDavid van Moolenbroek if (!is_atm)
8586*d56f51eaSDavid van Moolenbroek bpf_error("'ilmic' supported only on raw ATM");
8587*d56f51eaSDavid van Moolenbroek b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8588*d56f51eaSDavid van Moolenbroek b1 = gen_atmfield_code(A_VCI, 16, BPF_JEQ, 0);
8589*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
8590*d56f51eaSDavid van Moolenbroek break;
8591*d56f51eaSDavid van Moolenbroek
8592*d56f51eaSDavid van Moolenbroek case A_LANE:
8593*d56f51eaSDavid van Moolenbroek /* Get all LANE packets */
8594*d56f51eaSDavid van Moolenbroek if (!is_atm)
8595*d56f51eaSDavid van Moolenbroek bpf_error("'lane' supported only on raw ATM");
8596*d56f51eaSDavid van Moolenbroek b1 = gen_atmfield_code(A_PROTOTYPE, PT_LANE, BPF_JEQ, 0);
8597*d56f51eaSDavid van Moolenbroek
8598*d56f51eaSDavid van Moolenbroek /*
8599*d56f51eaSDavid van Moolenbroek * Arrange that all subsequent tests assume LANE
8600*d56f51eaSDavid van Moolenbroek * rather than LLC-encapsulated packets, and set
8601*d56f51eaSDavid van Moolenbroek * the offsets appropriately for LANE-encapsulated
8602*d56f51eaSDavid van Moolenbroek * Ethernet.
8603*d56f51eaSDavid van Moolenbroek *
8604*d56f51eaSDavid van Moolenbroek * We assume LANE means Ethernet, not Token Ring.
8605*d56f51eaSDavid van Moolenbroek */
8606*d56f51eaSDavid van Moolenbroek PUSH_LINKHDR(DLT_EN10MB, 0,
8607*d56f51eaSDavid van Moolenbroek off_payload + 2, /* Ethernet header */
8608*d56f51eaSDavid van Moolenbroek -1);
8609*d56f51eaSDavid van Moolenbroek off_linktype.constant_part = off_linkhdr.constant_part + 12;
8610*d56f51eaSDavid van Moolenbroek off_linkpl.constant_part = off_linkhdr.constant_part + 14; /* Ethernet */
8611*d56f51eaSDavid van Moolenbroek off_nl = 0; /* Ethernet II */
8612*d56f51eaSDavid van Moolenbroek off_nl_nosnap = 3; /* 802.3+802.2 */
8613*d56f51eaSDavid van Moolenbroek break;
8614*d56f51eaSDavid van Moolenbroek
8615*d56f51eaSDavid van Moolenbroek case A_LLC:
8616*d56f51eaSDavid van Moolenbroek /* Get all LLC-encapsulated packets */
8617*d56f51eaSDavid van Moolenbroek if (!is_atm)
8618*d56f51eaSDavid van Moolenbroek bpf_error("'llc' supported only on raw ATM");
8619*d56f51eaSDavid van Moolenbroek b1 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
8620*d56f51eaSDavid van Moolenbroek linktype = prevlinktype;
8621*d56f51eaSDavid van Moolenbroek break;
8622*d56f51eaSDavid van Moolenbroek
8623*d56f51eaSDavid van Moolenbroek default:
8624*d56f51eaSDavid van Moolenbroek abort();
8625*d56f51eaSDavid van Moolenbroek }
8626*d56f51eaSDavid van Moolenbroek return b1;
8627*d56f51eaSDavid van Moolenbroek }
8628*d56f51eaSDavid van Moolenbroek
8629*d56f51eaSDavid van Moolenbroek /*
8630*d56f51eaSDavid van Moolenbroek * Filtering for MTP2 messages based on li value
8631*d56f51eaSDavid van Moolenbroek * FISU, length is null
8632*d56f51eaSDavid van Moolenbroek * LSSU, length is 1 or 2
8633*d56f51eaSDavid van Moolenbroek * MSU, length is 3 or more
8634*d56f51eaSDavid van Moolenbroek * For MTP2_HSL, sequences are on 2 bytes, and length on 9 bits
8635*d56f51eaSDavid van Moolenbroek */
8636*d56f51eaSDavid van Moolenbroek struct block *
gen_mtp2type_abbrev(type)8637*d56f51eaSDavid van Moolenbroek gen_mtp2type_abbrev(type)
8638*d56f51eaSDavid van Moolenbroek int type;
8639*d56f51eaSDavid van Moolenbroek {
8640*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
8641*d56f51eaSDavid van Moolenbroek
8642*d56f51eaSDavid van Moolenbroek switch (type) {
8643*d56f51eaSDavid van Moolenbroek
8644*d56f51eaSDavid van Moolenbroek case M_FISU:
8645*d56f51eaSDavid van Moolenbroek if ( (linktype != DLT_MTP2) &&
8646*d56f51eaSDavid van Moolenbroek (linktype != DLT_ERF) &&
8647*d56f51eaSDavid van Moolenbroek (linktype != DLT_MTP2_WITH_PHDR) )
8648*d56f51eaSDavid van Moolenbroek bpf_error("'fisu' supported only on MTP2");
8649*d56f51eaSDavid van Moolenbroek /* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */
8650*d56f51eaSDavid van Moolenbroek b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JEQ, 0, 0);
8651*d56f51eaSDavid van Moolenbroek break;
8652*d56f51eaSDavid van Moolenbroek
8653*d56f51eaSDavid van Moolenbroek case M_LSSU:
8654*d56f51eaSDavid van Moolenbroek if ( (linktype != DLT_MTP2) &&
8655*d56f51eaSDavid van Moolenbroek (linktype != DLT_ERF) &&
8656*d56f51eaSDavid van Moolenbroek (linktype != DLT_MTP2_WITH_PHDR) )
8657*d56f51eaSDavid van Moolenbroek bpf_error("'lssu' supported only on MTP2");
8658*d56f51eaSDavid van Moolenbroek b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 1, 2);
8659*d56f51eaSDavid van Moolenbroek b1 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 0);
8660*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
8661*d56f51eaSDavid van Moolenbroek break;
8662*d56f51eaSDavid van Moolenbroek
8663*d56f51eaSDavid van Moolenbroek case M_MSU:
8664*d56f51eaSDavid van Moolenbroek if ( (linktype != DLT_MTP2) &&
8665*d56f51eaSDavid van Moolenbroek (linktype != DLT_ERF) &&
8666*d56f51eaSDavid van Moolenbroek (linktype != DLT_MTP2_WITH_PHDR) )
8667*d56f51eaSDavid van Moolenbroek bpf_error("'msu' supported only on MTP2");
8668*d56f51eaSDavid van Moolenbroek b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 2);
8669*d56f51eaSDavid van Moolenbroek break;
8670*d56f51eaSDavid van Moolenbroek
8671*d56f51eaSDavid van Moolenbroek case MH_FISU:
8672*d56f51eaSDavid van Moolenbroek if ( (linktype != DLT_MTP2) &&
8673*d56f51eaSDavid van Moolenbroek (linktype != DLT_ERF) &&
8674*d56f51eaSDavid van Moolenbroek (linktype != DLT_MTP2_WITH_PHDR) )
8675*d56f51eaSDavid van Moolenbroek bpf_error("'hfisu' supported only on MTP2_HSL");
8676*d56f51eaSDavid van Moolenbroek /* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */
8677*d56f51eaSDavid van Moolenbroek b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JEQ, 0, 0);
8678*d56f51eaSDavid van Moolenbroek break;
8679*d56f51eaSDavid van Moolenbroek
8680*d56f51eaSDavid van Moolenbroek case MH_LSSU:
8681*d56f51eaSDavid van Moolenbroek if ( (linktype != DLT_MTP2) &&
8682*d56f51eaSDavid van Moolenbroek (linktype != DLT_ERF) &&
8683*d56f51eaSDavid van Moolenbroek (linktype != DLT_MTP2_WITH_PHDR) )
8684*d56f51eaSDavid van Moolenbroek bpf_error("'hlssu' supported only on MTP2_HSL");
8685*d56f51eaSDavid van Moolenbroek b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 1, 0x0100);
8686*d56f51eaSDavid van Moolenbroek b1 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0);
8687*d56f51eaSDavid van Moolenbroek gen_and(b1, b0);
8688*d56f51eaSDavid van Moolenbroek break;
8689*d56f51eaSDavid van Moolenbroek
8690*d56f51eaSDavid van Moolenbroek case MH_MSU:
8691*d56f51eaSDavid van Moolenbroek if ( (linktype != DLT_MTP2) &&
8692*d56f51eaSDavid van Moolenbroek (linktype != DLT_ERF) &&
8693*d56f51eaSDavid van Moolenbroek (linktype != DLT_MTP2_WITH_PHDR) )
8694*d56f51eaSDavid van Moolenbroek bpf_error("'hmsu' supported only on MTP2_HSL");
8695*d56f51eaSDavid van Moolenbroek b0 = gen_ncmp(OR_PACKET, off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0x0100);
8696*d56f51eaSDavid van Moolenbroek break;
8697*d56f51eaSDavid van Moolenbroek
8698*d56f51eaSDavid van Moolenbroek default:
8699*d56f51eaSDavid van Moolenbroek abort();
8700*d56f51eaSDavid van Moolenbroek }
8701*d56f51eaSDavid van Moolenbroek return b0;
8702*d56f51eaSDavid van Moolenbroek }
8703*d56f51eaSDavid van Moolenbroek
8704*d56f51eaSDavid van Moolenbroek struct block *
gen_mtp3field_code(mtp3field,jvalue,jtype,reverse)8705*d56f51eaSDavid van Moolenbroek gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
8706*d56f51eaSDavid van Moolenbroek int mtp3field;
8707*d56f51eaSDavid van Moolenbroek bpf_u_int32 jvalue;
8708*d56f51eaSDavid van Moolenbroek bpf_u_int32 jtype;
8709*d56f51eaSDavid van Moolenbroek int reverse;
8710*d56f51eaSDavid van Moolenbroek {
8711*d56f51eaSDavid van Moolenbroek struct block *b0;
8712*d56f51eaSDavid van Moolenbroek bpf_u_int32 val1 , val2 , val3;
8713*d56f51eaSDavid van Moolenbroek u_int newoff_sio=off_sio;
8714*d56f51eaSDavid van Moolenbroek u_int newoff_opc=off_opc;
8715*d56f51eaSDavid van Moolenbroek u_int newoff_dpc=off_dpc;
8716*d56f51eaSDavid van Moolenbroek u_int newoff_sls=off_sls;
8717*d56f51eaSDavid van Moolenbroek
8718*d56f51eaSDavid van Moolenbroek switch (mtp3field) {
8719*d56f51eaSDavid van Moolenbroek
8720*d56f51eaSDavid van Moolenbroek case MH_SIO:
8721*d56f51eaSDavid van Moolenbroek newoff_sio += 3; /* offset for MTP2_HSL */
8722*d56f51eaSDavid van Moolenbroek /* FALLTHROUGH */
8723*d56f51eaSDavid van Moolenbroek
8724*d56f51eaSDavid van Moolenbroek case M_SIO:
8725*d56f51eaSDavid van Moolenbroek if (off_sio == (u_int)-1)
8726*d56f51eaSDavid van Moolenbroek bpf_error("'sio' supported only on SS7");
8727*d56f51eaSDavid van Moolenbroek /* sio coded on 1 byte so max value 255 */
8728*d56f51eaSDavid van Moolenbroek if(jvalue > 255)
8729*d56f51eaSDavid van Moolenbroek bpf_error("sio value %u too big; max value = 255",
8730*d56f51eaSDavid van Moolenbroek jvalue);
8731*d56f51eaSDavid van Moolenbroek b0 = gen_ncmp(OR_PACKET, newoff_sio, BPF_B, 0xffffffff,
8732*d56f51eaSDavid van Moolenbroek (u_int)jtype, reverse, (u_int)jvalue);
8733*d56f51eaSDavid van Moolenbroek break;
8734*d56f51eaSDavid van Moolenbroek
8735*d56f51eaSDavid van Moolenbroek case MH_OPC:
8736*d56f51eaSDavid van Moolenbroek newoff_opc+=3;
8737*d56f51eaSDavid van Moolenbroek case M_OPC:
8738*d56f51eaSDavid van Moolenbroek if (off_opc == (u_int)-1)
8739*d56f51eaSDavid van Moolenbroek bpf_error("'opc' supported only on SS7");
8740*d56f51eaSDavid van Moolenbroek /* opc coded on 14 bits so max value 16383 */
8741*d56f51eaSDavid van Moolenbroek if (jvalue > 16383)
8742*d56f51eaSDavid van Moolenbroek bpf_error("opc value %u too big; max value = 16383",
8743*d56f51eaSDavid van Moolenbroek jvalue);
8744*d56f51eaSDavid van Moolenbroek /* the following instructions are made to convert jvalue
8745*d56f51eaSDavid van Moolenbroek * to the form used to write opc in an ss7 message*/
8746*d56f51eaSDavid van Moolenbroek val1 = jvalue & 0x00003c00;
8747*d56f51eaSDavid van Moolenbroek val1 = val1 >>10;
8748*d56f51eaSDavid van Moolenbroek val2 = jvalue & 0x000003fc;
8749*d56f51eaSDavid van Moolenbroek val2 = val2 <<6;
8750*d56f51eaSDavid van Moolenbroek val3 = jvalue & 0x00000003;
8751*d56f51eaSDavid van Moolenbroek val3 = val3 <<22;
8752*d56f51eaSDavid van Moolenbroek jvalue = val1 + val2 + val3;
8753*d56f51eaSDavid van Moolenbroek b0 = gen_ncmp(OR_PACKET, newoff_opc, BPF_W, 0x00c0ff0f,
8754*d56f51eaSDavid van Moolenbroek (u_int)jtype, reverse, (u_int)jvalue);
8755*d56f51eaSDavid van Moolenbroek break;
8756*d56f51eaSDavid van Moolenbroek
8757*d56f51eaSDavid van Moolenbroek case MH_DPC:
8758*d56f51eaSDavid van Moolenbroek newoff_dpc += 3;
8759*d56f51eaSDavid van Moolenbroek /* FALLTHROUGH */
8760*d56f51eaSDavid van Moolenbroek
8761*d56f51eaSDavid van Moolenbroek case M_DPC:
8762*d56f51eaSDavid van Moolenbroek if (off_dpc == (u_int)-1)
8763*d56f51eaSDavid van Moolenbroek bpf_error("'dpc' supported only on SS7");
8764*d56f51eaSDavid van Moolenbroek /* dpc coded on 14 bits so max value 16383 */
8765*d56f51eaSDavid van Moolenbroek if (jvalue > 16383)
8766*d56f51eaSDavid van Moolenbroek bpf_error("dpc value %u too big; max value = 16383",
8767*d56f51eaSDavid van Moolenbroek jvalue);
8768*d56f51eaSDavid van Moolenbroek /* the following instructions are made to convert jvalue
8769*d56f51eaSDavid van Moolenbroek * to the forme used to write dpc in an ss7 message*/
8770*d56f51eaSDavid van Moolenbroek val1 = jvalue & 0x000000ff;
8771*d56f51eaSDavid van Moolenbroek val1 = val1 << 24;
8772*d56f51eaSDavid van Moolenbroek val2 = jvalue & 0x00003f00;
8773*d56f51eaSDavid van Moolenbroek val2 = val2 << 8;
8774*d56f51eaSDavid van Moolenbroek jvalue = val1 + val2;
8775*d56f51eaSDavid van Moolenbroek b0 = gen_ncmp(OR_PACKET, newoff_dpc, BPF_W, 0xff3f0000,
8776*d56f51eaSDavid van Moolenbroek (u_int)jtype, reverse, (u_int)jvalue);
8777*d56f51eaSDavid van Moolenbroek break;
8778*d56f51eaSDavid van Moolenbroek
8779*d56f51eaSDavid van Moolenbroek case MH_SLS:
8780*d56f51eaSDavid van Moolenbroek newoff_sls+=3;
8781*d56f51eaSDavid van Moolenbroek case M_SLS:
8782*d56f51eaSDavid van Moolenbroek if (off_sls == (u_int)-1)
8783*d56f51eaSDavid van Moolenbroek bpf_error("'sls' supported only on SS7");
8784*d56f51eaSDavid van Moolenbroek /* sls coded on 4 bits so max value 15 */
8785*d56f51eaSDavid van Moolenbroek if (jvalue > 15)
8786*d56f51eaSDavid van Moolenbroek bpf_error("sls value %u too big; max value = 15",
8787*d56f51eaSDavid van Moolenbroek jvalue);
8788*d56f51eaSDavid van Moolenbroek /* the following instruction is made to convert jvalue
8789*d56f51eaSDavid van Moolenbroek * to the forme used to write sls in an ss7 message*/
8790*d56f51eaSDavid van Moolenbroek jvalue = jvalue << 4;
8791*d56f51eaSDavid van Moolenbroek b0 = gen_ncmp(OR_PACKET, newoff_sls, BPF_B, 0xf0,
8792*d56f51eaSDavid van Moolenbroek (u_int)jtype,reverse, (u_int)jvalue);
8793*d56f51eaSDavid van Moolenbroek break;
8794*d56f51eaSDavid van Moolenbroek
8795*d56f51eaSDavid van Moolenbroek default:
8796*d56f51eaSDavid van Moolenbroek abort();
8797*d56f51eaSDavid van Moolenbroek }
8798*d56f51eaSDavid van Moolenbroek return b0;
8799*d56f51eaSDavid van Moolenbroek }
8800*d56f51eaSDavid van Moolenbroek
8801*d56f51eaSDavid van Moolenbroek static struct block *
gen_msg_abbrev(type)8802*d56f51eaSDavid van Moolenbroek gen_msg_abbrev(type)
8803*d56f51eaSDavid van Moolenbroek int type;
8804*d56f51eaSDavid van Moolenbroek {
8805*d56f51eaSDavid van Moolenbroek struct block *b1;
8806*d56f51eaSDavid van Moolenbroek
8807*d56f51eaSDavid van Moolenbroek /*
8808*d56f51eaSDavid van Moolenbroek * Q.2931 signalling protocol messages for handling virtual circuits
8809*d56f51eaSDavid van Moolenbroek * establishment and teardown
8810*d56f51eaSDavid van Moolenbroek */
8811*d56f51eaSDavid van Moolenbroek switch (type) {
8812*d56f51eaSDavid van Moolenbroek
8813*d56f51eaSDavid van Moolenbroek case A_SETUP:
8814*d56f51eaSDavid van Moolenbroek b1 = gen_atmfield_code(A_MSGTYPE, SETUP, BPF_JEQ, 0);
8815*d56f51eaSDavid van Moolenbroek break;
8816*d56f51eaSDavid van Moolenbroek
8817*d56f51eaSDavid van Moolenbroek case A_CALLPROCEED:
8818*d56f51eaSDavid van Moolenbroek b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
8819*d56f51eaSDavid van Moolenbroek break;
8820*d56f51eaSDavid van Moolenbroek
8821*d56f51eaSDavid van Moolenbroek case A_CONNECT:
8822*d56f51eaSDavid van Moolenbroek b1 = gen_atmfield_code(A_MSGTYPE, CONNECT, BPF_JEQ, 0);
8823*d56f51eaSDavid van Moolenbroek break;
8824*d56f51eaSDavid van Moolenbroek
8825*d56f51eaSDavid van Moolenbroek case A_CONNECTACK:
8826*d56f51eaSDavid van Moolenbroek b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
8827*d56f51eaSDavid van Moolenbroek break;
8828*d56f51eaSDavid van Moolenbroek
8829*d56f51eaSDavid van Moolenbroek case A_RELEASE:
8830*d56f51eaSDavid van Moolenbroek b1 = gen_atmfield_code(A_MSGTYPE, RELEASE, BPF_JEQ, 0);
8831*d56f51eaSDavid van Moolenbroek break;
8832*d56f51eaSDavid van Moolenbroek
8833*d56f51eaSDavid van Moolenbroek case A_RELEASE_DONE:
8834*d56f51eaSDavid van Moolenbroek b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
8835*d56f51eaSDavid van Moolenbroek break;
8836*d56f51eaSDavid van Moolenbroek
8837*d56f51eaSDavid van Moolenbroek default:
8838*d56f51eaSDavid van Moolenbroek abort();
8839*d56f51eaSDavid van Moolenbroek }
8840*d56f51eaSDavid van Moolenbroek return b1;
8841*d56f51eaSDavid van Moolenbroek }
8842*d56f51eaSDavid van Moolenbroek
8843*d56f51eaSDavid van Moolenbroek struct block *
gen_atmmulti_abbrev(type)8844*d56f51eaSDavid van Moolenbroek gen_atmmulti_abbrev(type)
8845*d56f51eaSDavid van Moolenbroek int type;
8846*d56f51eaSDavid van Moolenbroek {
8847*d56f51eaSDavid van Moolenbroek struct block *b0, *b1;
8848*d56f51eaSDavid van Moolenbroek
8849*d56f51eaSDavid van Moolenbroek switch (type) {
8850*d56f51eaSDavid van Moolenbroek
8851*d56f51eaSDavid van Moolenbroek case A_OAM:
8852*d56f51eaSDavid van Moolenbroek if (!is_atm)
8853*d56f51eaSDavid van Moolenbroek bpf_error("'oam' supported only on raw ATM");
8854*d56f51eaSDavid van Moolenbroek b1 = gen_atmmulti_abbrev(A_OAMF4);
8855*d56f51eaSDavid van Moolenbroek break;
8856*d56f51eaSDavid van Moolenbroek
8857*d56f51eaSDavid van Moolenbroek case A_OAMF4:
8858*d56f51eaSDavid van Moolenbroek if (!is_atm)
8859*d56f51eaSDavid van Moolenbroek bpf_error("'oamf4' supported only on raw ATM");
8860*d56f51eaSDavid van Moolenbroek /* OAM F4 type */
8861*d56f51eaSDavid van Moolenbroek b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
8862*d56f51eaSDavid van Moolenbroek b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0);
8863*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
8864*d56f51eaSDavid van Moolenbroek b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8865*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
8866*d56f51eaSDavid van Moolenbroek break;
8867*d56f51eaSDavid van Moolenbroek
8868*d56f51eaSDavid van Moolenbroek case A_CONNECTMSG:
8869*d56f51eaSDavid van Moolenbroek /*
8870*d56f51eaSDavid van Moolenbroek * Get Q.2931 signalling messages for switched
8871*d56f51eaSDavid van Moolenbroek * virtual connection
8872*d56f51eaSDavid van Moolenbroek */
8873*d56f51eaSDavid van Moolenbroek if (!is_atm)
8874*d56f51eaSDavid van Moolenbroek bpf_error("'connectmsg' supported only on raw ATM");
8875*d56f51eaSDavid van Moolenbroek b0 = gen_msg_abbrev(A_SETUP);
8876*d56f51eaSDavid van Moolenbroek b1 = gen_msg_abbrev(A_CALLPROCEED);
8877*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
8878*d56f51eaSDavid van Moolenbroek b0 = gen_msg_abbrev(A_CONNECT);
8879*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
8880*d56f51eaSDavid van Moolenbroek b0 = gen_msg_abbrev(A_CONNECTACK);
8881*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
8882*d56f51eaSDavid van Moolenbroek b0 = gen_msg_abbrev(A_RELEASE);
8883*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
8884*d56f51eaSDavid van Moolenbroek b0 = gen_msg_abbrev(A_RELEASE_DONE);
8885*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
8886*d56f51eaSDavid van Moolenbroek b0 = gen_atmtype_abbrev(A_SC);
8887*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
8888*d56f51eaSDavid van Moolenbroek break;
8889*d56f51eaSDavid van Moolenbroek
8890*d56f51eaSDavid van Moolenbroek case A_METACONNECT:
8891*d56f51eaSDavid van Moolenbroek if (!is_atm)
8892*d56f51eaSDavid van Moolenbroek bpf_error("'metaconnect' supported only on raw ATM");
8893*d56f51eaSDavid van Moolenbroek b0 = gen_msg_abbrev(A_SETUP);
8894*d56f51eaSDavid van Moolenbroek b1 = gen_msg_abbrev(A_CALLPROCEED);
8895*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
8896*d56f51eaSDavid van Moolenbroek b0 = gen_msg_abbrev(A_CONNECT);
8897*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
8898*d56f51eaSDavid van Moolenbroek b0 = gen_msg_abbrev(A_RELEASE);
8899*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
8900*d56f51eaSDavid van Moolenbroek b0 = gen_msg_abbrev(A_RELEASE_DONE);
8901*d56f51eaSDavid van Moolenbroek gen_or(b0, b1);
8902*d56f51eaSDavid van Moolenbroek b0 = gen_atmtype_abbrev(A_METAC);
8903*d56f51eaSDavid van Moolenbroek gen_and(b0, b1);
8904*d56f51eaSDavid van Moolenbroek break;
8905*d56f51eaSDavid van Moolenbroek
8906*d56f51eaSDavid van Moolenbroek default:
8907*d56f51eaSDavid van Moolenbroek abort();
8908*d56f51eaSDavid van Moolenbroek }
8909*d56f51eaSDavid van Moolenbroek return b1;
8910*d56f51eaSDavid van Moolenbroek }
8911