blob: a887f2730f7ac55783d869467f7557629affc1f3 [file] [log] [blame]
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001/*#define CHASE_CHAIN*/
2/*
3 * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
4 * The Regents of the University of California. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that: (1) source code distributions
8 * retain the above copyright notice and this paragraph in its entirety, (2)
9 * distributions including binary code include the above copyright notice and
10 * this paragraph in its entirety in the documentation or other materials
11 * provided with the distribution, and (3) all advertising materials mentioning
12 * features or use of this software display the following acknowledgement:
13 * ``This product includes software developed by the University of California,
14 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
15 * the University nor the names of its contributors may be used to endorse
16 * or promote products derived from this software without specific prior
17 * written permission.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -080022
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
Elliott Hughes965a4b52017-05-15 10:37:39 -070027#ifdef _WIN32
The Android Open Source Project478ab6c2009-03-03 19:30:05 -080028#include <pcap-stdinc.h>
Elliott Hughes965a4b52017-05-15 10:37:39 -070029#else /* _WIN32 */
JP Abgrall511eca32014-02-12 13:46:45 -080030#if HAVE_INTTYPES_H
31#include <inttypes.h>
32#elif HAVE_STDINT_H
33#include <stdint.h>
34#endif
35#ifdef HAVE_SYS_BITYPES_H
36#include <sys/bitypes.h>
37#endif
The Android Open Source Project478ab6c2009-03-03 19:30:05 -080038#include <sys/types.h>
39#include <sys/socket.h>
Elliott Hughes965a4b52017-05-15 10:37:39 -070040#endif /* _WIN32 */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -080041
Elliott Hughes965a4b52017-05-15 10:37:39 -070042#ifndef _WIN32
The Android Open Source Project478ab6c2009-03-03 19:30:05 -080043
44#ifdef __NetBSD__
45#include <sys/param.h>
46#endif
47
48#include <netinet/in.h>
JP Abgrall511eca32014-02-12 13:46:45 -080049#include <arpa/inet.h>
The Android Open Source Project478ab6c2009-03-03 19:30:05 -080050
Elliott Hughes965a4b52017-05-15 10:37:39 -070051#endif /* _WIN32 */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -080052
53#include <stdlib.h>
54#include <string.h>
55#include <memory.h>
56#include <setjmp.h>
57#include <stdarg.h>
58
59#ifdef MSDOS
60#include "pcap-dos.h"
61#endif
62
63#include "pcap-int.h"
64
65#include "ethertype.h"
66#include "nlpid.h"
67#include "llc.h"
68#include "gencode.h"
JP Abgrall511eca32014-02-12 13:46:45 -080069#include "ieee80211.h"
The Android Open Source Project478ab6c2009-03-03 19:30:05 -080070#include "atmuni31.h"
71#include "sunatmpos.h"
72#include "ppp.h"
JP Abgrall511eca32014-02-12 13:46:45 -080073#include "pcap/sll.h"
74#include "pcap/ipnet.h"
The Android Open Source Project478ab6c2009-03-03 19:30:05 -080075#include "arcnet.h"
Elliott Hughes965a4b52017-05-15 10:37:39 -070076
77#include "grammar.h"
78#include "scanner.h"
79
JP Abgrall511eca32014-02-12 13:46:45 -080080#if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
81#include <linux/types.h>
82#include <linux/if_packet.h>
83#include <linux/filter.h>
84#endif
Elliott Hughes965a4b52017-05-15 10:37:39 -070085
The Android Open Source Project478ab6c2009-03-03 19:30:05 -080086#ifdef HAVE_NET_PFVAR_H
87#include <sys/socket.h>
88#include <net/if.h>
89#include <net/pfvar.h>
90#include <net/if_pflog.h>
91#endif
Elliott Hughes965a4b52017-05-15 10:37:39 -070092
The Android Open Source Project478ab6c2009-03-03 19:30:05 -080093#ifndef offsetof
94#define offsetof(s, e) ((size_t)&((s *)0)->e)
95#endif
Elliott Hughes965a4b52017-05-15 10:37:39 -070096
The Android Open Source Project478ab6c2009-03-03 19:30:05 -080097#ifdef INET6
Elliott Hughes965a4b52017-05-15 10:37:39 -070098#ifdef _WIN32
99#if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
100/* IPv6 address */
101struct in6_addr
102 {
103 union
104 {
105 u_int8_t u6_addr8[16];
106 u_int16_t u6_addr16[8];
107 u_int32_t u6_addr32[4];
108 } in6_u;
109#define s6_addr in6_u.u6_addr8
110#define s6_addr16 in6_u.u6_addr16
111#define s6_addr32 in6_u.u6_addr32
112#define s6_addr64 in6_u.u6_addr64
113 };
114
115typedef unsigned short sa_family_t;
116
117#define __SOCKADDR_COMMON(sa_prefix) \
118 sa_family_t sa_prefix##family
119
120/* Ditto, for IPv6. */
121struct sockaddr_in6
122 {
123 __SOCKADDR_COMMON (sin6_);
124 u_int16_t sin6_port; /* Transport layer port # */
125 u_int32_t sin6_flowinfo; /* IPv6 flow information */
126 struct in6_addr sin6_addr; /* IPv6 address */
127 };
128
129#ifndef EAI_ADDRFAMILY
130struct addrinfo {
131 int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
132 int ai_family; /* PF_xxx */
133 int ai_socktype; /* SOCK_xxx */
134 int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
135 size_t ai_addrlen; /* length of ai_addr */
136 char *ai_canonname; /* canonical name for hostname */
137 struct sockaddr *ai_addr; /* binary address */
138 struct addrinfo *ai_next; /* next structure in linked list */
139};
140#endif /* EAI_ADDRFAMILY */
141#endif /* defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF) */
142#else /* _WIN32 */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800143#include <netdb.h> /* for "struct addrinfo" */
Elliott Hughes965a4b52017-05-15 10:37:39 -0700144#endif /* _WIN32 */
145#endif /* INET6 */
JP Abgrall511eca32014-02-12 13:46:45 -0800146#include <pcap/namedb.h>
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800147
Elliott Hughes965a4b52017-05-15 10:37:39 -0700148#include "nametoaddr.h"
149
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800150#define ETHERMTU 1500
151
Elliott Hughesd8845d72015-10-19 18:07:04 -0700152#ifndef ETHERTYPE_TEB
153#define ETHERTYPE_TEB 0x6558
154#endif
155
JP Abgrall511eca32014-02-12 13:46:45 -0800156#ifndef IPPROTO_HOPOPTS
157#define IPPROTO_HOPOPTS 0
158#endif
159#ifndef IPPROTO_ROUTING
160#define IPPROTO_ROUTING 43
161#endif
162#ifndef IPPROTO_FRAGMENT
163#define IPPROTO_FRAGMENT 44
164#endif
165#ifndef IPPROTO_DSTOPTS
166#define IPPROTO_DSTOPTS 60
167#endif
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800168#ifndef IPPROTO_SCTP
169#define IPPROTO_SCTP 132
170#endif
171
Elliott Hughesd8845d72015-10-19 18:07:04 -0700172#define GENEVE_PORT 6081
173
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800174#ifdef HAVE_OS_PROTO_H
175#include "os-proto.h"
176#endif
177
178#define JMP(c) ((c)|BPF_JMP|BPF_K)
179
Elliott Hughes965a4b52017-05-15 10:37:39 -0700180/*
181 * "Push" the current value of the link-layer header type and link-layer
182 * header offset onto a "stack", and set a new value. (It's not a
183 * full-blown stack; we keep only the top two items.)
184 */
185#define PUSH_LINKHDR(cs, new_linktype, new_is_variable, new_constant_part, new_reg) \
186{ \
187 (cs)->prevlinktype = (cs)->linktype; \
188 (cs)->off_prevlinkhdr = (cs)->off_linkhdr; \
189 (cs)->linktype = (new_linktype); \
190 (cs)->off_linkhdr.is_variable = (new_is_variable); \
191 (cs)->off_linkhdr.constant_part = (new_constant_part); \
192 (cs)->off_linkhdr.reg = (new_reg); \
193 (cs)->is_geneve = 0; \
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800194}
195
Elliott Hughes965a4b52017-05-15 10:37:39 -0700196/*
197 * Offset "not set" value.
198 */
199#define OFFSET_NOT_SET 0xffffffffU
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800200
201/*
Elliott Hughesd8845d72015-10-19 18:07:04 -0700202 * Absolute offsets, which are offsets from the beginning of the raw
203 * packet data, are, in the general case, the sum of a variable value
204 * and a constant value; the variable value may be absent, in which
205 * case the offset is only the constant value, and the constant value
206 * may be zero, in which case the offset is only the variable value.
207 *
208 * bpf_abs_offset is a structure containing all that information:
209 *
210 * is_variable is 1 if there's a variable part.
211 *
212 * constant_part is the constant part of the value, possibly zero;
213 *
214 * if is_variable is 1, reg is the register number for a register
215 * containing the variable value if the register has been assigned,
216 * and -1 otherwise.
217 */
218typedef struct {
219 int is_variable;
220 u_int constant_part;
221 int reg;
222} bpf_abs_offset;
223
224/*
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800225 * Value passed to gen_load_a() to indicate what the offset argument
Elliott Hughesd8845d72015-10-19 18:07:04 -0700226 * is relative to the beginning of.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800227 */
228enum e_offrel {
Elliott Hughesd8845d72015-10-19 18:07:04 -0700229 OR_PACKET, /* full packet data */
230 OR_LINKHDR, /* link-layer header */
231 OR_PREVLINKHDR, /* previous link-layer header */
232 OR_LLC, /* 802.2 LLC header */
233 OR_PREVMPLSHDR, /* previous MPLS header */
234 OR_LINKTYPE, /* link-layer type */
235 OR_LINKPL, /* link-layer payload */
236 OR_LINKPL_NOSNAP, /* link-layer payload, with no SNAP header at the link layer */
237 OR_TRAN_IPV4, /* transport-layer header, with IPv4 network layer */
238 OR_TRAN_IPV6 /* transport-layer header, with IPv6 network layer */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800239};
240
241/*
242 * We divy out chunks of memory rather than call malloc each time so
243 * we don't have to worry about leaking memory. It's probably
244 * not a big deal if all this memory was wasted but if this ever
245 * goes into a library that would probably not be a good idea.
246 *
247 * XXX - this *is* in a library....
248 */
249#define NCHUNKS 16
250#define CHUNK0SIZE 1024
251struct chunk {
Elliott Hughes965a4b52017-05-15 10:37:39 -0700252 size_t n_left;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800253 void *m;
254};
255
Elliott Hughes965a4b52017-05-15 10:37:39 -0700256/* Code generator state */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800257
Elliott Hughes965a4b52017-05-15 10:37:39 -0700258struct _compiler_state {
259 jmp_buf top_ctx;
260 pcap_t *bpf_pcap;
261
262 struct icode ic;
263
264 int snaplen;
265
266 int linktype;
267 int prevlinktype;
268 int outermostlinktype;
269
270 bpf_u_int32 netmask;
271 int no_optimize;
272
273 /* Hack for handling VLAN and MPLS stacks. */
274 u_int label_stack_depth;
275 u_int vlan_stack_depth;
276
277 /* XXX */
278 u_int pcap_fddipad;
279
280#ifdef INET6
281 /*
282 * As errors are handled by a longjmp, anything allocated must
283 * be freed in the longjmp handler, so it must be reachable
284 * from that handler.
285 *
286 * One thing that's allocated is the result of pcap_nametoaddrinfo();
287 * it must be freed with freeaddrinfo(). This variable points to
288 * any addrinfo structure that would need to be freed.
289 */
290 struct addrinfo *ai;
291#endif
292
293 /*
294 * Various code constructs need to know the layout of the packet.
295 * These values give the necessary offsets from the beginning
296 * of the packet data.
297 */
298
299 /*
300 * Absolute offset of the beginning of the link-layer header.
301 */
302 bpf_abs_offset off_linkhdr;
303
304 /*
305 * If we're checking a link-layer header for a packet encapsulated
306 * in another protocol layer, this is the equivalent information
307 * for the previous layers' link-layer header from the beginning
308 * of the raw packet data.
309 */
310 bpf_abs_offset off_prevlinkhdr;
311
312 /*
313 * This is the equivalent information for the outermost layers'
314 * link-layer header.
315 */
316 bpf_abs_offset off_outermostlinkhdr;
317
318 /*
319 * Absolute offset of the beginning of the link-layer payload.
320 */
321 bpf_abs_offset off_linkpl;
322
323 /*
324 * "off_linktype" is the offset to information in the link-layer
325 * header giving the packet type. This is an absolute offset
326 * from the beginning of the packet.
327 *
328 * For Ethernet, it's the offset of the Ethernet type field; this
329 * means that it must have a value that skips VLAN tags.
330 *
331 * For link-layer types that always use 802.2 headers, it's the
332 * offset of the LLC header; this means that it must have a value
333 * that skips VLAN tags.
334 *
335 * For PPP, it's the offset of the PPP type field.
336 *
337 * For Cisco HDLC, it's the offset of the CHDLC type field.
338 *
339 * For BSD loopback, it's the offset of the AF_ value.
340 *
341 * For Linux cooked sockets, it's the offset of the type field.
342 *
343 * off_linktype.constant_part is set to OFFSET_NOT_SET for no
344 * encapsulation, in which case, IP is assumed.
345 */
346 bpf_abs_offset off_linktype;
347
348 /*
349 * TRUE if the link layer includes an ATM pseudo-header.
350 */
351 int is_atm;
352
353 /*
354 * TRUE if "geneve" appeared in the filter; it causes us to
355 * generate code that checks for a Geneve header and assume
356 * that later filters apply to the encapsulated payload.
357 */
358 int is_geneve;
359
360 /*
361 * These are offsets for the ATM pseudo-header.
362 */
363 u_int off_vpi;
364 u_int off_vci;
365 u_int off_proto;
366
367 /*
368 * These are offsets for the MTP2 fields.
369 */
370 u_int off_li;
371 u_int off_li_hsl;
372
373 /*
374 * These are offsets for the MTP3 fields.
375 */
376 u_int off_sio;
377 u_int off_opc;
378 u_int off_dpc;
379 u_int off_sls;
380
381 /*
382 * This is the offset of the first byte after the ATM pseudo_header,
383 * or -1 if there is no ATM pseudo-header.
384 */
385 u_int off_payload;
386
387 /*
388 * These are offsets to the beginning of the network-layer header.
389 * They are relative to the beginning of the link-layer payload
390 * (i.e., they don't include off_linkhdr.constant_part or
391 * off_linkpl.constant_part).
392 *
393 * If the link layer never uses 802.2 LLC:
394 *
395 * "off_nl" and "off_nl_nosnap" are the same.
396 *
397 * If the link layer always uses 802.2 LLC:
398 *
399 * "off_nl" is the offset if there's a SNAP header following
400 * the 802.2 header;
401 *
402 * "off_nl_nosnap" is the offset if there's no SNAP header.
403 *
404 * If the link layer is Ethernet:
405 *
406 * "off_nl" is the offset if the packet is an Ethernet II packet
407 * (we assume no 802.3+802.2+SNAP);
408 *
409 * "off_nl_nosnap" is the offset if the packet is an 802.3 packet
410 * with an 802.2 header following it.
411 */
412 u_int off_nl;
413 u_int off_nl_nosnap;
414
415 /*
416 * Here we handle simple allocation of the scratch registers.
417 * If too many registers are alloc'd, the allocator punts.
418 */
419 int regused[BPF_MEMWORDS];
420 int curreg;
421
422 /*
423 * Memory chunks.
424 */
425 struct chunk chunks[NCHUNKS];
426 int cur_chunk;
427};
428
429void
430bpf_syntax_error(compiler_state_t *cstate, const char *msg)
431{
432 bpf_error(cstate, "syntax error in filter expression: %s", msg);
433 /* NOTREACHED */
434}
435
436/* VARARGS */
437void
438bpf_error(compiler_state_t *cstate, const char *fmt, ...)
439{
440 va_list ap;
441
442 va_start(ap, fmt);
443 if (cstate->bpf_pcap != NULL)
444 (void)pcap_vsnprintf(pcap_geterr(cstate->bpf_pcap),
445 PCAP_ERRBUF_SIZE, fmt, ap);
446 va_end(ap);
447 longjmp(cstate->top_ctx, 1);
448 /* NOTREACHED */
449}
450
451static void init_linktype(compiler_state_t *, pcap_t *);
452
453static void init_regs(compiler_state_t *);
454static int alloc_reg(compiler_state_t *);
455static void free_reg(compiler_state_t *, int);
456
457static void initchunks(compiler_state_t *cstate);
458static void *newchunk(compiler_state_t *cstate, size_t);
459static void freechunks(compiler_state_t *cstate);
460static inline struct block *new_block(compiler_state_t *cstate, int);
461static inline struct slist *new_stmt(compiler_state_t *cstate, int);
462static struct block *gen_retblk(compiler_state_t *cstate, int);
463static inline void syntax(compiler_state_t *cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800464
465static void backpatch(struct block *, struct block *);
466static void merge(struct block *, struct block *);
Elliott Hughes965a4b52017-05-15 10:37:39 -0700467static struct block *gen_cmp(compiler_state_t *, enum e_offrel, u_int,
468 u_int, bpf_int32);
469static struct block *gen_cmp_gt(compiler_state_t *, enum e_offrel, u_int,
470 u_int, bpf_int32);
471static struct block *gen_cmp_ge(compiler_state_t *, enum e_offrel, u_int,
472 u_int, bpf_int32);
473static struct block *gen_cmp_lt(compiler_state_t *, enum e_offrel, u_int,
474 u_int, bpf_int32);
475static struct block *gen_cmp_le(compiler_state_t *, enum e_offrel, u_int,
476 u_int, bpf_int32);
477static struct block *gen_mcmp(compiler_state_t *, enum e_offrel, u_int,
478 u_int, bpf_int32, bpf_u_int32);
479static struct block *gen_bcmp(compiler_state_t *, enum e_offrel, u_int,
480 u_int, const u_char *);
481static struct block *gen_ncmp(compiler_state_t *, enum e_offrel, bpf_u_int32,
482 bpf_u_int32, bpf_u_int32, bpf_u_int32, int, bpf_int32);
483static struct slist *gen_load_absoffsetrel(compiler_state_t *, bpf_abs_offset *,
484 u_int, u_int);
485static struct slist *gen_load_a(compiler_state_t *, enum e_offrel, u_int,
486 u_int);
487static struct slist *gen_loadx_iphdrlen(compiler_state_t *);
488static struct block *gen_uncond(compiler_state_t *, int);
489static inline struct block *gen_true(compiler_state_t *);
490static inline struct block *gen_false(compiler_state_t *);
491static struct block *gen_ether_linktype(compiler_state_t *, int);
492static struct block *gen_ipnet_linktype(compiler_state_t *, int);
493static struct block *gen_linux_sll_linktype(compiler_state_t *, int);
494static struct slist *gen_load_prism_llprefixlen(compiler_state_t *);
495static struct slist *gen_load_avs_llprefixlen(compiler_state_t *);
496static struct slist *gen_load_radiotap_llprefixlen(compiler_state_t *);
497static struct slist *gen_load_ppi_llprefixlen(compiler_state_t *);
498static void insert_compute_vloffsets(compiler_state_t *, struct block *);
499static struct slist *gen_abs_offset_varpart(compiler_state_t *,
500 bpf_abs_offset *);
JP Abgrall511eca32014-02-12 13:46:45 -0800501static int ethertype_to_ppptype(int);
Elliott Hughes965a4b52017-05-15 10:37:39 -0700502static struct block *gen_linktype(compiler_state_t *, int);
503static struct block *gen_snap(compiler_state_t *, bpf_u_int32, bpf_u_int32);
504static struct block *gen_llc_linktype(compiler_state_t *, int);
505static struct block *gen_hostop(compiler_state_t *, bpf_u_int32, bpf_u_int32,
506 int, int, u_int, u_int);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800507#ifdef INET6
Elliott Hughes965a4b52017-05-15 10:37:39 -0700508static struct block *gen_hostop6(compiler_state_t *, struct in6_addr *,
509 struct in6_addr *, int, int, u_int, u_int);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800510#endif
Elliott Hughes965a4b52017-05-15 10:37:39 -0700511static struct block *gen_ahostop(compiler_state_t *, const u_char *, int);
512static struct block *gen_ehostop(compiler_state_t *, const u_char *, int);
513static struct block *gen_fhostop(compiler_state_t *, const u_char *, int);
514static struct block *gen_thostop(compiler_state_t *, const u_char *, int);
515static struct block *gen_wlanhostop(compiler_state_t *, const u_char *, int);
516static struct block *gen_ipfchostop(compiler_state_t *, const u_char *, int);
517static struct block *gen_dnhostop(compiler_state_t *, bpf_u_int32, int);
518static struct block *gen_mpls_linktype(compiler_state_t *, int);
519static struct block *gen_host(compiler_state_t *, bpf_u_int32, bpf_u_int32,
520 int, int, int);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800521#ifdef INET6
Elliott Hughes965a4b52017-05-15 10:37:39 -0700522static struct block *gen_host6(compiler_state_t *, struct in6_addr *,
523 struct in6_addr *, int, int, int);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800524#endif
525#ifndef INET6
526static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);
527#endif
Elliott Hughes965a4b52017-05-15 10:37:39 -0700528static struct block *gen_ipfrag(compiler_state_t *);
529static struct block *gen_portatom(compiler_state_t *, int, bpf_int32);
530static struct block *gen_portrangeatom(compiler_state_t *, int, bpf_int32,
531 bpf_int32);
532static struct block *gen_portatom6(compiler_state_t *, int, bpf_int32);
533static struct block *gen_portrangeatom6(compiler_state_t *, int, bpf_int32,
534 bpf_int32);
535struct block *gen_portop(compiler_state_t *, int, int, int);
536static struct block *gen_port(compiler_state_t *, int, int, int);
537struct block *gen_portrangeop(compiler_state_t *, int, int, int, int);
538static struct block *gen_portrange(compiler_state_t *, int, int, int, int);
539struct block *gen_portop6(compiler_state_t *, int, int, int);
540static struct block *gen_port6(compiler_state_t *, int, int, int);
541struct block *gen_portrangeop6(compiler_state_t *, int, int, int, int);
542static struct block *gen_portrange6(compiler_state_t *, int, int, int, int);
543static int lookup_proto(compiler_state_t *, const char *, int);
544static struct block *gen_protochain(compiler_state_t *, int, int, int);
545static struct block *gen_proto(compiler_state_t *, int, int, int);
546static struct slist *xfer_to_x(compiler_state_t *, struct arth *);
547static struct slist *xfer_to_a(compiler_state_t *, struct arth *);
548static struct block *gen_mac_multicast(compiler_state_t *, int);
549static struct block *gen_len(compiler_state_t *, int, int);
550static struct block *gen_check_802_11_data_frame(compiler_state_t *);
551static struct block *gen_geneve_ll_check(compiler_state_t *cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800552
Elliott Hughes965a4b52017-05-15 10:37:39 -0700553static struct block *gen_ppi_dlt_check(compiler_state_t *);
554static struct block *gen_msg_abbrev(compiler_state_t *, int type);
555
556static void
557initchunks(compiler_state_t *cstate)
558{
559 int i;
560
561 for (i = 0; i < NCHUNKS; i++) {
562 cstate->chunks[i].n_left = 0;
563 cstate->chunks[i].m = NULL;
564 }
565 cstate->cur_chunk = 0;
566}
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800567
568static void *
Elliott Hughes965a4b52017-05-15 10:37:39 -0700569newchunk(compiler_state_t *cstate, size_t n)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800570{
571 struct chunk *cp;
572 int k;
573 size_t size;
574
575#ifndef __NetBSD__
576 /* XXX Round up to nearest long. */
577 n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);
578#else
579 /* XXX Round up to structure boundary. */
580 n = ALIGN(n);
581#endif
582
Elliott Hughes965a4b52017-05-15 10:37:39 -0700583 cp = &cstate->chunks[cstate->cur_chunk];
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800584 if (n > cp->n_left) {
Elliott Hughes965a4b52017-05-15 10:37:39 -0700585 ++cp, k = ++cstate->cur_chunk;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800586 if (k >= NCHUNKS)
Elliott Hughes965a4b52017-05-15 10:37:39 -0700587 bpf_error(cstate, "out of memory");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800588 size = CHUNK0SIZE << k;
589 cp->m = (void *)malloc(size);
590 if (cp->m == NULL)
Elliott Hughes965a4b52017-05-15 10:37:39 -0700591 bpf_error(cstate, "out of memory");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800592 memset((char *)cp->m, 0, size);
593 cp->n_left = size;
594 if (n > size)
Elliott Hughes965a4b52017-05-15 10:37:39 -0700595 bpf_error(cstate, "out of memory");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800596 }
597 cp->n_left -= n;
598 return (void *)((char *)cp->m + cp->n_left);
599}
600
601static void
Elliott Hughes965a4b52017-05-15 10:37:39 -0700602freechunks(compiler_state_t *cstate)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800603{
604 int i;
605
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800606 for (i = 0; i < NCHUNKS; ++i)
Elliott Hughes965a4b52017-05-15 10:37:39 -0700607 if (cstate->chunks[i].m != NULL)
608 free(cstate->chunks[i].m);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800609}
610
611/*
612 * A strdup whose allocations are freed after code generation is over.
613 */
614char *
Elliott Hughes965a4b52017-05-15 10:37:39 -0700615sdup(compiler_state_t *cstate, const char *s)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800616{
Elliott Hughes965a4b52017-05-15 10:37:39 -0700617 size_t n = strlen(s) + 1;
618 char *cp = newchunk(cstate, n);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800619
620 strlcpy(cp, s, n);
621 return (cp);
622}
623
624static inline struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -0700625new_block(compiler_state_t *cstate, int code)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800626{
627 struct block *p;
628
Elliott Hughes965a4b52017-05-15 10:37:39 -0700629 p = (struct block *)newchunk(cstate, sizeof(*p));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800630 p->s.code = code;
631 p->head = p;
632
633 return p;
634}
635
636static inline struct slist *
Elliott Hughes965a4b52017-05-15 10:37:39 -0700637new_stmt(compiler_state_t *cstate, int code)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800638{
639 struct slist *p;
640
Elliott Hughes965a4b52017-05-15 10:37:39 -0700641 p = (struct slist *)newchunk(cstate, sizeof(*p));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800642 p->s.code = code;
643
644 return p;
645}
646
647static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -0700648gen_retblk(compiler_state_t *cstate, int v)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800649{
Elliott Hughes965a4b52017-05-15 10:37:39 -0700650 struct block *b = new_block(cstate, BPF_RET|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800651
652 b->s.k = v;
653 return b;
654}
655
656static inline void
Elliott Hughes965a4b52017-05-15 10:37:39 -0700657syntax(compiler_state_t *cstate)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800658{
Elliott Hughes965a4b52017-05-15 10:37:39 -0700659 bpf_error(cstate, "syntax error in filter expression");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800660}
661
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800662int
663pcap_compile(pcap_t *p, struct bpf_program *program,
664 const char *buf, int optimize, bpf_u_int32 mask)
665{
Elliott Hughes965a4b52017-05-15 10:37:39 -0700666 compiler_state_t cstate;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800667 const char * volatile xbuf = buf;
Elliott Hughes965a4b52017-05-15 10:37:39 -0700668 yyscan_t scanner = NULL;
669 YY_BUFFER_STATE in_buffer = NULL;
JP Abgrall511eca32014-02-12 13:46:45 -0800670 u_int len;
Elliott Hughesd8845d72015-10-19 18:07:04 -0700671 int rc;
672
Elliott Hughes965a4b52017-05-15 10:37:39 -0700673#ifdef _WIN32
Elliott Hughesd8845d72015-10-19 18:07:04 -0700674 static int done = 0;
675
676 if (!done)
Elliott Hughes965a4b52017-05-15 10:37:39 -0700677 pcap_wsockinit();
Elliott Hughesd8845d72015-10-19 18:07:04 -0700678 done = 1;
Elliott Hughesd8845d72015-10-19 18:07:04 -0700679#endif
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800680
JP Abgrall511eca32014-02-12 13:46:45 -0800681 /*
682 * If this pcap_t hasn't been activated, it doesn't have a
683 * link-layer type, so we can't use it.
684 */
685 if (!p->activated) {
Elliott Hughes965a4b52017-05-15 10:37:39 -0700686 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
JP Abgrall511eca32014-02-12 13:46:45 -0800687 "not-yet-activated pcap_t passed to pcap_compile");
Elliott Hughesd8845d72015-10-19 18:07:04 -0700688 rc = -1;
689 goto quit;
JP Abgrall511eca32014-02-12 13:46:45 -0800690 }
Elliott Hughes965a4b52017-05-15 10:37:39 -0700691 initchunks(&cstate);
692 cstate.no_optimize = 0;
693 cstate.ai = NULL;
694 cstate.ic.root = NULL;
695 cstate.ic.cur_mark = 0;
696 cstate.bpf_pcap = p;
697 init_regs(&cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -0700698
Elliott Hughes965a4b52017-05-15 10:37:39 -0700699 if (setjmp(cstate.top_ctx)) {
JP Abgrall511eca32014-02-12 13:46:45 -0800700#ifdef INET6
Elliott Hughes965a4b52017-05-15 10:37:39 -0700701 if (cstate.ai != NULL)
702 freeaddrinfo(cstate.ai);
JP Abgrall511eca32014-02-12 13:46:45 -0800703#endif
Elliott Hughesd8845d72015-10-19 18:07:04 -0700704 rc = -1;
705 goto quit;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800706 }
707
Elliott Hughes965a4b52017-05-15 10:37:39 -0700708 cstate.netmask = mask;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800709
Elliott Hughes965a4b52017-05-15 10:37:39 -0700710 cstate.snaplen = pcap_snapshot(p);
711 if (cstate.snaplen == 0) {
712 pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800713 "snaplen of 0 rejects all packets");
Elliott Hughesd8845d72015-10-19 18:07:04 -0700714 rc = -1;
715 goto quit;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800716 }
717
Elliott Hughes965a4b52017-05-15 10:37:39 -0700718 if (pcap_lex_init(&scanner) != 0)
719 bpf_error(&cstate, "can't initialize scanner: %s", pcap_strerror(errno));
720 in_buffer = pcap__scan_string(xbuf ? xbuf : "", scanner);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800721
Elliott Hughes965a4b52017-05-15 10:37:39 -0700722 /*
723 * Associate the compiler state with the lexical analyzer
724 * state.
725 */
726 pcap_set_extra(&cstate, scanner);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800727
Elliott Hughes965a4b52017-05-15 10:37:39 -0700728 init_linktype(&cstate, p);
729 (void)pcap_parse(scanner, &cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800730
Elliott Hughes965a4b52017-05-15 10:37:39 -0700731 if (cstate.ic.root == NULL)
732 cstate.ic.root = gen_retblk(&cstate, cstate.snaplen);
733
734 if (optimize && !cstate.no_optimize) {
735 bpf_optimize(&cstate, &cstate.ic);
736 if (cstate.ic.root == NULL ||
737 (cstate.ic.root->s.code == (BPF_RET|BPF_K) && cstate.ic.root->s.k == 0))
738 bpf_error(&cstate, "expression rejects all packets");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800739 }
Elliott Hughes965a4b52017-05-15 10:37:39 -0700740 program->bf_insns = icode_to_fcode(&cstate, &cstate.ic, cstate.ic.root, &len);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800741 program->bf_len = len;
742
Elliott Hughesd8845d72015-10-19 18:07:04 -0700743 rc = 0; /* We're all okay */
744
745quit:
Elliott Hughes965a4b52017-05-15 10:37:39 -0700746 /*
747 * Clean up everything for the lexical analyzer.
748 */
749 if (in_buffer != NULL)
750 pcap__delete_buffer(in_buffer, scanner);
751 if (scanner != NULL)
752 pcap_lex_destroy(scanner);
Elliott Hughesd8845d72015-10-19 18:07:04 -0700753
Elliott Hughes965a4b52017-05-15 10:37:39 -0700754 /*
755 * Clean up our own allocated memory.
756 */
757 freechunks(&cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -0700758
759 return (rc);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800760}
761
762/*
763 * entry point for using the compiler with no pcap open
764 * pass in all the stuff that is needed explicitly instead.
765 */
766int
767pcap_compile_nopcap(int snaplen_arg, int linktype_arg,
768 struct bpf_program *program,
769 const char *buf, int optimize, bpf_u_int32 mask)
770{
771 pcap_t *p;
772 int ret;
773
774 p = pcap_open_dead(linktype_arg, snaplen_arg);
775 if (p == NULL)
776 return (-1);
777 ret = pcap_compile(p, program, buf, optimize, mask);
778 pcap_close(p);
779 return (ret);
780}
781
782/*
783 * Clean up a "struct bpf_program" by freeing all the memory allocated
784 * in it.
785 */
786void
787pcap_freecode(struct bpf_program *program)
788{
789 program->bf_len = 0;
790 if (program->bf_insns != NULL) {
791 free((char *)program->bf_insns);
792 program->bf_insns = NULL;
793 }
794}
795
796/*
797 * Backpatch the blocks in 'list' to 'target'. The 'sense' field indicates
798 * which of the jt and jf fields has been resolved and which is a pointer
799 * back to another unresolved block (or nil). At least one of the fields
800 * in each block is already resolved.
801 */
802static void
803backpatch(list, target)
804 struct block *list, *target;
805{
806 struct block *next;
807
808 while (list) {
809 if (!list->sense) {
810 next = JT(list);
811 JT(list) = target;
812 } else {
813 next = JF(list);
814 JF(list) = target;
815 }
816 list = next;
817 }
818}
819
820/*
821 * Merge the lists in b0 and b1, using the 'sense' field to indicate
822 * which of jt and jf is the link.
823 */
824static void
825merge(b0, b1)
826 struct block *b0, *b1;
827{
828 register struct block **p = &b0;
829
830 /* Find end of list. */
831 while (*p)
832 p = !((*p)->sense) ? &JT(*p) : &JF(*p);
833
834 /* Concatenate the lists. */
835 *p = b1;
836}
837
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800838void
Elliott Hughes965a4b52017-05-15 10:37:39 -0700839finish_parse(compiler_state_t *cstate, struct block *p)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800840{
841 struct block *ppi_dlt_check;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800842
843 /*
844 * Insert before the statements of the first (root) block any
845 * statements needed to load the lengths of any variable-length
846 * headers into registers.
847 *
848 * XXX - a fancier strategy would be to insert those before the
849 * statements of all blocks that use those lengths and that
850 * have no predecessors that use them, so that we only compute
851 * the lengths if we need them. There might be even better
JP Abgrall511eca32014-02-12 13:46:45 -0800852 * approaches than that.
853 *
854 * However, those strategies would be more complicated, and
855 * as we don't generate code to compute a length if the
856 * program has no tests that use the length, and as most
857 * tests will probably use those lengths, we would just
858 * postpone computing the lengths so that it's not done
859 * for tests that fail early, and it's not clear that's
860 * worth the effort.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800861 */
Elliott Hughes965a4b52017-05-15 10:37:39 -0700862 insert_compute_vloffsets(cstate, p->head);
Elliott Hughesd8845d72015-10-19 18:07:04 -0700863
JP Abgrall511eca32014-02-12 13:46:45 -0800864 /*
865 * For DLT_PPI captures, generate a check of the per-packet
866 * DLT value to make sure it's DLT_IEEE802_11.
Elliott Hughes965a4b52017-05-15 10:37:39 -0700867 *
868 * XXX - TurboCap cards use DLT_PPI for Ethernet.
869 * Can we just define some DLT_ETHERNET_WITH_PHDR pseudo-header
870 * with appropriate Ethernet information and use that rather
871 * than using something such as DLT_PPI where you don't know
872 * the link-layer header type until runtime, which, in the
873 * general case, would force us to generate both Ethernet *and*
874 * 802.11 code (*and* anything else for which PPI is used)
875 * and choose between them early in the BPF program?
JP Abgrall511eca32014-02-12 13:46:45 -0800876 */
Elliott Hughes965a4b52017-05-15 10:37:39 -0700877 ppi_dlt_check = gen_ppi_dlt_check(cstate);
JP Abgrall511eca32014-02-12 13:46:45 -0800878 if (ppi_dlt_check != NULL)
879 gen_and(ppi_dlt_check, p);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800880
Elliott Hughes965a4b52017-05-15 10:37:39 -0700881 backpatch(p, gen_retblk(cstate, cstate->snaplen));
JP Abgrall511eca32014-02-12 13:46:45 -0800882 p->sense = !p->sense;
Elliott Hughes965a4b52017-05-15 10:37:39 -0700883 backpatch(p, gen_retblk(cstate, 0));
884 cstate->ic.root = p->head;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800885}
886
887void
888gen_and(b0, b1)
889 struct block *b0, *b1;
890{
891 backpatch(b0, b1->head);
892 b0->sense = !b0->sense;
893 b1->sense = !b1->sense;
894 merge(b1, b0);
895 b1->sense = !b1->sense;
896 b1->head = b0->head;
897}
898
899void
900gen_or(b0, b1)
901 struct block *b0, *b1;
902{
903 b0->sense = !b0->sense;
904 backpatch(b0, b1->head);
905 b0->sense = !b0->sense;
906 merge(b1, b0);
907 b1->head = b0->head;
908}
909
910void
911gen_not(b)
912 struct block *b;
913{
914 b->sense = !b->sense;
915}
916
917static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -0700918gen_cmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
919 u_int size, bpf_int32 v)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800920{
Elliott Hughes965a4b52017-05-15 10:37:39 -0700921 return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800922}
923
924static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -0700925gen_cmp_gt(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
926 u_int size, bpf_int32 v)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800927{
Elliott Hughes965a4b52017-05-15 10:37:39 -0700928 return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGT, 0, v);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800929}
930
931static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -0700932gen_cmp_ge(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
933 u_int size, bpf_int32 v)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800934{
Elliott Hughes965a4b52017-05-15 10:37:39 -0700935 return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGE, 0, v);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800936}
937
938static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -0700939gen_cmp_lt(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
940 u_int size, bpf_int32 v)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800941{
Elliott Hughes965a4b52017-05-15 10:37:39 -0700942 return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGE, 1, v);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800943}
944
945static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -0700946gen_cmp_le(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
947 u_int size, bpf_int32 v)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800948{
Elliott Hughes965a4b52017-05-15 10:37:39 -0700949 return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGT, 1, v);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800950}
951
952static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -0700953gen_mcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
954 u_int size, bpf_int32 v, bpf_u_int32 mask)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800955{
Elliott Hughes965a4b52017-05-15 10:37:39 -0700956 return gen_ncmp(cstate, offrel, offset, size, mask, BPF_JEQ, 0, v);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800957}
958
959static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -0700960gen_bcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
961 u_int size, const u_char *v)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800962{
963 register struct block *b, *tmp;
964
965 b = NULL;
966 while (size >= 4) {
967 register const u_char *p = &v[size - 4];
968 bpf_int32 w = ((bpf_int32)p[0] << 24) |
969 ((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3];
970
Elliott Hughes965a4b52017-05-15 10:37:39 -0700971 tmp = gen_cmp(cstate, offrel, offset + size - 4, BPF_W, w);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800972 if (b != NULL)
973 gen_and(b, tmp);
974 b = tmp;
975 size -= 4;
976 }
977 while (size >= 2) {
978 register const u_char *p = &v[size - 2];
979 bpf_int32 w = ((bpf_int32)p[0] << 8) | p[1];
980
Elliott Hughes965a4b52017-05-15 10:37:39 -0700981 tmp = gen_cmp(cstate, offrel, offset + size - 2, BPF_H, w);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800982 if (b != NULL)
983 gen_and(b, tmp);
984 b = tmp;
985 size -= 2;
986 }
987 if (size > 0) {
Elliott Hughes965a4b52017-05-15 10:37:39 -0700988 tmp = gen_cmp(cstate, offrel, offset, BPF_B, (bpf_int32)v[0]);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -0800989 if (b != NULL)
990 gen_and(b, tmp);
991 b = tmp;
992 }
993 return b;
994}
995
996/*
997 * AND the field of size "size" at offset "offset" relative to the header
998 * specified by "offrel" with "mask", and compare it with the value "v"
999 * with the test specified by "jtype"; if "reverse" is true, the test
1000 * should test the opposite of "jtype".
1001 */
1002static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07001003gen_ncmp(compiler_state_t *cstate, enum e_offrel offrel, bpf_u_int32 offset,
1004 bpf_u_int32 size, bpf_u_int32 mask, bpf_u_int32 jtype, int reverse,
1005 bpf_int32 v)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001006{
1007 struct slist *s, *s2;
1008 struct block *b;
1009
Elliott Hughes965a4b52017-05-15 10:37:39 -07001010 s = gen_load_a(cstate, offrel, offset, size);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001011
1012 if (mask != 0xffffffff) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07001013 s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001014 s2->s.k = mask;
1015 sappend(s, s2);
1016 }
1017
Elliott Hughes965a4b52017-05-15 10:37:39 -07001018 b = new_block(cstate, JMP(jtype));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001019 b->stmts = s;
1020 b->s.k = v;
1021 if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE))
1022 gen_not(b);
1023 return b;
1024}
1025
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001026static void
Elliott Hughes965a4b52017-05-15 10:37:39 -07001027init_linktype(compiler_state_t *cstate, pcap_t *p)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001028{
Elliott Hughes965a4b52017-05-15 10:37:39 -07001029 cstate->pcap_fddipad = p->fddipad;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001030
1031 /*
Elliott Hughesd8845d72015-10-19 18:07:04 -07001032 * We start out with only one link-layer header.
1033 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001034 cstate->outermostlinktype = pcap_datalink(p);
1035 cstate->off_outermostlinkhdr.constant_part = 0;
1036 cstate->off_outermostlinkhdr.is_variable = 0;
1037 cstate->off_outermostlinkhdr.reg = -1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001038
Elliott Hughes965a4b52017-05-15 10:37:39 -07001039 cstate->prevlinktype = cstate->outermostlinktype;
1040 cstate->off_prevlinkhdr.constant_part = 0;
1041 cstate->off_prevlinkhdr.is_variable = 0;
1042 cstate->off_prevlinkhdr.reg = -1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001043
Elliott Hughes965a4b52017-05-15 10:37:39 -07001044 cstate->linktype = cstate->outermostlinktype;
1045 cstate->off_linkhdr.constant_part = 0;
1046 cstate->off_linkhdr.is_variable = 0;
1047 cstate->off_linkhdr.reg = -1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001048
1049 /*
1050 * XXX
1051 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001052 cstate->off_linkpl.constant_part = 0;
1053 cstate->off_linkpl.is_variable = 0;
1054 cstate->off_linkpl.reg = -1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001055
Elliott Hughes965a4b52017-05-15 10:37:39 -07001056 cstate->off_linktype.constant_part = 0;
1057 cstate->off_linktype.is_variable = 0;
1058 cstate->off_linktype.reg = -1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001059
1060 /*
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001061 * Assume it's not raw ATM with a pseudo-header, for now.
1062 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001063 cstate->is_atm = 0;
1064 cstate->off_vpi = -1;
1065 cstate->off_vci = -1;
1066 cstate->off_proto = -1;
1067 cstate->off_payload = -1;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001068
1069 /*
Elliott Hughesd8845d72015-10-19 18:07:04 -07001070 * And not Geneve.
JP Abgrall511eca32014-02-12 13:46:45 -08001071 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001072 cstate->is_geneve = 0;
JP Abgrall511eca32014-02-12 13:46:45 -08001073
1074 /*
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001075 * And assume we're not doing SS7.
1076 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001077 cstate->off_li = -1;
1078 cstate->off_li_hsl = -1;
1079 cstate->off_sio = -1;
1080 cstate->off_opc = -1;
1081 cstate->off_dpc = -1;
1082 cstate->off_sls = -1;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001083
Elliott Hughes965a4b52017-05-15 10:37:39 -07001084 cstate->label_stack_depth = 0;
1085 cstate->vlan_stack_depth = 0;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001086
Elliott Hughes965a4b52017-05-15 10:37:39 -07001087 switch (cstate->linktype) {
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001088
1089 case DLT_ARCNET:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001090 cstate->off_linktype.constant_part = 2;
1091 cstate->off_linkpl.constant_part = 6;
1092 cstate->off_nl = 0; /* XXX in reality, variable! */
1093 cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001094 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001095
1096 case DLT_ARCNET_LINUX:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001097 cstate->off_linktype.constant_part = 4;
1098 cstate->off_linkpl.constant_part = 8;
1099 cstate->off_nl = 0; /* XXX in reality, variable! */
1100 cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001101 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001102
1103 case DLT_EN10MB:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001104 cstate->off_linktype.constant_part = 12;
1105 cstate->off_linkpl.constant_part = 14; /* Ethernet header length */
1106 cstate->off_nl = 0; /* Ethernet II */
1107 cstate->off_nl_nosnap = 3; /* 802.3+802.2 */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001108 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001109
1110 case DLT_SLIP:
1111 /*
1112 * SLIP doesn't have a link level type. The 16 byte
1113 * header is hacked into our SLIP driver.
1114 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001115 cstate->off_linktype.constant_part = OFFSET_NOT_SET;
1116 cstate->off_linkpl.constant_part = 16;
1117 cstate->off_nl = 0;
1118 cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001119 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001120
1121 case DLT_SLIP_BSDOS:
1122 /* XXX this may be the same as the DLT_PPP_BSDOS case */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001123 cstate->off_linktype.constant_part = OFFSET_NOT_SET;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001124 /* XXX end */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001125 cstate->off_linkpl.constant_part = 24;
1126 cstate->off_nl = 0;
1127 cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001128 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001129
1130 case DLT_NULL:
1131 case DLT_LOOP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001132 cstate->off_linktype.constant_part = 0;
1133 cstate->off_linkpl.constant_part = 4;
1134 cstate->off_nl = 0;
1135 cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001136 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001137
1138 case DLT_ENC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001139 cstate->off_linktype.constant_part = 0;
1140 cstate->off_linkpl.constant_part = 12;
1141 cstate->off_nl = 0;
1142 cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001143 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001144
1145 case DLT_PPP:
1146 case DLT_PPP_PPPD:
1147 case DLT_C_HDLC: /* BSD/OS Cisco HDLC */
1148 case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001149 cstate->off_linktype.constant_part = 2; /* skip HDLC-like framing */
1150 cstate->off_linkpl.constant_part = 4; /* skip HDLC-like framing and protocol field */
1151 cstate->off_nl = 0;
1152 cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001153 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001154
1155 case DLT_PPP_ETHER:
1156 /*
1157 * This does no include the Ethernet header, and
1158 * only covers session state.
1159 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001160 cstate->off_linktype.constant_part = 6;
1161 cstate->off_linkpl.constant_part = 8;
1162 cstate->off_nl = 0;
1163 cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001164 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001165
1166 case DLT_PPP_BSDOS:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001167 cstate->off_linktype.constant_part = 5;
1168 cstate->off_linkpl.constant_part = 24;
1169 cstate->off_nl = 0;
1170 cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001171 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001172
1173 case DLT_FDDI:
1174 /*
1175 * FDDI doesn't really have a link-level type field.
1176 * We set "off_linktype" to the offset of the LLC header.
1177 *
1178 * To check for Ethernet types, we assume that SSAP = SNAP
1179 * is being used and pick out the encapsulated Ethernet type.
1180 * XXX - should we generate code to check for SNAP?
1181 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001182 cstate->off_linktype.constant_part = 13;
1183 cstate->off_linktype.constant_part += cstate->pcap_fddipad;
1184 cstate->off_linkpl.constant_part = 13; /* FDDI MAC header length */
1185 cstate->off_linkpl.constant_part += cstate->pcap_fddipad;
1186 cstate->off_nl = 8; /* 802.2+SNAP */
1187 cstate->off_nl_nosnap = 3; /* 802.2 */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001188 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001189
1190 case DLT_IEEE802:
1191 /*
1192 * Token Ring doesn't really have a link-level type field.
1193 * We set "off_linktype" to the offset of the LLC header.
1194 *
1195 * To check for Ethernet types, we assume that SSAP = SNAP
1196 * is being used and pick out the encapsulated Ethernet type.
1197 * XXX - should we generate code to check for SNAP?
1198 *
1199 * XXX - the header is actually variable-length.
1200 * Some various Linux patched versions gave 38
1201 * as "off_linktype" and 40 as "off_nl"; however,
1202 * if a token ring packet has *no* routing
1203 * information, i.e. is not source-routed, the correct
1204 * values are 20 and 22, as they are in the vanilla code.
1205 *
1206 * A packet is source-routed iff the uppermost bit
1207 * of the first byte of the source address, at an
1208 * offset of 8, has the uppermost bit set. If the
1209 * packet is source-routed, the total number of bytes
1210 * of routing information is 2 plus bits 0x1F00 of
1211 * the 16-bit value at an offset of 14 (shifted right
1212 * 8 - figure out which byte that is).
1213 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001214 cstate->off_linktype.constant_part = 14;
1215 cstate->off_linkpl.constant_part = 14; /* Token Ring MAC header length */
1216 cstate->off_nl = 8; /* 802.2+SNAP */
1217 cstate->off_nl_nosnap = 3; /* 802.2 */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001218 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001219
JP Abgrall511eca32014-02-12 13:46:45 -08001220 case DLT_PRISM_HEADER:
1221 case DLT_IEEE802_11_RADIO_AVS:
1222 case DLT_IEEE802_11_RADIO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001223 cstate->off_linkhdr.is_variable = 1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001224 /* Fall through, 802.11 doesn't have a variable link
1225 * prefix but is otherwise the same. */
1226
1227 case DLT_IEEE802_11:
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001228 /*
1229 * 802.11 doesn't really have a link-level type field.
Elliott Hughesd8845d72015-10-19 18:07:04 -07001230 * We set "off_linktype.constant_part" to the offset of
1231 * the LLC header.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001232 *
1233 * To check for Ethernet types, we assume that SSAP = SNAP
1234 * is being used and pick out the encapsulated Ethernet type.
1235 * XXX - should we generate code to check for SNAP?
1236 *
JP Abgrall511eca32014-02-12 13:46:45 -08001237 * We also handle variable-length radio headers here.
1238 * The Prism header is in theory variable-length, but in
1239 * practice it's always 144 bytes long. However, some
1240 * drivers on Linux use ARPHRD_IEEE80211_PRISM, but
1241 * sometimes or always supply an AVS header, so we
1242 * have to check whether the radio header is a Prism
1243 * header or an AVS header, so, in practice, it's
1244 * variable-length.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001245 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001246 cstate->off_linktype.constant_part = 24;
1247 cstate->off_linkpl.constant_part = 0; /* link-layer header is variable-length */
1248 cstate->off_linkpl.is_variable = 1;
1249 cstate->off_nl = 8; /* 802.2+SNAP */
1250 cstate->off_nl_nosnap = 3; /* 802.2 */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001251 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001252
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001253 case DLT_PPI:
Elliott Hughesd8845d72015-10-19 18:07:04 -07001254 /*
JP Abgrall511eca32014-02-12 13:46:45 -08001255 * At the moment we treat PPI the same way that we treat
1256 * normal Radiotap encoded packets. The difference is in
1257 * the function that generates the code at the beginning
1258 * to compute the header length. Since this code generator
1259 * of PPI supports bare 802.11 encapsulation only (i.e.
1260 * the encapsulated DLT should be DLT_IEEE802_11) we
1261 * generate code to check for this too.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001262 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001263 cstate->off_linktype.constant_part = 24;
1264 cstate->off_linkpl.constant_part = 0; /* link-layer header is variable-length */
1265 cstate->off_linkpl.is_variable = 1;
1266 cstate->off_linkhdr.is_variable = 1;
1267 cstate->off_nl = 8; /* 802.2+SNAP */
1268 cstate->off_nl_nosnap = 3; /* 802.2 */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001269 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001270
1271 case DLT_ATM_RFC1483:
1272 case DLT_ATM_CLIP: /* Linux ATM defines this */
1273 /*
1274 * assume routed, non-ISO PDUs
1275 * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00)
1276 *
1277 * XXX - what about ISO PDUs, e.g. CLNP, ISIS, ESIS,
1278 * or PPP with the PPP NLPID (e.g., PPPoA)? The
1279 * latter would presumably be treated the way PPPoE
1280 * should be, so you can do "pppoe and udp port 2049"
1281 * or "pppoa and tcp port 80" and have it check for
1282 * PPPo{A,E} and a PPP protocol of IP and....
1283 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001284 cstate->off_linktype.constant_part = 0;
1285 cstate->off_linkpl.constant_part = 0; /* packet begins with LLC header */
1286 cstate->off_nl = 8; /* 802.2+SNAP */
1287 cstate->off_nl_nosnap = 3; /* 802.2 */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001288 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001289
1290 case DLT_SUNATM:
1291 /*
1292 * Full Frontal ATM; you get AALn PDUs with an ATM
1293 * pseudo-header.
1294 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001295 cstate->is_atm = 1;
1296 cstate->off_vpi = SUNATM_VPI_POS;
1297 cstate->off_vci = SUNATM_VCI_POS;
1298 cstate->off_proto = PROTO_POS;
1299 cstate->off_payload = SUNATM_PKT_BEGIN_POS;
1300 cstate->off_linktype.constant_part = cstate->off_payload;
1301 cstate->off_linkpl.constant_part = cstate->off_payload; /* if LLC-encapsulated */
1302 cstate->off_nl = 8; /* 802.2+SNAP */
1303 cstate->off_nl_nosnap = 3; /* 802.2 */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001304 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001305
1306 case DLT_RAW:
JP Abgrall511eca32014-02-12 13:46:45 -08001307 case DLT_IPV4:
1308 case DLT_IPV6:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001309 cstate->off_linktype.constant_part = OFFSET_NOT_SET;
1310 cstate->off_linkpl.constant_part = 0;
1311 cstate->off_nl = 0;
1312 cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001313 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001314
1315 case DLT_LINUX_SLL: /* fake header for Linux cooked socket */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001316 cstate->off_linktype.constant_part = 14;
1317 cstate->off_linkpl.constant_part = 16;
1318 cstate->off_nl = 0;
1319 cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001320 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001321
1322 case DLT_LTALK:
1323 /*
1324 * LocalTalk does have a 1-byte type field in the LLAP header,
1325 * but really it just indicates whether there is a "short" or
1326 * "long" DDP packet following.
1327 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001328 cstate->off_linktype.constant_part = OFFSET_NOT_SET;
1329 cstate->off_linkpl.constant_part = 0;
1330 cstate->off_nl = 0;
1331 cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001332 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001333
1334 case DLT_IP_OVER_FC:
1335 /*
1336 * RFC 2625 IP-over-Fibre-Channel doesn't really have a
1337 * link-level type field. We set "off_linktype" to the
1338 * offset of the LLC header.
1339 *
1340 * To check for Ethernet types, we assume that SSAP = SNAP
1341 * is being used and pick out the encapsulated Ethernet type.
1342 * XXX - should we generate code to check for SNAP? RFC
1343 * 2625 says SNAP should be used.
1344 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001345 cstate->off_linktype.constant_part = 16;
1346 cstate->off_linkpl.constant_part = 16;
1347 cstate->off_nl = 8; /* 802.2+SNAP */
1348 cstate->off_nl_nosnap = 3; /* 802.2 */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001349 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001350
1351 case DLT_FRELAY:
1352 /*
1353 * XXX - we should set this to handle SNAP-encapsulated
1354 * frames (NLPID of 0x80).
1355 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001356 cstate->off_linktype.constant_part = OFFSET_NOT_SET;
1357 cstate->off_linkpl.constant_part = 0;
1358 cstate->off_nl = 0;
1359 cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001360 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001361
1362 /*
1363 * the only BPF-interesting FRF.16 frames are non-control frames;
1364 * Frame Relay has a variable length link-layer
1365 * so lets start with offset 4 for now and increments later on (FIXME);
1366 */
1367 case DLT_MFR:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001368 cstate->off_linktype.constant_part = OFFSET_NOT_SET;
1369 cstate->off_linkpl.constant_part = 0;
1370 cstate->off_nl = 4;
1371 cstate->off_nl_nosnap = 0; /* XXX - for now -> no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001372 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001373
1374 case DLT_APPLE_IP_OVER_IEEE1394:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001375 cstate->off_linktype.constant_part = 16;
1376 cstate->off_linkpl.constant_part = 18;
1377 cstate->off_nl = 0;
1378 cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001379 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001380
1381 case DLT_SYMANTEC_FIREWALL:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001382 cstate->off_linktype.constant_part = 6;
1383 cstate->off_linkpl.constant_part = 44;
1384 cstate->off_nl = 0; /* Ethernet II */
1385 cstate->off_nl_nosnap = 0; /* XXX - what does it do with 802.3 packets? */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001386 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001387
1388#ifdef HAVE_NET_PFVAR_H
1389 case DLT_PFLOG:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001390 cstate->off_linktype.constant_part = 0;
1391 cstate->off_linkpl.constant_part = PFLOG_HDRLEN;
1392 cstate->off_nl = 0;
1393 cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001394 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001395#endif
1396
1397 case DLT_JUNIPER_MFR:
1398 case DLT_JUNIPER_MLFR:
1399 case DLT_JUNIPER_MLPPP:
1400 case DLT_JUNIPER_PPP:
1401 case DLT_JUNIPER_CHDLC:
1402 case DLT_JUNIPER_FRELAY:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001403 cstate->off_linktype.constant_part = 4;
1404 cstate->off_linkpl.constant_part = 4;
1405 cstate->off_nl = 0;
1406 cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001407 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001408
1409 case DLT_JUNIPER_ATM1:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001410 cstate->off_linktype.constant_part = 4; /* in reality variable between 4-8 */
1411 cstate->off_linkpl.constant_part = 4; /* in reality variable between 4-8 */
1412 cstate->off_nl = 0;
1413 cstate->off_nl_nosnap = 10;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001414 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001415
1416 case DLT_JUNIPER_ATM2:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001417 cstate->off_linktype.constant_part = 8; /* in reality variable between 8-12 */
1418 cstate->off_linkpl.constant_part = 8; /* in reality variable between 8-12 */
1419 cstate->off_nl = 0;
1420 cstate->off_nl_nosnap = 10;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001421 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001422
1423 /* frames captured on a Juniper PPPoE service PIC
1424 * contain raw ethernet frames */
1425 case DLT_JUNIPER_PPPOE:
1426 case DLT_JUNIPER_ETHER:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001427 cstate->off_linkpl.constant_part = 14;
1428 cstate->off_linktype.constant_part = 16;
1429 cstate->off_nl = 18; /* Ethernet II */
1430 cstate->off_nl_nosnap = 21; /* 802.3+802.2 */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001431 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001432
1433 case DLT_JUNIPER_PPPOE_ATM:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001434 cstate->off_linktype.constant_part = 4;
1435 cstate->off_linkpl.constant_part = 6;
1436 cstate->off_nl = 0;
1437 cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001438 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001439
1440 case DLT_JUNIPER_GGSN:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001441 cstate->off_linktype.constant_part = 6;
1442 cstate->off_linkpl.constant_part = 12;
1443 cstate->off_nl = 0;
1444 cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001445 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001446
1447 case DLT_JUNIPER_ES:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001448 cstate->off_linktype.constant_part = 6;
1449 cstate->off_linkpl.constant_part = OFFSET_NOT_SET; /* not really a network layer but raw IP addresses */
1450 cstate->off_nl = -1; /* not really a network layer but raw IP addresses */
1451 cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001452 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001453
1454 case DLT_JUNIPER_MONITOR:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001455 cstate->off_linktype.constant_part = 12;
1456 cstate->off_linkpl.constant_part = 12;
1457 cstate->off_nl = 0; /* raw IP/IP6 header */
1458 cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001459 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001460
JP Abgrall511eca32014-02-12 13:46:45 -08001461 case DLT_BACNET_MS_TP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001462 cstate->off_linktype.constant_part = OFFSET_NOT_SET;
1463 cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
1464 cstate->off_nl = -1;
1465 cstate->off_nl_nosnap = -1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001466 break;
JP Abgrall511eca32014-02-12 13:46:45 -08001467
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001468 case DLT_JUNIPER_SERVICES:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001469 cstate->off_linktype.constant_part = 12;
1470 cstate->off_linkpl.constant_part = OFFSET_NOT_SET; /* L3 proto location dep. on cookie type */
1471 cstate->off_nl = -1; /* L3 proto location dep. on cookie type */
1472 cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001473 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001474
1475 case DLT_JUNIPER_VP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001476 cstate->off_linktype.constant_part = 18;
1477 cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
1478 cstate->off_nl = -1;
1479 cstate->off_nl_nosnap = -1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001480 break;
JP Abgrall511eca32014-02-12 13:46:45 -08001481
1482 case DLT_JUNIPER_ST:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001483 cstate->off_linktype.constant_part = 18;
1484 cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
1485 cstate->off_nl = -1;
1486 cstate->off_nl_nosnap = -1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001487 break;
JP Abgrall511eca32014-02-12 13:46:45 -08001488
1489 case DLT_JUNIPER_ISM:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001490 cstate->off_linktype.constant_part = 8;
1491 cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
1492 cstate->off_nl = -1;
1493 cstate->off_nl_nosnap = -1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001494 break;
JP Abgrall511eca32014-02-12 13:46:45 -08001495
1496 case DLT_JUNIPER_VS:
1497 case DLT_JUNIPER_SRX_E2E:
1498 case DLT_JUNIPER_FIBRECHANNEL:
1499 case DLT_JUNIPER_ATM_CEMIC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001500 cstate->off_linktype.constant_part = 8;
1501 cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
1502 cstate->off_nl = -1;
1503 cstate->off_nl_nosnap = -1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001504 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001505
1506 case DLT_MTP2:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001507 cstate->off_li = 2;
1508 cstate->off_li_hsl = 4;
1509 cstate->off_sio = 3;
1510 cstate->off_opc = 4;
1511 cstate->off_dpc = 4;
1512 cstate->off_sls = 7;
1513 cstate->off_linktype.constant_part = OFFSET_NOT_SET;
1514 cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
1515 cstate->off_nl = -1;
1516 cstate->off_nl_nosnap = -1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001517 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001518
1519 case DLT_MTP2_WITH_PHDR:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001520 cstate->off_li = 6;
1521 cstate->off_li_hsl = 8;
1522 cstate->off_sio = 7;
1523 cstate->off_opc = 8;
1524 cstate->off_dpc = 8;
1525 cstate->off_sls = 11;
1526 cstate->off_linktype.constant_part = OFFSET_NOT_SET;
1527 cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
1528 cstate->off_nl = -1;
1529 cstate->off_nl_nosnap = -1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001530 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001531
JP Abgrall511eca32014-02-12 13:46:45 -08001532 case DLT_ERF:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001533 cstate->off_li = 22;
1534 cstate->off_li_hsl = 24;
1535 cstate->off_sio = 23;
1536 cstate->off_opc = 24;
1537 cstate->off_dpc = 24;
1538 cstate->off_sls = 27;
1539 cstate->off_linktype.constant_part = OFFSET_NOT_SET;
1540 cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
1541 cstate->off_nl = -1;
1542 cstate->off_nl_nosnap = -1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001543 break;
JP Abgrall511eca32014-02-12 13:46:45 -08001544
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001545 case DLT_PFSYNC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001546 cstate->off_linktype.constant_part = OFFSET_NOT_SET;
1547 cstate->off_linkpl.constant_part = 4;
1548 cstate->off_nl = 0;
1549 cstate->off_nl_nosnap = 0;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001550 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001551
JP Abgrall511eca32014-02-12 13:46:45 -08001552 case DLT_AX25_KISS:
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001553 /*
1554 * Currently, only raw "link[N:M]" filtering is supported.
1555 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001556 cstate->off_linktype.constant_part = OFFSET_NOT_SET; /* variable, min 15, max 71 steps of 7 */
1557 cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
1558 cstate->off_nl = -1; /* variable, min 16, max 71 steps of 7 */
1559 cstate->off_nl_nosnap = -1; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001560 break;
JP Abgrall511eca32014-02-12 13:46:45 -08001561
1562 case DLT_IPNET:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001563 cstate->off_linktype.constant_part = 1;
1564 cstate->off_linkpl.constant_part = 24; /* ipnet header length */
1565 cstate->off_nl = 0;
1566 cstate->off_nl_nosnap = -1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001567 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001568
JP Abgrall511eca32014-02-12 13:46:45 -08001569 case DLT_NETANALYZER:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001570 cstate->off_linkhdr.constant_part = 4; /* Ethernet header is past 4-byte pseudo-header */
1571 cstate->off_linktype.constant_part = cstate->off_linkhdr.constant_part + 12;
1572 cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 14; /* pseudo-header+Ethernet header length */
1573 cstate->off_nl = 0; /* Ethernet II */
1574 cstate->off_nl_nosnap = 3; /* 802.3+802.2 */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001575 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001576
JP Abgrall511eca32014-02-12 13:46:45 -08001577 case DLT_NETANALYZER_TRANSPARENT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001578 cstate->off_linkhdr.constant_part = 12; /* MAC header is past 4-byte pseudo-header, preamble, and SFD */
1579 cstate->off_linktype.constant_part = cstate->off_linkhdr.constant_part + 12;
1580 cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 14; /* pseudo-header+preamble+SFD+Ethernet header length */
1581 cstate->off_nl = 0; /* Ethernet II */
1582 cstate->off_nl_nosnap = 3; /* 802.3+802.2 */
Elliott Hughesd8845d72015-10-19 18:07:04 -07001583 break;
JP Abgrall511eca32014-02-12 13:46:45 -08001584
1585 default:
1586 /*
1587 * For values in the range in which we've assigned new
1588 * DLT_ values, only raw "link[N:M]" filtering is supported.
1589 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001590 if (cstate->linktype >= DLT_MATCHING_MIN &&
1591 cstate->linktype <= DLT_MATCHING_MAX) {
1592 cstate->off_linktype.constant_part = OFFSET_NOT_SET;
1593 cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
1594 cstate->off_nl = -1;
1595 cstate->off_nl_nosnap = -1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07001596 } else {
Elliott Hughes965a4b52017-05-15 10:37:39 -07001597 bpf_error(cstate, "unknown data link type %d", cstate->linktype);
JP Abgrall511eca32014-02-12 13:46:45 -08001598 }
Elliott Hughesd8845d72015-10-19 18:07:04 -07001599 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001600 }
Elliott Hughesd8845d72015-10-19 18:07:04 -07001601
Elliott Hughes965a4b52017-05-15 10:37:39 -07001602 cstate->off_outermostlinkhdr = cstate->off_prevlinkhdr = cstate->off_linkhdr;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001603}
1604
1605/*
Elliott Hughesd8845d72015-10-19 18:07:04 -07001606 * Load a value relative to the specified absolute offset.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001607 */
1608static struct slist *
Elliott Hughes965a4b52017-05-15 10:37:39 -07001609gen_load_absoffsetrel(compiler_state_t *cstate, bpf_abs_offset *abs_offset,
1610 u_int offset, u_int size)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001611{
1612 struct slist *s, *s2;
1613
Elliott Hughes965a4b52017-05-15 10:37:39 -07001614 s = gen_abs_offset_varpart(cstate, abs_offset);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001615
1616 /*
1617 * If "s" is non-null, it has code to arrange that the X register
Elliott Hughesd8845d72015-10-19 18:07:04 -07001618 * contains the variable part of the absolute offset, so we
1619 * generate a load relative to that, with an offset of
1620 * abs_offset->constant_part + offset.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001621 *
Elliott Hughesd8845d72015-10-19 18:07:04 -07001622 * Otherwise, we can do an absolute load with an offset of
1623 * abs_offset->constant_part + offset.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001624 */
1625 if (s != NULL) {
1626 /*
Elliott Hughesd8845d72015-10-19 18:07:04 -07001627 * "s" points to a list of statements that puts the
1628 * variable part of the absolute offset into the X register.
1629 * Do an indirect load, to use the X register as an offset.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001630 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001631 s2 = new_stmt(cstate, BPF_LD|BPF_IND|size);
Elliott Hughesd8845d72015-10-19 18:07:04 -07001632 s2->s.k = abs_offset->constant_part + offset;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001633 sappend(s, s2);
1634 } else {
1635 /*
Elliott Hughesd8845d72015-10-19 18:07:04 -07001636 * There is no variable part of the absolute offset, so
1637 * just do an absolute load.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001638 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001639 s = new_stmt(cstate, BPF_LD|BPF_ABS|size);
Elliott Hughesd8845d72015-10-19 18:07:04 -07001640 s->s.k = abs_offset->constant_part + offset;
JP Abgrall511eca32014-02-12 13:46:45 -08001641 }
1642 return s;
1643}
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001644
1645/*
1646 * Load a value relative to the beginning of the specified header.
1647 */
1648static struct slist *
Elliott Hughes965a4b52017-05-15 10:37:39 -07001649gen_load_a(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
1650 u_int size)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001651{
1652 struct slist *s, *s2;
1653
1654 switch (offrel) {
1655
1656 case OR_PACKET:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001657 s = new_stmt(cstate, BPF_LD|BPF_ABS|size);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001658 s->s.k = offset;
1659 break;
1660
Elliott Hughesd8845d72015-10-19 18:07:04 -07001661 case OR_LINKHDR:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001662 s = gen_load_absoffsetrel(cstate, &cstate->off_linkhdr, offset, size);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001663 break;
1664
Elliott Hughesd8845d72015-10-19 18:07:04 -07001665 case OR_PREVLINKHDR:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001666 s = gen_load_absoffsetrel(cstate, &cstate->off_prevlinkhdr, offset, size);
JP Abgrall511eca32014-02-12 13:46:45 -08001667 break;
1668
Elliott Hughesd8845d72015-10-19 18:07:04 -07001669 case OR_LLC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001670 s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, offset, size);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001671 break;
1672
Elliott Hughesd8845d72015-10-19 18:07:04 -07001673 case OR_PREVMPLSHDR:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001674 s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl - 4 + offset, size);
Elliott Hughesd8845d72015-10-19 18:07:04 -07001675 break;
1676
1677 case OR_LINKPL:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001678 s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl + offset, size);
Elliott Hughesd8845d72015-10-19 18:07:04 -07001679 break;
1680
1681 case OR_LINKPL_NOSNAP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001682 s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl_nosnap + offset, size);
Elliott Hughesd8845d72015-10-19 18:07:04 -07001683 break;
1684
1685 case OR_LINKTYPE:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001686 s = gen_load_absoffsetrel(cstate, &cstate->off_linktype, offset, size);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001687 break;
1688
1689 case OR_TRAN_IPV4:
1690 /*
1691 * Load the X register with the length of the IPv4 header
1692 * (plus the offset of the link-layer header, if it's
1693 * preceded by a variable-length header such as a radio
1694 * header), in bytes.
1695 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001696 s = gen_loadx_iphdrlen(cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001697
1698 /*
Elliott Hughesd8845d72015-10-19 18:07:04 -07001699 * Load the item at {offset of the link-layer payload} +
1700 * {offset, relative to the start of the link-layer
JP Abgrall511eca32014-02-12 13:46:45 -08001701 * paylod, of the IPv4 header} + {length of the IPv4 header} +
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001702 * {specified offset}.
1703 *
Elliott Hughesd8845d72015-10-19 18:07:04 -07001704 * If the offset of the link-layer payload is variable,
1705 * the variable part of that offset is included in the
1706 * value in the X register, and we include the constant
1707 * part in the offset of the load.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001708 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001709 s2 = new_stmt(cstate, BPF_LD|BPF_IND|size);
1710 s2->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + offset;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001711 sappend(s, s2);
1712 break;
1713
1714 case OR_TRAN_IPV6:
Elliott Hughes965a4b52017-05-15 10:37:39 -07001715 s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl + 40 + offset, size);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001716 break;
1717
1718 default:
1719 abort();
1720 return NULL;
1721 }
1722 return s;
1723}
1724
1725/*
1726 * Generate code to load into the X register the sum of the length of
Elliott Hughesd8845d72015-10-19 18:07:04 -07001727 * the IPv4 header and the variable part of the offset of the link-layer
1728 * payload.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001729 */
1730static struct slist *
Elliott Hughes965a4b52017-05-15 10:37:39 -07001731gen_loadx_iphdrlen(compiler_state_t *cstate)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001732{
1733 struct slist *s, *s2;
1734
Elliott Hughes965a4b52017-05-15 10:37:39 -07001735 s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001736 if (s != NULL) {
1737 /*
Elliott Hughesd8845d72015-10-19 18:07:04 -07001738 * The offset of the link-layer payload has a variable
1739 * part. "s" points to a list of statements that put
1740 * the variable part of that offset into the X register.
JP Abgrall511eca32014-02-12 13:46:45 -08001741 *
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001742 * The 4*([k]&0xf) addressing mode can't be used, as we
1743 * don't have a constant offset, so we have to load the
1744 * value in question into the A register and add to it
1745 * the value from the X register.
1746 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001747 s2 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
1748 s2->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001749 sappend(s, s2);
Elliott Hughes965a4b52017-05-15 10:37:39 -07001750 s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001751 s2->s.k = 0xf;
1752 sappend(s, s2);
Elliott Hughes965a4b52017-05-15 10:37:39 -07001753 s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001754 s2->s.k = 2;
1755 sappend(s, s2);
1756
1757 /*
Elliott Hughesd8845d72015-10-19 18:07:04 -07001758 * The A register now contains the length of the IP header.
1759 * We need to add to it the variable part of the offset of
1760 * the link-layer payload, which is still in the X
JP Abgrall511eca32014-02-12 13:46:45 -08001761 * register, and move the result into the X register.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001762 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001763 sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
1764 sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001765 } else {
1766 /*
Elliott Hughesd8845d72015-10-19 18:07:04 -07001767 * The offset of the link-layer payload is a constant,
1768 * so no code was generated to load the (non-existent)
1769 * variable part of that offset.
1770 *
1771 * This means we can use the 4*([k]&0xf) addressing
1772 * mode. Load the length of the IPv4 header, which
Elliott Hughes965a4b52017-05-15 10:37:39 -07001773 * is at an offset of cstate->off_nl from the beginning of
Elliott Hughesd8845d72015-10-19 18:07:04 -07001774 * the link-layer payload, and thus at an offset of
Elliott Hughes965a4b52017-05-15 10:37:39 -07001775 * cstate->off_linkpl.constant_part + cstate->off_nl from the beginning
Elliott Hughesd8845d72015-10-19 18:07:04 -07001776 * of the raw packet data, using that addressing mode.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001777 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001778 s = new_stmt(cstate, BPF_LDX|BPF_MSH|BPF_B);
1779 s->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001780 }
1781 return s;
1782}
1783
1784static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07001785gen_uncond(compiler_state_t *cstate, int rsense)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001786{
1787 struct block *b;
1788 struct slist *s;
1789
Elliott Hughes965a4b52017-05-15 10:37:39 -07001790 s = new_stmt(cstate, BPF_LD|BPF_IMM);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001791 s->s.k = !rsense;
Elliott Hughes965a4b52017-05-15 10:37:39 -07001792 b = new_block(cstate, JMP(BPF_JEQ));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001793 b->stmts = s;
1794
1795 return b;
1796}
1797
1798static inline struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07001799gen_true(compiler_state_t *cstate)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001800{
Elliott Hughes965a4b52017-05-15 10:37:39 -07001801 return gen_uncond(cstate, 1);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001802}
1803
1804static inline struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07001805gen_false(compiler_state_t *cstate)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001806{
Elliott Hughes965a4b52017-05-15 10:37:39 -07001807 return gen_uncond(cstate, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001808}
1809
1810/*
1811 * Byte-swap a 32-bit number.
1812 * ("htonl()" or "ntohl()" won't work - we want to byte-swap even on
1813 * big-endian platforms.)
1814 */
1815#define SWAPLONG(y) \
1816((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
1817
1818/*
1819 * Generate code to match a particular packet type.
1820 *
1821 * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
1822 * value, if <= ETHERMTU. We use that to determine whether to
1823 * match the type/length field or to check the type/length field for
1824 * a value <= ETHERMTU to see whether it's a type field and then do
1825 * the appropriate test.
1826 */
1827static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07001828gen_ether_linktype(compiler_state_t *cstate, int proto)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001829{
1830 struct block *b0, *b1;
1831
1832 switch (proto) {
1833
1834 case LLCSAP_ISONS:
1835 case LLCSAP_IP:
1836 case LLCSAP_NETBEUI:
1837 /*
1838 * OSI protocols and NetBEUI always use 802.2 encapsulation,
1839 * so we check the DSAP and SSAP.
1840 *
1841 * LLCSAP_IP checks for IP-over-802.2, rather
1842 * than IP-over-Ethernet or IP-over-SNAP.
1843 *
1844 * XXX - should we check both the DSAP and the
1845 * SSAP, like this, or should we check just the
1846 * DSAP, as we do for other types <= ETHERMTU
1847 * (i.e., other SAP values)?
1848 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001849 b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001850 gen_not(b0);
Elliott Hughes965a4b52017-05-15 10:37:39 -07001851 b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001852 ((proto << 8) | proto));
1853 gen_and(b0, b1);
1854 return b1;
1855
1856 case LLCSAP_IPX:
1857 /*
1858 * Check for;
1859 *
1860 * Ethernet_II frames, which are Ethernet
1861 * frames with a frame type of ETHERTYPE_IPX;
1862 *
1863 * Ethernet_802.3 frames, which are 802.3
1864 * frames (i.e., the type/length field is
1865 * a length field, <= ETHERMTU, rather than
1866 * a type field) with the first two bytes
1867 * after the Ethernet/802.3 header being
1868 * 0xFFFF;
1869 *
1870 * Ethernet_802.2 frames, which are 802.3
1871 * frames with an 802.2 LLC header and
1872 * with the IPX LSAP as the DSAP in the LLC
1873 * header;
1874 *
1875 * Ethernet_SNAP frames, which are 802.3
1876 * frames with an LLC header and a SNAP
1877 * header and with an OUI of 0x000000
1878 * (encapsulated Ethernet) and a protocol
1879 * ID of ETHERTYPE_IPX in the SNAP header.
1880 *
1881 * XXX - should we generate the same code both
1882 * for tests for LLCSAP_IPX and for ETHERTYPE_IPX?
1883 */
1884
1885 /*
1886 * This generates code to check both for the
1887 * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3.
1888 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001889 b0 = gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
1890 b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001891 gen_or(b0, b1);
1892
1893 /*
1894 * Now we add code to check for SNAP frames with
1895 * ETHERTYPE_IPX, i.e. Ethernet_SNAP.
1896 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001897 b0 = gen_snap(cstate, 0x000000, ETHERTYPE_IPX);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001898 gen_or(b0, b1);
1899
1900 /*
1901 * Now we generate code to check for 802.3
1902 * frames in general.
1903 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001904 b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001905 gen_not(b0);
1906
1907 /*
1908 * Now add the check for 802.3 frames before the
1909 * check for Ethernet_802.2 and Ethernet_802.3,
1910 * as those checks should only be done on 802.3
1911 * frames, not on Ethernet frames.
1912 */
1913 gen_and(b0, b1);
1914
1915 /*
1916 * Now add the check for Ethernet_II frames, and
1917 * do that before checking for the other frame
1918 * types.
1919 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001920 b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001921 gen_or(b0, b1);
1922 return b1;
1923
1924 case ETHERTYPE_ATALK:
1925 case ETHERTYPE_AARP:
1926 /*
1927 * EtherTalk (AppleTalk protocols on Ethernet link
1928 * layer) may use 802.2 encapsulation.
1929 */
1930
1931 /*
1932 * Check for 802.2 encapsulation (EtherTalk phase 2?);
1933 * we check for an Ethernet type field less than
1934 * 1500, which means it's an 802.3 length field.
1935 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001936 b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001937 gen_not(b0);
1938
1939 /*
1940 * 802.2-encapsulated ETHERTYPE_ATALK packets are
1941 * SNAP packets with an organization code of
1942 * 0x080007 (Apple, for Appletalk) and a protocol
1943 * type of ETHERTYPE_ATALK (Appletalk).
1944 *
1945 * 802.2-encapsulated ETHERTYPE_AARP packets are
1946 * SNAP packets with an organization code of
1947 * 0x000000 (encapsulated Ethernet) and a protocol
1948 * type of ETHERTYPE_AARP (Appletalk ARP).
1949 */
1950 if (proto == ETHERTYPE_ATALK)
Elliott Hughes965a4b52017-05-15 10:37:39 -07001951 b1 = gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001952 else /* proto == ETHERTYPE_AARP */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001953 b1 = gen_snap(cstate, 0x000000, ETHERTYPE_AARP);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001954 gen_and(b0, b1);
1955
1956 /*
1957 * Check for Ethernet encapsulation (Ethertalk
1958 * phase 1?); we just check for the Ethernet
1959 * protocol type.
1960 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001961 b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001962
1963 gen_or(b0, b1);
1964 return b1;
1965
1966 default:
1967 if (proto <= ETHERMTU) {
1968 /*
1969 * This is an LLC SAP value, so the frames
1970 * that match would be 802.2 frames.
1971 * Check that the frame is an 802.2 frame
1972 * (i.e., that the length/type field is
1973 * a length field, <= ETHERMTU) and
1974 * then check the DSAP.
1975 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001976 b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001977 gen_not(b0);
Elliott Hughes965a4b52017-05-15 10:37:39 -07001978 b1 = gen_cmp(cstate, OR_LINKTYPE, 2, BPF_B, (bpf_int32)proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001979 gen_and(b0, b1);
1980 return b1;
1981 } else {
1982 /*
1983 * This is an Ethernet type, so compare
1984 * the length/type field with it (if
1985 * the frame is an 802.2 frame, the length
1986 * field will be <= ETHERMTU, and, as
1987 * "proto" is > ETHERMTU, this test
1988 * will fail and the frame won't match,
1989 * which is what we want).
1990 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07001991 return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08001992 (bpf_int32)proto);
1993 }
1994 }
1995}
1996
Elliott Hughes965a4b52017-05-15 10:37:39 -07001997static struct block *
1998gen_loopback_linktype(compiler_state_t *cstate, int proto)
1999{
2000 /*
2001 * For DLT_NULL, the link-layer header is a 32-bit word
2002 * containing an AF_ value in *host* byte order, and for
2003 * DLT_ENC, the link-layer header begins with a 32-bit
2004 * word containing an AF_ value in host byte order.
2005 *
2006 * In addition, if we're reading a saved capture file,
2007 * the host byte order in the capture may not be the
2008 * same as the host byte order on this machine.
2009 *
2010 * For DLT_LOOP, the link-layer header is a 32-bit
2011 * word containing an AF_ value in *network* byte order.
2012 */
2013 if (cstate->linktype == DLT_NULL || cstate->linktype == DLT_ENC) {
2014 /*
2015 * The AF_ value is in host byte order, but the BPF
2016 * interpreter will convert it to network byte order.
2017 *
2018 * If this is a save file, and it's from a machine
2019 * with the opposite byte order to ours, we byte-swap
2020 * the AF_ value.
2021 *
2022 * Then we run it through "htonl()", and generate
2023 * code to compare against the result.
2024 */
2025 if (cstate->bpf_pcap->rfile != NULL && cstate->bpf_pcap->swapped)
2026 proto = SWAPLONG(proto);
2027 proto = htonl(proto);
2028 }
2029 return (gen_cmp(cstate, OR_LINKHDR, 0, BPF_W, (bpf_int32)proto));
2030}
2031
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002032/*
JP Abgrall511eca32014-02-12 13:46:45 -08002033 * "proto" is an Ethernet type value and for IPNET, if it is not IPv4
2034 * or IPv6 then we have an error.
2035 */
2036static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07002037gen_ipnet_linktype(compiler_state_t *cstate, int proto)
JP Abgrall511eca32014-02-12 13:46:45 -08002038{
2039 switch (proto) {
2040
2041 case ETHERTYPE_IP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07002042 return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B, (bpf_int32)IPH_AF_INET);
JP Abgrall511eca32014-02-12 13:46:45 -08002043 /* NOTREACHED */
2044
2045 case ETHERTYPE_IPV6:
Elliott Hughes965a4b52017-05-15 10:37:39 -07002046 return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
JP Abgrall511eca32014-02-12 13:46:45 -08002047 (bpf_int32)IPH_AF_INET6);
2048 /* NOTREACHED */
2049
2050 default:
2051 break;
2052 }
2053
Elliott Hughes965a4b52017-05-15 10:37:39 -07002054 return gen_false(cstate);
JP Abgrall511eca32014-02-12 13:46:45 -08002055}
2056
2057/*
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002058 * Generate code to match a particular packet type.
2059 *
2060 * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
2061 * value, if <= ETHERMTU. We use that to determine whether to
2062 * match the type field or to check the type field for the special
2063 * LINUX_SLL_P_802_2 value and then do the appropriate test.
2064 */
2065static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07002066gen_linux_sll_linktype(compiler_state_t *cstate, int proto)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002067{
2068 struct block *b0, *b1;
2069
2070 switch (proto) {
2071
2072 case LLCSAP_ISONS:
2073 case LLCSAP_IP:
2074 case LLCSAP_NETBEUI:
2075 /*
2076 * OSI protocols and NetBEUI always use 802.2 encapsulation,
2077 * so we check the DSAP and SSAP.
2078 *
2079 * LLCSAP_IP checks for IP-over-802.2, rather
2080 * than IP-over-Ethernet or IP-over-SNAP.
2081 *
2082 * XXX - should we check both the DSAP and the
2083 * SSAP, like this, or should we check just the
2084 * DSAP, as we do for other types <= ETHERMTU
2085 * (i.e., other SAP values)?
2086 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002087 b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
2088 b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002089 ((proto << 8) | proto));
2090 gen_and(b0, b1);
2091 return b1;
2092
2093 case LLCSAP_IPX:
2094 /*
2095 * Ethernet_II frames, which are Ethernet
2096 * frames with a frame type of ETHERTYPE_IPX;
2097 *
2098 * Ethernet_802.3 frames, which have a frame
2099 * type of LINUX_SLL_P_802_3;
2100 *
2101 * Ethernet_802.2 frames, which are 802.3
2102 * frames with an 802.2 LLC header (i.e, have
2103 * a frame type of LINUX_SLL_P_802_2) and
2104 * with the IPX LSAP as the DSAP in the LLC
2105 * header;
2106 *
2107 * Ethernet_SNAP frames, which are 802.3
2108 * frames with an LLC header and a SNAP
2109 * header and with an OUI of 0x000000
2110 * (encapsulated Ethernet) and a protocol
2111 * ID of ETHERTYPE_IPX in the SNAP header.
2112 *
2113 * First, do the checks on LINUX_SLL_P_802_2
2114 * frames; generate the check for either
2115 * Ethernet_802.2 or Ethernet_SNAP frames, and
2116 * then put a check for LINUX_SLL_P_802_2 frames
2117 * before it.
2118 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002119 b0 = gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
2120 b1 = gen_snap(cstate, 0x000000, ETHERTYPE_IPX);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002121 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07002122 b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002123 gen_and(b0, b1);
2124
2125 /*
2126 * Now check for 802.3 frames and OR that with
2127 * the previous test.
2128 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002129 b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_3);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002130 gen_or(b0, b1);
2131
2132 /*
2133 * Now add the check for Ethernet_II frames, and
2134 * do that before checking for the other frame
2135 * types.
2136 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002137 b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002138 gen_or(b0, b1);
2139 return b1;
2140
2141 case ETHERTYPE_ATALK:
2142 case ETHERTYPE_AARP:
2143 /*
2144 * EtherTalk (AppleTalk protocols on Ethernet link
2145 * layer) may use 802.2 encapsulation.
2146 */
2147
2148 /*
2149 * Check for 802.2 encapsulation (EtherTalk phase 2?);
2150 * we check for the 802.2 protocol type in the
2151 * "Ethernet type" field.
2152 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002153 b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002154
2155 /*
2156 * 802.2-encapsulated ETHERTYPE_ATALK packets are
2157 * SNAP packets with an organization code of
2158 * 0x080007 (Apple, for Appletalk) and a protocol
2159 * type of ETHERTYPE_ATALK (Appletalk).
2160 *
2161 * 802.2-encapsulated ETHERTYPE_AARP packets are
2162 * SNAP packets with an organization code of
2163 * 0x000000 (encapsulated Ethernet) and a protocol
2164 * type of ETHERTYPE_AARP (Appletalk ARP).
2165 */
2166 if (proto == ETHERTYPE_ATALK)
Elliott Hughes965a4b52017-05-15 10:37:39 -07002167 b1 = gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002168 else /* proto == ETHERTYPE_AARP */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002169 b1 = gen_snap(cstate, 0x000000, ETHERTYPE_AARP);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002170 gen_and(b0, b1);
2171
2172 /*
2173 * Check for Ethernet encapsulation (Ethertalk
2174 * phase 1?); we just check for the Ethernet
2175 * protocol type.
2176 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002177 b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002178
2179 gen_or(b0, b1);
2180 return b1;
2181
2182 default:
2183 if (proto <= ETHERMTU) {
2184 /*
2185 * This is an LLC SAP value, so the frames
2186 * that match would be 802.2 frames.
2187 * Check for the 802.2 protocol type
2188 * in the "Ethernet type" field, and
2189 * then check the DSAP.
2190 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002191 b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
2192 b1 = gen_cmp(cstate, OR_LINKHDR, cstate->off_linkpl.constant_part, BPF_B,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002193 (bpf_int32)proto);
2194 gen_and(b0, b1);
2195 return b1;
2196 } else {
2197 /*
2198 * This is an Ethernet type, so compare
2199 * the length/type field with it (if
2200 * the frame is an 802.2 frame, the length
2201 * field will be <= ETHERMTU, and, as
2202 * "proto" is > ETHERMTU, this test
2203 * will fail and the frame won't match,
2204 * which is what we want).
2205 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002206 return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002207 }
2208 }
2209}
2210
JP Abgrall511eca32014-02-12 13:46:45 -08002211static struct slist *
Elliott Hughes965a4b52017-05-15 10:37:39 -07002212gen_load_prism_llprefixlen(compiler_state_t *cstate)
JP Abgrall511eca32014-02-12 13:46:45 -08002213{
2214 struct slist *s1, *s2;
2215 struct slist *sjeq_avs_cookie;
2216 struct slist *sjcommon;
2217
2218 /*
2219 * This code is not compatible with the optimizer, as
2220 * we are generating jmp instructions within a normal
2221 * slist of instructions
2222 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002223 cstate->no_optimize = 1;
JP Abgrall511eca32014-02-12 13:46:45 -08002224
2225 /*
2226 * Generate code to load the length of the radio header into
2227 * the register assigned to hold that length, if one has been
2228 * assigned. (If one hasn't been assigned, no code we've
2229 * generated uses that prefix, so we don't need to generate any
2230 * code to load it.)
2231 *
2232 * Some Linux drivers use ARPHRD_IEEE80211_PRISM but sometimes
2233 * or always use the AVS header rather than the Prism header.
2234 * We load a 4-byte big-endian value at the beginning of the
2235 * raw packet data, and see whether, when masked with 0xFFFFF000,
2236 * it's equal to 0x80211000. If so, that indicates that it's
2237 * an AVS header (the masked-out bits are the version number).
2238 * Otherwise, it's a Prism header.
2239 *
2240 * XXX - the Prism header is also, in theory, variable-length,
2241 * but no known software generates headers that aren't 144
2242 * bytes long.
2243 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002244 if (cstate->off_linkhdr.reg != -1) {
JP Abgrall511eca32014-02-12 13:46:45 -08002245 /*
2246 * Load the cookie.
2247 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002248 s1 = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
JP Abgrall511eca32014-02-12 13:46:45 -08002249 s1->s.k = 0;
2250
2251 /*
2252 * AND it with 0xFFFFF000.
2253 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002254 s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
JP Abgrall511eca32014-02-12 13:46:45 -08002255 s2->s.k = 0xFFFFF000;
2256 sappend(s1, s2);
2257
2258 /*
2259 * Compare with 0x80211000.
2260 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002261 sjeq_avs_cookie = new_stmt(cstate, JMP(BPF_JEQ));
JP Abgrall511eca32014-02-12 13:46:45 -08002262 sjeq_avs_cookie->s.k = 0x80211000;
2263 sappend(s1, sjeq_avs_cookie);
2264
2265 /*
2266 * If it's AVS:
2267 *
2268 * The 4 bytes at an offset of 4 from the beginning of
2269 * the AVS header are the length of the AVS header.
2270 * That field is big-endian.
2271 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002272 s2 = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
JP Abgrall511eca32014-02-12 13:46:45 -08002273 s2->s.k = 4;
2274 sappend(s1, s2);
2275 sjeq_avs_cookie->s.jt = s2;
2276
2277 /*
2278 * Now jump to the code to allocate a register
2279 * into which to save the header length and
2280 * store the length there. (The "jump always"
2281 * instruction needs to have the k field set;
2282 * it's added to the PC, so, as we're jumping
2283 * over a single instruction, it should be 1.)
2284 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002285 sjcommon = new_stmt(cstate, JMP(BPF_JA));
JP Abgrall511eca32014-02-12 13:46:45 -08002286 sjcommon->s.k = 1;
2287 sappend(s1, sjcommon);
2288
2289 /*
2290 * Now for the code that handles the Prism header.
2291 * Just load the length of the Prism header (144)
2292 * into the A register. Have the test for an AVS
2293 * header branch here if we don't have an AVS header.
2294 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002295 s2 = new_stmt(cstate, BPF_LD|BPF_W|BPF_IMM);
JP Abgrall511eca32014-02-12 13:46:45 -08002296 s2->s.k = 144;
2297 sappend(s1, s2);
2298 sjeq_avs_cookie->s.jf = s2;
2299
2300 /*
2301 * Now allocate a register to hold that value and store
2302 * it. The code for the AVS header will jump here after
2303 * loading the length of the AVS header.
2304 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002305 s2 = new_stmt(cstate, BPF_ST);
2306 s2->s.k = cstate->off_linkhdr.reg;
JP Abgrall511eca32014-02-12 13:46:45 -08002307 sappend(s1, s2);
2308 sjcommon->s.jf = s2;
2309
2310 /*
2311 * Now move it into the X register.
2312 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002313 s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
JP Abgrall511eca32014-02-12 13:46:45 -08002314 sappend(s1, s2);
2315
2316 return (s1);
2317 } else
2318 return (NULL);
2319}
2320
2321static struct slist *
Elliott Hughes965a4b52017-05-15 10:37:39 -07002322gen_load_avs_llprefixlen(compiler_state_t *cstate)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002323{
2324 struct slist *s1, *s2;
2325
2326 /*
JP Abgrall511eca32014-02-12 13:46:45 -08002327 * Generate code to load the length of the AVS header into
2328 * the register assigned to hold that length, if one has been
2329 * assigned. (If one hasn't been assigned, no code we've
2330 * generated uses that prefix, so we don't need to generate any
2331 * code to load it.)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002332 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002333 if (cstate->off_linkhdr.reg != -1) {
JP Abgrall511eca32014-02-12 13:46:45 -08002334 /*
2335 * The 4 bytes at an offset of 4 from the beginning of
2336 * the AVS header are the length of the AVS header.
2337 * That field is big-endian.
2338 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002339 s1 = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
JP Abgrall511eca32014-02-12 13:46:45 -08002340 s1->s.k = 4;
2341
2342 /*
2343 * Now allocate a register to hold that value and store
2344 * it.
2345 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002346 s2 = new_stmt(cstate, BPF_ST);
2347 s2->s.k = cstate->off_linkhdr.reg;
JP Abgrall511eca32014-02-12 13:46:45 -08002348 sappend(s1, s2);
2349
2350 /*
2351 * Now move it into the X register.
2352 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002353 s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
JP Abgrall511eca32014-02-12 13:46:45 -08002354 sappend(s1, s2);
2355
2356 return (s1);
2357 } else
2358 return (NULL);
2359}
2360
2361static struct slist *
Elliott Hughes965a4b52017-05-15 10:37:39 -07002362gen_load_radiotap_llprefixlen(compiler_state_t *cstate)
JP Abgrall511eca32014-02-12 13:46:45 -08002363{
2364 struct slist *s1, *s2;
2365
2366 /*
2367 * Generate code to load the length of the radiotap header into
2368 * the register assigned to hold that length, if one has been
2369 * assigned. (If one hasn't been assigned, no code we've
2370 * generated uses that prefix, so we don't need to generate any
2371 * code to load it.)
2372 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002373 if (cstate->off_linkhdr.reg != -1) {
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002374 /*
2375 * The 2 bytes at offsets of 2 and 3 from the beginning
2376 * of the radiotap header are the length of the radiotap
2377 * header; unfortunately, it's little-endian, so we have
2378 * to load it a byte at a time and construct the value.
2379 */
2380
2381 /*
2382 * Load the high-order byte, at an offset of 3, shift it
2383 * left a byte, and put the result in the X register.
2384 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002385 s1 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002386 s1->s.k = 3;
Elliott Hughes965a4b52017-05-15 10:37:39 -07002387 s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002388 sappend(s1, s2);
2389 s2->s.k = 8;
Elliott Hughes965a4b52017-05-15 10:37:39 -07002390 s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002391 sappend(s1, s2);
2392
2393 /*
2394 * Load the next byte, at an offset of 2, and OR the
2395 * value from the X register into it.
2396 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002397 s2 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002398 sappend(s1, s2);
2399 s2->s.k = 2;
Elliott Hughes965a4b52017-05-15 10:37:39 -07002400 s2 = new_stmt(cstate, BPF_ALU|BPF_OR|BPF_X);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002401 sappend(s1, s2);
2402
2403 /*
2404 * Now allocate a register to hold that value and store
2405 * it.
2406 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002407 s2 = new_stmt(cstate, BPF_ST);
2408 s2->s.k = cstate->off_linkhdr.reg;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002409 sappend(s1, s2);
2410
2411 /*
2412 * Now move it into the X register.
2413 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002414 s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002415 sappend(s1, s2);
2416
JP Abgrall511eca32014-02-12 13:46:45 -08002417 return (s1);
2418 } else
2419 return (NULL);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002420}
2421
Elliott Hughesd8845d72015-10-19 18:07:04 -07002422/*
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002423 * At the moment we treat PPI as normal Radiotap encoded
2424 * packets. The difference is in the function that generates
2425 * the code at the beginning to compute the header length.
2426 * Since this code generator of PPI supports bare 802.11
2427 * encapsulation only (i.e. the encapsulated DLT should be
JP Abgrall511eca32014-02-12 13:46:45 -08002428 * DLT_IEEE802_11) we generate code to check for this too;
2429 * that's done in finish_parse().
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002430 */
JP Abgrall511eca32014-02-12 13:46:45 -08002431static struct slist *
Elliott Hughes965a4b52017-05-15 10:37:39 -07002432gen_load_ppi_llprefixlen(compiler_state_t *cstate)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002433{
2434 struct slist *s1, *s2;
Elliott Hughesd8845d72015-10-19 18:07:04 -07002435
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002436 /*
JP Abgrall511eca32014-02-12 13:46:45 -08002437 * Generate code to load the length of the radiotap header
2438 * into the register assigned to hold that length, if one has
2439 * been assigned.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002440 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002441 if (cstate->off_linkhdr.reg != -1) {
JP Abgrall511eca32014-02-12 13:46:45 -08002442 /*
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002443 * The 2 bytes at offsets of 2 and 3 from the beginning
2444 * of the radiotap header are the length of the radiotap
2445 * header; unfortunately, it's little-endian, so we have
2446 * to load it a byte at a time and construct the value.
2447 */
2448
2449 /*
2450 * Load the high-order byte, at an offset of 3, shift it
2451 * left a byte, and put the result in the X register.
2452 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002453 s1 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002454 s1->s.k = 3;
Elliott Hughes965a4b52017-05-15 10:37:39 -07002455 s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002456 sappend(s1, s2);
2457 s2->s.k = 8;
Elliott Hughes965a4b52017-05-15 10:37:39 -07002458 s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002459 sappend(s1, s2);
2460
2461 /*
2462 * Load the next byte, at an offset of 2, and OR the
2463 * value from the X register into it.
2464 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002465 s2 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002466 sappend(s1, s2);
2467 s2->s.k = 2;
Elliott Hughes965a4b52017-05-15 10:37:39 -07002468 s2 = new_stmt(cstate, BPF_ALU|BPF_OR|BPF_X);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002469 sappend(s1, s2);
2470
2471 /*
2472 * Now allocate a register to hold that value and store
2473 * it.
2474 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002475 s2 = new_stmt(cstate, BPF_ST);
2476 s2->s.k = cstate->off_linkhdr.reg;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002477 sappend(s1, s2);
2478
2479 /*
2480 * Now move it into the X register.
2481 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002482 s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002483 sappend(s1, s2);
2484
JP Abgrall511eca32014-02-12 13:46:45 -08002485 return (s1);
2486 } else
2487 return (NULL);
2488}
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002489
JP Abgrall511eca32014-02-12 13:46:45 -08002490/*
2491 * Load a value relative to the beginning of the link-layer header after the 802.11
2492 * header, i.e. LLC_SNAP.
2493 * The link-layer header doesn't necessarily begin at the beginning
2494 * of the packet data; there might be a variable-length prefix containing
2495 * radio information.
2496 */
2497static struct slist *
Elliott Hughes965a4b52017-05-15 10:37:39 -07002498gen_load_802_11_header_len(compiler_state_t *cstate, struct slist *s, struct slist *snext)
JP Abgrall511eca32014-02-12 13:46:45 -08002499{
2500 struct slist *s2;
2501 struct slist *sjset_data_frame_1;
2502 struct slist *sjset_data_frame_2;
2503 struct slist *sjset_qos;
Elliott Hughes965a4b52017-05-15 10:37:39 -07002504 struct slist *sjset_radiotap_flags_present;
2505 struct slist *sjset_radiotap_ext_present;
2506 struct slist *sjset_radiotap_tsft_present;
JP Abgrall511eca32014-02-12 13:46:45 -08002507 struct slist *sjset_tsft_datapad, *sjset_notsft_datapad;
2508 struct slist *s_roundup;
2509
Elliott Hughes965a4b52017-05-15 10:37:39 -07002510 if (cstate->off_linkpl.reg == -1) {
JP Abgrall511eca32014-02-12 13:46:45 -08002511 /*
2512 * No register has been assigned to the offset of
Elliott Hughesd8845d72015-10-19 18:07:04 -07002513 * the link-layer payload, which means nobody needs
JP Abgrall511eca32014-02-12 13:46:45 -08002514 * it; don't bother computing it - just return
2515 * what we already have.
2516 */
2517 return (s);
2518 }
2519
2520 /*
2521 * This code is not compatible with the optimizer, as
2522 * we are generating jmp instructions within a normal
2523 * slist of instructions
2524 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002525 cstate->no_optimize = 1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07002526
JP Abgrall511eca32014-02-12 13:46:45 -08002527 /*
2528 * If "s" is non-null, it has code to arrange that the X register
2529 * contains the length of the prefix preceding the link-layer
2530 * header.
2531 *
2532 * Otherwise, the length of the prefix preceding the link-layer
Elliott Hughesd8845d72015-10-19 18:07:04 -07002533 * header is "off_outermostlinkhdr.constant_part".
JP Abgrall511eca32014-02-12 13:46:45 -08002534 */
2535 if (s == NULL) {
2536 /*
2537 * There is no variable-length header preceding the
2538 * link-layer header.
2539 *
2540 * Load the length of the fixed-length prefix preceding
2541 * the link-layer header (if any) into the X register,
Elliott Hughes965a4b52017-05-15 10:37:39 -07002542 * and store it in the cstate->off_linkpl.reg register.
Elliott Hughesd8845d72015-10-19 18:07:04 -07002543 * That length is off_outermostlinkhdr.constant_part.
JP Abgrall511eca32014-02-12 13:46:45 -08002544 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002545 s = new_stmt(cstate, BPF_LDX|BPF_IMM);
2546 s->s.k = cstate->off_outermostlinkhdr.constant_part;
JP Abgrall511eca32014-02-12 13:46:45 -08002547 }
2548
2549 /*
2550 * The X register contains the offset of the beginning of the
2551 * link-layer header; add 24, which is the minimum length
2552 * of the MAC header for a data frame, to that, and store it
Elliott Hughes965a4b52017-05-15 10:37:39 -07002553 * in cstate->off_linkpl.reg, and then load the Frame Control field,
JP Abgrall511eca32014-02-12 13:46:45 -08002554 * which is at the offset in the X register, with an indexed load.
2555 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002556 s2 = new_stmt(cstate, BPF_MISC|BPF_TXA);
JP Abgrall511eca32014-02-12 13:46:45 -08002557 sappend(s, s2);
Elliott Hughes965a4b52017-05-15 10:37:39 -07002558 s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
JP Abgrall511eca32014-02-12 13:46:45 -08002559 s2->s.k = 24;
2560 sappend(s, s2);
Elliott Hughes965a4b52017-05-15 10:37:39 -07002561 s2 = new_stmt(cstate, BPF_ST);
2562 s2->s.k = cstate->off_linkpl.reg;
JP Abgrall511eca32014-02-12 13:46:45 -08002563 sappend(s, s2);
2564
Elliott Hughes965a4b52017-05-15 10:37:39 -07002565 s2 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
JP Abgrall511eca32014-02-12 13:46:45 -08002566 s2->s.k = 0;
2567 sappend(s, s2);
2568
2569 /*
2570 * Check the Frame Control field to see if this is a data frame;
2571 * a data frame has the 0x08 bit (b3) in that field set and the
2572 * 0x04 bit (b2) clear.
2573 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002574 sjset_data_frame_1 = new_stmt(cstate, JMP(BPF_JSET));
JP Abgrall511eca32014-02-12 13:46:45 -08002575 sjset_data_frame_1->s.k = 0x08;
2576 sappend(s, sjset_data_frame_1);
Elliott Hughesd8845d72015-10-19 18:07:04 -07002577
JP Abgrall511eca32014-02-12 13:46:45 -08002578 /*
2579 * If b3 is set, test b2, otherwise go to the first statement of
2580 * the rest of the program.
2581 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002582 sjset_data_frame_1->s.jt = sjset_data_frame_2 = new_stmt(cstate, JMP(BPF_JSET));
JP Abgrall511eca32014-02-12 13:46:45 -08002583 sjset_data_frame_2->s.k = 0x04;
2584 sappend(s, sjset_data_frame_2);
2585 sjset_data_frame_1->s.jf = snext;
2586
2587 /*
2588 * If b2 is not set, this is a data frame; test the QoS bit.
2589 * Otherwise, go to the first statement of the rest of the
2590 * program.
2591 */
2592 sjset_data_frame_2->s.jt = snext;
Elliott Hughes965a4b52017-05-15 10:37:39 -07002593 sjset_data_frame_2->s.jf = sjset_qos = new_stmt(cstate, JMP(BPF_JSET));
JP Abgrall511eca32014-02-12 13:46:45 -08002594 sjset_qos->s.k = 0x80; /* QoS bit */
2595 sappend(s, sjset_qos);
Elliott Hughesd8845d72015-10-19 18:07:04 -07002596
JP Abgrall511eca32014-02-12 13:46:45 -08002597 /*
Elliott Hughes965a4b52017-05-15 10:37:39 -07002598 * If it's set, add 2 to cstate->off_linkpl.reg, to skip the QoS
JP Abgrall511eca32014-02-12 13:46:45 -08002599 * field.
2600 * Otherwise, go to the first statement of the rest of the
2601 * program.
2602 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002603 sjset_qos->s.jt = s2 = new_stmt(cstate, BPF_LD|BPF_MEM);
2604 s2->s.k = cstate->off_linkpl.reg;
JP Abgrall511eca32014-02-12 13:46:45 -08002605 sappend(s, s2);
Elliott Hughes965a4b52017-05-15 10:37:39 -07002606 s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_IMM);
JP Abgrall511eca32014-02-12 13:46:45 -08002607 s2->s.k = 2;
2608 sappend(s, s2);
Elliott Hughes965a4b52017-05-15 10:37:39 -07002609 s2 = new_stmt(cstate, BPF_ST);
2610 s2->s.k = cstate->off_linkpl.reg;
JP Abgrall511eca32014-02-12 13:46:45 -08002611 sappend(s, s2);
2612
2613 /*
2614 * If we have a radiotap header, look at it to see whether
2615 * there's Atheros padding between the MAC-layer header
2616 * and the payload.
2617 *
2618 * Note: all of the fields in the radiotap header are
2619 * little-endian, so we byte-swap all of the values
2620 * we test against, as they will be loaded as big-endian
2621 * values.
Elliott Hughes965a4b52017-05-15 10:37:39 -07002622 *
2623 * XXX - in the general case, we would have to scan through
2624 * *all* the presence bits, if there's more than one word of
2625 * presence bits. That would require a loop, meaning that
2626 * we wouldn't be able to run the filter in the kernel.
2627 *
2628 * We assume here that the Atheros adapters that insert the
2629 * annoying padding don't have multiple antennae and therefore
2630 * do not generate radiotap headers with multiple presence words.
JP Abgrall511eca32014-02-12 13:46:45 -08002631 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002632 if (cstate->linktype == DLT_IEEE802_11_RADIO) {
JP Abgrall511eca32014-02-12 13:46:45 -08002633 /*
2634 * Is the IEEE80211_RADIOTAP_FLAGS bit (0x0000002) set
Elliott Hughes965a4b52017-05-15 10:37:39 -07002635 * in the first presence flag word?
JP Abgrall511eca32014-02-12 13:46:45 -08002636 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002637 sjset_qos->s.jf = s2 = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_W);
JP Abgrall511eca32014-02-12 13:46:45 -08002638 s2->s.k = 4;
2639 sappend(s, s2);
2640
Elliott Hughes965a4b52017-05-15 10:37:39 -07002641 sjset_radiotap_flags_present = new_stmt(cstate, JMP(BPF_JSET));
2642 sjset_radiotap_flags_present->s.k = SWAPLONG(0x00000002);
2643 sappend(s, sjset_radiotap_flags_present);
JP Abgrall511eca32014-02-12 13:46:45 -08002644
2645 /*
2646 * If not, skip all of this.
2647 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002648 sjset_radiotap_flags_present->s.jf = snext;
2649
2650 /*
2651 * Otherwise, is the "extension" bit set in that word?
2652 */
2653 sjset_radiotap_ext_present = new_stmt(cstate, JMP(BPF_JSET));
2654 sjset_radiotap_ext_present->s.k = SWAPLONG(0x80000000);
2655 sappend(s, sjset_radiotap_ext_present);
2656 sjset_radiotap_flags_present->s.jt = sjset_radiotap_ext_present;
2657
2658 /*
2659 * If so, skip all of this.
2660 */
2661 sjset_radiotap_ext_present->s.jt = snext;
JP Abgrall511eca32014-02-12 13:46:45 -08002662
2663 /*
2664 * Otherwise, is the IEEE80211_RADIOTAP_TSFT bit set?
2665 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002666 sjset_radiotap_tsft_present = new_stmt(cstate, JMP(BPF_JSET));
2667 sjset_radiotap_tsft_present->s.k = SWAPLONG(0x00000001);
2668 sappend(s, sjset_radiotap_tsft_present);
2669 sjset_radiotap_ext_present->s.jf = sjset_radiotap_tsft_present;
JP Abgrall511eca32014-02-12 13:46:45 -08002670
2671 /*
2672 * If IEEE80211_RADIOTAP_TSFT is set, the flags field is
2673 * at an offset of 16 from the beginning of the raw packet
2674 * data (8 bytes for the radiotap header and 8 bytes for
2675 * the TSFT field).
2676 *
2677 * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
2678 * is set.
2679 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002680 s2 = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
JP Abgrall511eca32014-02-12 13:46:45 -08002681 s2->s.k = 16;
2682 sappend(s, s2);
Elliott Hughes965a4b52017-05-15 10:37:39 -07002683 sjset_radiotap_tsft_present->s.jt = s2;
JP Abgrall511eca32014-02-12 13:46:45 -08002684
Elliott Hughes965a4b52017-05-15 10:37:39 -07002685 sjset_tsft_datapad = new_stmt(cstate, JMP(BPF_JSET));
JP Abgrall511eca32014-02-12 13:46:45 -08002686 sjset_tsft_datapad->s.k = 0x20;
2687 sappend(s, sjset_tsft_datapad);
2688
2689 /*
2690 * If IEEE80211_RADIOTAP_TSFT is not set, the flags field is
2691 * at an offset of 8 from the beginning of the raw packet
2692 * data (8 bytes for the radiotap header).
2693 *
2694 * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
2695 * is set.
2696 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002697 s2 = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
JP Abgrall511eca32014-02-12 13:46:45 -08002698 s2->s.k = 8;
2699 sappend(s, s2);
Elliott Hughes965a4b52017-05-15 10:37:39 -07002700 sjset_radiotap_tsft_present->s.jf = s2;
JP Abgrall511eca32014-02-12 13:46:45 -08002701
Elliott Hughes965a4b52017-05-15 10:37:39 -07002702 sjset_notsft_datapad = new_stmt(cstate, JMP(BPF_JSET));
JP Abgrall511eca32014-02-12 13:46:45 -08002703 sjset_notsft_datapad->s.k = 0x20;
2704 sappend(s, sjset_notsft_datapad);
2705
2706 /*
2707 * In either case, if IEEE80211_RADIOTAP_F_DATAPAD is
2708 * set, round the length of the 802.11 header to
2709 * a multiple of 4. Do that by adding 3 and then
2710 * dividing by and multiplying by 4, which we do by
2711 * ANDing with ~3.
2712 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002713 s_roundup = new_stmt(cstate, BPF_LD|BPF_MEM);
2714 s_roundup->s.k = cstate->off_linkpl.reg;
JP Abgrall511eca32014-02-12 13:46:45 -08002715 sappend(s, s_roundup);
Elliott Hughes965a4b52017-05-15 10:37:39 -07002716 s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_IMM);
JP Abgrall511eca32014-02-12 13:46:45 -08002717 s2->s.k = 3;
2718 sappend(s, s2);
Elliott Hughes965a4b52017-05-15 10:37:39 -07002719 s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_IMM);
JP Abgrall511eca32014-02-12 13:46:45 -08002720 s2->s.k = ~3;
2721 sappend(s, s2);
Elliott Hughes965a4b52017-05-15 10:37:39 -07002722 s2 = new_stmt(cstate, BPF_ST);
2723 s2->s.k = cstate->off_linkpl.reg;
JP Abgrall511eca32014-02-12 13:46:45 -08002724 sappend(s, s2);
2725
2726 sjset_tsft_datapad->s.jt = s_roundup;
2727 sjset_tsft_datapad->s.jf = snext;
2728 sjset_notsft_datapad->s.jt = s_roundup;
2729 sjset_notsft_datapad->s.jf = snext;
2730 } else
2731 sjset_qos->s.jf = snext;
2732
2733 return s;
2734}
2735
2736static void
Elliott Hughes965a4b52017-05-15 10:37:39 -07002737insert_compute_vloffsets(compiler_state_t *cstate, struct block *b)
JP Abgrall511eca32014-02-12 13:46:45 -08002738{
2739 struct slist *s;
2740
Elliott Hughesd8845d72015-10-19 18:07:04 -07002741 /* There is an implicit dependency between the link
2742 * payload and link header since the payload computation
2743 * includes the variable part of the header. Therefore,
2744 * if nobody else has allocated a register for the link
2745 * header and we need it, do it now. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002746 if (cstate->off_linkpl.reg != -1 && cstate->off_linkhdr.is_variable &&
2747 cstate->off_linkhdr.reg == -1)
2748 cstate->off_linkhdr.reg = alloc_reg(cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -07002749
JP Abgrall511eca32014-02-12 13:46:45 -08002750 /*
2751 * For link-layer types that have a variable-length header
2752 * preceding the link-layer header, generate code to load
2753 * the offset of the link-layer header into the register
2754 * assigned to that offset, if any.
Elliott Hughesd8845d72015-10-19 18:07:04 -07002755 *
2756 * XXX - this, and the next switch statement, won't handle
2757 * encapsulation of 802.11 or 802.11+radio information in
2758 * some other protocol stack. That's significantly more
2759 * complicated.
JP Abgrall511eca32014-02-12 13:46:45 -08002760 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002761 switch (cstate->outermostlinktype) {
JP Abgrall511eca32014-02-12 13:46:45 -08002762
2763 case DLT_PRISM_HEADER:
Elliott Hughes965a4b52017-05-15 10:37:39 -07002764 s = gen_load_prism_llprefixlen(cstate);
JP Abgrall511eca32014-02-12 13:46:45 -08002765 break;
2766
2767 case DLT_IEEE802_11_RADIO_AVS:
Elliott Hughes965a4b52017-05-15 10:37:39 -07002768 s = gen_load_avs_llprefixlen(cstate);
JP Abgrall511eca32014-02-12 13:46:45 -08002769 break;
2770
2771 case DLT_IEEE802_11_RADIO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07002772 s = gen_load_radiotap_llprefixlen(cstate);
JP Abgrall511eca32014-02-12 13:46:45 -08002773 break;
2774
2775 case DLT_PPI:
Elliott Hughes965a4b52017-05-15 10:37:39 -07002776 s = gen_load_ppi_llprefixlen(cstate);
JP Abgrall511eca32014-02-12 13:46:45 -08002777 break;
2778
2779 default:
2780 s = NULL;
2781 break;
2782 }
2783
2784 /*
2785 * For link-layer types that have a variable-length link-layer
Elliott Hughesd8845d72015-10-19 18:07:04 -07002786 * header, generate code to load the offset of the link-layer
JP Abgrall511eca32014-02-12 13:46:45 -08002787 * payload into the register assigned to that offset, if any.
2788 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002789 switch (cstate->outermostlinktype) {
JP Abgrall511eca32014-02-12 13:46:45 -08002790
2791 case DLT_IEEE802_11:
2792 case DLT_PRISM_HEADER:
2793 case DLT_IEEE802_11_RADIO_AVS:
2794 case DLT_IEEE802_11_RADIO:
2795 case DLT_PPI:
Elliott Hughes965a4b52017-05-15 10:37:39 -07002796 s = gen_load_802_11_header_len(cstate, s, b->stmts);
JP Abgrall511eca32014-02-12 13:46:45 -08002797 break;
2798 }
2799
2800 /*
2801 * If we have any offset-loading code, append all the
2802 * existing statements in the block to those statements,
2803 * and make the resulting list the list of statements
2804 * for the block.
2805 */
2806 if (s != NULL) {
2807 sappend(s, b->stmts);
2808 b->stmts = s;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002809 }
2810}
JP Abgrall511eca32014-02-12 13:46:45 -08002811
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002812static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07002813gen_ppi_dlt_check(compiler_state_t *cstate)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002814{
2815 struct slist *s_load_dlt;
2816 struct block *b;
2817
Elliott Hughes965a4b52017-05-15 10:37:39 -07002818 if (cstate->linktype == DLT_PPI)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002819 {
2820 /* Create the statements that check for the DLT
2821 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002822 s_load_dlt = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002823 s_load_dlt->s.k = 4;
2824
Elliott Hughes965a4b52017-05-15 10:37:39 -07002825 b = new_block(cstate, JMP(BPF_JEQ));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002826
2827 b->stmts = s_load_dlt;
2828 b->s.k = SWAPLONG(DLT_IEEE802_11);
2829 }
2830 else
2831 {
2832 b = NULL;
2833 }
2834
2835 return b;
2836}
2837
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002838/*
Elliott Hughesd8845d72015-10-19 18:07:04 -07002839 * Take an absolute offset, and:
2840 *
2841 * if it has no variable part, return NULL;
2842 *
2843 * if it has a variable part, generate code to load the register
2844 * containing that variable part into the X register, returning
2845 * a pointer to that code - if no register for that offset has
2846 * been allocated, allocate it first.
2847 *
2848 * (The code to set that register will be generated later, but will
2849 * be placed earlier in the code sequence.)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002850 */
2851static struct slist *
Elliott Hughes965a4b52017-05-15 10:37:39 -07002852gen_abs_offset_varpart(compiler_state_t *cstate, bpf_abs_offset *off)
JP Abgrall511eca32014-02-12 13:46:45 -08002853{
2854 struct slist *s;
2855
Elliott Hughesd8845d72015-10-19 18:07:04 -07002856 if (off->is_variable) {
2857 if (off->reg == -1) {
JP Abgrall511eca32014-02-12 13:46:45 -08002858 /*
Elliott Hughesd8845d72015-10-19 18:07:04 -07002859 * We haven't yet assigned a register for the
2860 * variable part of the offset of the link-layer
2861 * header; allocate one.
JP Abgrall511eca32014-02-12 13:46:45 -08002862 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002863 off->reg = alloc_reg(cstate);
JP Abgrall511eca32014-02-12 13:46:45 -08002864 }
2865
2866 /*
Elliott Hughesd8845d72015-10-19 18:07:04 -07002867 * Load the register containing the variable part of the
2868 * offset of the link-layer header into the X register.
JP Abgrall511eca32014-02-12 13:46:45 -08002869 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002870 s = new_stmt(cstate, BPF_LDX|BPF_MEM);
Elliott Hughesd8845d72015-10-19 18:07:04 -07002871 s->s.k = off->reg;
JP Abgrall511eca32014-02-12 13:46:45 -08002872 return s;
2873 } else {
2874 /*
Elliott Hughesd8845d72015-10-19 18:07:04 -07002875 * That offset isn't variable, there's no variable part,
2876 * so we don't need to generate any code.
JP Abgrall511eca32014-02-12 13:46:45 -08002877 */
2878 return NULL;
2879 }
2880}
2881
2882/*
2883 * Map an Ethernet type to the equivalent PPP type.
2884 */
2885static int
2886ethertype_to_ppptype(proto)
2887 int proto;
2888{
2889 switch (proto) {
2890
2891 case ETHERTYPE_IP:
2892 proto = PPP_IP;
2893 break;
2894
2895 case ETHERTYPE_IPV6:
2896 proto = PPP_IPV6;
2897 break;
2898
2899 case ETHERTYPE_DN:
2900 proto = PPP_DECNET;
2901 break;
2902
2903 case ETHERTYPE_ATALK:
2904 proto = PPP_APPLE;
2905 break;
2906
2907 case ETHERTYPE_NS:
2908 proto = PPP_NS;
2909 break;
2910
2911 case LLCSAP_ISONS:
2912 proto = PPP_OSI;
2913 break;
2914
2915 case LLCSAP_8021D:
2916 /*
2917 * I'm assuming the "Bridging PDU"s that go
2918 * over PPP are Spanning Tree Protocol
2919 * Bridging PDUs.
2920 */
2921 proto = PPP_BRPDU;
2922 break;
2923
2924 case LLCSAP_IPX:
2925 proto = PPP_IPX;
2926 break;
2927 }
2928 return (proto);
2929}
2930
2931/*
Elliott Hughesd8845d72015-10-19 18:07:04 -07002932 * Generate any tests that, for encapsulation of a link-layer packet
2933 * inside another protocol stack, need to be done to check for those
2934 * link-layer packets (and that haven't already been done by a check
2935 * for that encapsulation).
2936 */
2937static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07002938gen_prevlinkhdr_check(compiler_state_t *cstate)
Elliott Hughesd8845d72015-10-19 18:07:04 -07002939{
2940 struct block *b0;
2941
Elliott Hughes965a4b52017-05-15 10:37:39 -07002942 if (cstate->is_geneve)
2943 return gen_geneve_ll_check(cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -07002944
Elliott Hughes965a4b52017-05-15 10:37:39 -07002945 switch (cstate->prevlinktype) {
Elliott Hughesd8845d72015-10-19 18:07:04 -07002946
2947 case DLT_SUNATM:
2948 /*
2949 * This is LANE-encapsulated Ethernet; check that the LANE
2950 * packet doesn't begin with an LE Control marker, i.e.
2951 * that it's data, not a control message.
2952 *
2953 * (We've already generated a test for LANE.)
2954 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002955 b0 = gen_cmp(cstate, OR_PREVLINKHDR, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
Elliott Hughesd8845d72015-10-19 18:07:04 -07002956 gen_not(b0);
2957 return b0;
2958
2959 default:
2960 /*
2961 * No such tests are necessary.
2962 */
2963 return NULL;
2964 }
2965 /*NOTREACHED*/
2966}
2967
2968/*
Elliott Hughes965a4b52017-05-15 10:37:39 -07002969 * The three different values we should check for when checking for an
2970 * IPv6 packet with DLT_NULL.
2971 */
2972#define BSD_AFNUM_INET6_BSD 24 /* NetBSD, OpenBSD, BSD/OS, Npcap */
2973#define BSD_AFNUM_INET6_FREEBSD 28 /* FreeBSD */
2974#define BSD_AFNUM_INET6_DARWIN 30 /* OS X, iOS, other Darwin-based OSes */
2975
2976/*
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002977 * Generate code to match a particular packet type by matching the
2978 * link-layer type field or fields in the 802.2 LLC header.
2979 *
2980 * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
2981 * value, if <= ETHERMTU.
2982 */
2983static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07002984gen_linktype(compiler_state_t *cstate, int proto)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002985{
2986 struct block *b0, *b1, *b2;
Elliott Hughesd8845d72015-10-19 18:07:04 -07002987 const char *description;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002988
2989 /* are we checking MPLS-encapsulated packets? */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002990 if (cstate->label_stack_depth > 0) {
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002991 switch (proto) {
2992 case ETHERTYPE_IP:
2993 case PPP_IP:
JP Abgrall511eca32014-02-12 13:46:45 -08002994 /* FIXME add other L3 proto IDs */
Elliott Hughes965a4b52017-05-15 10:37:39 -07002995 return gen_mpls_linktype(cstate, Q_IP);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08002996
2997 case ETHERTYPE_IPV6:
2998 case PPP_IPV6:
JP Abgrall511eca32014-02-12 13:46:45 -08002999 /* FIXME add other L3 proto IDs */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003000 return gen_mpls_linktype(cstate, Q_IPV6);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003001
3002 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003003 bpf_error(cstate, "unsupported protocol over mpls");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003004 /* NOTREACHED */
3005 }
3006 }
3007
Elliott Hughes965a4b52017-05-15 10:37:39 -07003008 switch (cstate->linktype) {
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003009
3010 case DLT_EN10MB:
JP Abgrall511eca32014-02-12 13:46:45 -08003011 case DLT_NETANALYZER:
3012 case DLT_NETANALYZER_TRANSPARENT:
Elliott Hughesd8845d72015-10-19 18:07:04 -07003013 /* Geneve has an EtherType regardless of whether there is an
3014 * L2 header. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003015 if (!cstate->is_geneve)
3016 b0 = gen_prevlinkhdr_check(cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003017 else
3018 b0 = NULL;
3019
Elliott Hughes965a4b52017-05-15 10:37:39 -07003020 b1 = gen_ether_linktype(cstate, proto);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003021 if (b0 != NULL)
3022 gen_and(b0, b1);
3023 return b1;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003024 /*NOTREACHED*/
3025 break;
3026
3027 case DLT_C_HDLC:
3028 switch (proto) {
3029
3030 case LLCSAP_ISONS:
3031 proto = (proto << 8 | LLCSAP_ISONS);
3032 /* fall through */
3033
3034 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003035 return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003036 /*NOTREACHED*/
3037 break;
3038 }
3039 break;
3040
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003041 case DLT_IEEE802_11:
JP Abgrall511eca32014-02-12 13:46:45 -08003042 case DLT_PRISM_HEADER:
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003043 case DLT_IEEE802_11_RADIO_AVS:
3044 case DLT_IEEE802_11_RADIO:
JP Abgrall511eca32014-02-12 13:46:45 -08003045 case DLT_PPI:
3046 /*
3047 * Check that we have a data frame.
3048 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003049 b0 = gen_check_802_11_data_frame(cstate);
JP Abgrall511eca32014-02-12 13:46:45 -08003050
3051 /*
3052 * Now check for the specified link-layer type.
3053 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003054 b1 = gen_llc_linktype(cstate, proto);
JP Abgrall511eca32014-02-12 13:46:45 -08003055 gen_and(b0, b1);
3056 return b1;
3057 /*NOTREACHED*/
3058 break;
3059
3060 case DLT_FDDI:
3061 /*
Elliott Hughesd8845d72015-10-19 18:07:04 -07003062 * XXX - check for LLC frames.
JP Abgrall511eca32014-02-12 13:46:45 -08003063 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003064 return gen_llc_linktype(cstate, proto);
JP Abgrall511eca32014-02-12 13:46:45 -08003065 /*NOTREACHED*/
3066 break;
3067
3068 case DLT_IEEE802:
3069 /*
3070 * XXX - check for LLC PDUs, as per IEEE 802.5.
3071 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003072 return gen_llc_linktype(cstate, proto);
JP Abgrall511eca32014-02-12 13:46:45 -08003073 /*NOTREACHED*/
3074 break;
3075
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003076 case DLT_ATM_RFC1483:
3077 case DLT_ATM_CLIP:
3078 case DLT_IP_OVER_FC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003079 return gen_llc_linktype(cstate, proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003080 /*NOTREACHED*/
3081 break;
3082
3083 case DLT_SUNATM:
3084 /*
Elliott Hughesd8845d72015-10-19 18:07:04 -07003085 * Check for an LLC-encapsulated version of this protocol;
3086 * if we were checking for LANE, linktype would no longer
3087 * be DLT_SUNATM.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003088 *
Elliott Hughesd8845d72015-10-19 18:07:04 -07003089 * Check for LLC encapsulation and then check the protocol.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003090 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003091 b0 = gen_atmfield_code(cstate, A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
3092 b1 = gen_llc_linktype(cstate, proto);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003093 gen_and(b0, b1);
3094 return b1;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003095 /*NOTREACHED*/
3096 break;
3097
3098 case DLT_LINUX_SLL:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003099 return gen_linux_sll_linktype(cstate, proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003100 /*NOTREACHED*/
3101 break;
3102
3103 case DLT_SLIP:
3104 case DLT_SLIP_BSDOS:
3105 case DLT_RAW:
3106 /*
3107 * These types don't provide any type field; packets
3108 * are always IPv4 or IPv6.
3109 *
3110 * XXX - for IPv4, check for a version number of 4, and,
3111 * for IPv6, check for a version number of 6?
3112 */
3113 switch (proto) {
3114
3115 case ETHERTYPE_IP:
3116 /* Check for a version number of 4. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003117 return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, 0x40, 0xF0);
JP Abgrall511eca32014-02-12 13:46:45 -08003118
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003119 case ETHERTYPE_IPV6:
3120 /* Check for a version number of 6. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003121 return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, 0x60, 0xF0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003122
3123 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003124 return gen_false(cstate); /* always false */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003125 }
3126 /*NOTREACHED*/
3127 break;
3128
JP Abgrall511eca32014-02-12 13:46:45 -08003129 case DLT_IPV4:
3130 /*
3131 * Raw IPv4, so no type field.
3132 */
3133 if (proto == ETHERTYPE_IP)
Elliott Hughes965a4b52017-05-15 10:37:39 -07003134 return gen_true(cstate); /* always true */
JP Abgrall511eca32014-02-12 13:46:45 -08003135
3136 /* Checking for something other than IPv4; always false */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003137 return gen_false(cstate);
JP Abgrall511eca32014-02-12 13:46:45 -08003138 /*NOTREACHED*/
3139 break;
3140
3141 case DLT_IPV6:
3142 /*
3143 * Raw IPv6, so no type field.
3144 */
3145 if (proto == ETHERTYPE_IPV6)
Elliott Hughes965a4b52017-05-15 10:37:39 -07003146 return gen_true(cstate); /* always true */
JP Abgrall511eca32014-02-12 13:46:45 -08003147
3148 /* Checking for something other than IPv6; always false */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003149 return gen_false(cstate);
JP Abgrall511eca32014-02-12 13:46:45 -08003150 /*NOTREACHED*/
3151 break;
3152
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003153 case DLT_PPP:
3154 case DLT_PPP_PPPD:
3155 case DLT_PPP_SERIAL:
3156 case DLT_PPP_ETHER:
3157 /*
3158 * We use Ethernet protocol types inside libpcap;
3159 * map them to the corresponding PPP protocol types.
3160 */
JP Abgrall511eca32014-02-12 13:46:45 -08003161 proto = ethertype_to_ppptype(proto);
Elliott Hughes965a4b52017-05-15 10:37:39 -07003162 return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
JP Abgrall511eca32014-02-12 13:46:45 -08003163 /*NOTREACHED*/
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003164 break;
3165
3166 case DLT_PPP_BSDOS:
3167 /*
3168 * We use Ethernet protocol types inside libpcap;
3169 * map them to the corresponding PPP protocol types.
3170 */
3171 switch (proto) {
3172
3173 case ETHERTYPE_IP:
JP Abgrall511eca32014-02-12 13:46:45 -08003174 /*
3175 * Also check for Van Jacobson-compressed IP.
3176 * XXX - do this for other forms of PPP?
3177 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003178 b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, PPP_IP);
3179 b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, PPP_VJC);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003180 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07003181 b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, PPP_VJNC);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003182 gen_or(b1, b0);
3183 return b0;
3184
JP Abgrall511eca32014-02-12 13:46:45 -08003185 default:
3186 proto = ethertype_to_ppptype(proto);
Elliott Hughes965a4b52017-05-15 10:37:39 -07003187 return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H,
JP Abgrall511eca32014-02-12 13:46:45 -08003188 (bpf_int32)proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003189 }
JP Abgrall511eca32014-02-12 13:46:45 -08003190 /*NOTREACHED*/
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003191 break;
3192
3193 case DLT_NULL:
3194 case DLT_LOOP:
3195 case DLT_ENC:
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003196 switch (proto) {
3197
3198 case ETHERTYPE_IP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003199 return (gen_loopback_linktype(cstate, AF_INET));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003200
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003201 case ETHERTYPE_IPV6:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003202 /*
3203 * AF_ values may, unfortunately, be platform-
3204 * dependent; AF_INET isn't, because everybody
3205 * used 4.2BSD's value, but AF_INET6 is, because
3206 * 4.2BSD didn't have a value for it (given that
3207 * IPv6 didn't exist back in the early 1980's),
3208 * and they all picked their own values.
3209 *
3210 * This means that, if we're reading from a
3211 * savefile, we need to check for all the
3212 * possible values.
3213 *
3214 * If we're doing a live capture, we only need
3215 * to check for this platform's value; however,
3216 * Npcap uses 24, which isn't Windows's AF_INET6
3217 * value. (Given the multiple different values,
3218 * programs that read pcap files shouldn't be
3219 * checking for their platform's AF_INET6 value
3220 * anyway, they should check for all of the
3221 * possible values. and they might as well do
3222 * that even for live captures.)
3223 */
3224 if (cstate->bpf_pcap->rfile != NULL) {
3225 /*
3226 * Savefile - check for all three
3227 * possible IPv6 values.
3228 */
3229 b0 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_BSD);
3230 b1 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_FREEBSD);
3231 gen_or(b0, b1);
3232 b0 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_DARWIN);
3233 gen_or(b0, b1);
3234 return (b1);
3235 } else {
3236 /*
3237 * Live capture, so we only need to
3238 * check for the value used on this
3239 * platform.
3240 */
3241#ifdef _WIN32
3242 /*
3243 * Npcap doesn't use Windows's AF_INET6,
3244 * as that collides with AF_IPX on
3245 * some BSDs (both have the value 23).
3246 * Instead, it uses 24.
3247 */
3248 return (gen_loopback_linktype(cstate, 24));
3249#else /* _WIN32 */
3250#ifdef AF_INET6
3251 return (gen_loopback_linktype(cstate, AF_INET6));
3252#else /* AF_INET6 */
3253 /*
3254 * I guess this platform doesn't support
3255 * IPv6, so we just reject all packets.
3256 */
3257 return gen_false(cstate);
3258#endif /* AF_INET6 */
3259#endif /* _WIN32 */
3260 }
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003261
3262 default:
3263 /*
3264 * Not a type on which we support filtering.
3265 * XXX - support those that have AF_ values
3266 * #defined on this platform, at least?
3267 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003268 return gen_false(cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003269 }
3270
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003271#ifdef HAVE_NET_PFVAR_H
3272 case DLT_PFLOG:
3273 /*
3274 * af field is host byte order in contrast to the rest of
3275 * the packet.
3276 */
3277 if (proto == ETHERTYPE_IP)
Elliott Hughes965a4b52017-05-15 10:37:39 -07003278 return (gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, af),
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003279 BPF_B, (bpf_int32)AF_INET));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003280 else if (proto == ETHERTYPE_IPV6)
Elliott Hughes965a4b52017-05-15 10:37:39 -07003281 return (gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, af),
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003282 BPF_B, (bpf_int32)AF_INET6));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003283 else
Elliott Hughes965a4b52017-05-15 10:37:39 -07003284 return gen_false(cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003285 /*NOTREACHED*/
3286 break;
3287#endif /* HAVE_NET_PFVAR_H */
3288
3289 case DLT_ARCNET:
3290 case DLT_ARCNET_LINUX:
3291 /*
3292 * XXX should we check for first fragment if the protocol
3293 * uses PHDS?
3294 */
3295 switch (proto) {
3296
3297 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003298 return gen_false(cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003299
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003300 case ETHERTYPE_IPV6:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003301 return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003302 (bpf_int32)ARCTYPE_INET6));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003303
3304 case ETHERTYPE_IP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003305 b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003306 (bpf_int32)ARCTYPE_IP);
Elliott Hughes965a4b52017-05-15 10:37:39 -07003307 b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003308 (bpf_int32)ARCTYPE_IP_OLD);
3309 gen_or(b0, b1);
3310 return (b1);
3311
3312 case ETHERTYPE_ARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003313 b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003314 (bpf_int32)ARCTYPE_ARP);
Elliott Hughes965a4b52017-05-15 10:37:39 -07003315 b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003316 (bpf_int32)ARCTYPE_ARP_OLD);
3317 gen_or(b0, b1);
3318 return (b1);
3319
3320 case ETHERTYPE_REVARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003321 return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003322 (bpf_int32)ARCTYPE_REVARP));
3323
3324 case ETHERTYPE_ATALK:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003325 return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003326 (bpf_int32)ARCTYPE_ATALK));
3327 }
3328 /*NOTREACHED*/
3329 break;
3330
3331 case DLT_LTALK:
3332 switch (proto) {
3333 case ETHERTYPE_ATALK:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003334 return gen_true(cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003335 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003336 return gen_false(cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003337 }
3338 /*NOTREACHED*/
3339 break;
3340
3341 case DLT_FRELAY:
3342 /*
3343 * XXX - assumes a 2-byte Frame Relay header with
3344 * DLCI and flags. What if the address is longer?
3345 */
3346 switch (proto) {
3347
3348 case ETHERTYPE_IP:
3349 /*
3350 * Check for the special NLPID for IP.
3351 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003352 return gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0xcc);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003353
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003354 case ETHERTYPE_IPV6:
3355 /*
3356 * Check for the special NLPID for IPv6.
3357 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003358 return gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0x8e);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003359
3360 case LLCSAP_ISONS:
3361 /*
3362 * Check for several OSI protocols.
3363 *
3364 * Frame Relay packets typically have an OSI
3365 * NLPID at the beginning; we check for each
3366 * of them.
3367 *
3368 * What we check for is the NLPID and a frame
3369 * control field of UI, i.e. 0x03 followed
3370 * by the NLPID.
3371 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003372 b0 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO8473_CLNP);
3373 b1 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO9542_ESIS);
3374 b2 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO10589_ISIS);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003375 gen_or(b1, b2);
3376 gen_or(b0, b2);
3377 return b2;
3378
3379 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003380 return gen_false(cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003381 }
3382 /*NOTREACHED*/
3383 break;
3384
JP Abgrall511eca32014-02-12 13:46:45 -08003385 case DLT_MFR:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003386 bpf_error(cstate, "Multi-link Frame Relay link-layer type filtering not implemented");
JP Abgrall511eca32014-02-12 13:46:45 -08003387
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003388 case DLT_JUNIPER_MFR:
3389 case DLT_JUNIPER_MLFR:
3390 case DLT_JUNIPER_MLPPP:
3391 case DLT_JUNIPER_ATM1:
3392 case DLT_JUNIPER_ATM2:
3393 case DLT_JUNIPER_PPPOE:
3394 case DLT_JUNIPER_PPPOE_ATM:
3395 case DLT_JUNIPER_GGSN:
3396 case DLT_JUNIPER_ES:
3397 case DLT_JUNIPER_MONITOR:
3398 case DLT_JUNIPER_SERVICES:
3399 case DLT_JUNIPER_ETHER:
3400 case DLT_JUNIPER_PPP:
3401 case DLT_JUNIPER_FRELAY:
3402 case DLT_JUNIPER_CHDLC:
3403 case DLT_JUNIPER_VP:
JP Abgrall511eca32014-02-12 13:46:45 -08003404 case DLT_JUNIPER_ST:
3405 case DLT_JUNIPER_ISM:
3406 case DLT_JUNIPER_VS:
3407 case DLT_JUNIPER_SRX_E2E:
3408 case DLT_JUNIPER_FIBRECHANNEL:
3409 case DLT_JUNIPER_ATM_CEMIC:
3410
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003411 /* just lets verify the magic number for now -
3412 * on ATM we may have up to 6 different encapsulations on the wire
3413 * and need a lot of heuristics to figure out that the payload
3414 * might be;
3415 *
3416 * FIXME encapsulation specific BPF_ filters
3417 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003418 return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003419
JP Abgrall511eca32014-02-12 13:46:45 -08003420 case DLT_BACNET_MS_TP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003421 return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_W, 0x55FF0000, 0xffff0000);
JP Abgrall511eca32014-02-12 13:46:45 -08003422
3423 case DLT_IPNET:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003424 return gen_ipnet_linktype(cstate, proto);
JP Abgrall511eca32014-02-12 13:46:45 -08003425
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003426 case DLT_LINUX_IRDA:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003427 bpf_error(cstate, "IrDA link-layer type filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003428
3429 case DLT_DOCSIS:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003430 bpf_error(cstate, "DOCSIS link-layer type filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003431
JP Abgrall511eca32014-02-12 13:46:45 -08003432 case DLT_MTP2:
3433 case DLT_MTP2_WITH_PHDR:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003434 bpf_error(cstate, "MTP2 link-layer type filtering not implemented");
JP Abgrall511eca32014-02-12 13:46:45 -08003435
3436 case DLT_ERF:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003437 bpf_error(cstate, "ERF link-layer type filtering not implemented");
JP Abgrall511eca32014-02-12 13:46:45 -08003438
3439 case DLT_PFSYNC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003440 bpf_error(cstate, "PFSYNC link-layer type filtering not implemented");
JP Abgrall511eca32014-02-12 13:46:45 -08003441
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003442 case DLT_LINUX_LAPD:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003443 bpf_error(cstate, "LAPD link-layer type filtering not implemented");
JP Abgrall511eca32014-02-12 13:46:45 -08003444
Elliott Hughes965a4b52017-05-15 10:37:39 -07003445 case DLT_USB_FREEBSD:
JP Abgrall511eca32014-02-12 13:46:45 -08003446 case DLT_USB_LINUX:
3447 case DLT_USB_LINUX_MMAPPED:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003448 case DLT_USBPCAP:
3449 bpf_error(cstate, "USB link-layer type filtering not implemented");
JP Abgrall511eca32014-02-12 13:46:45 -08003450
3451 case DLT_BLUETOOTH_HCI_H4:
3452 case DLT_BLUETOOTH_HCI_H4_WITH_PHDR:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003453 bpf_error(cstate, "Bluetooth link-layer type filtering not implemented");
JP Abgrall511eca32014-02-12 13:46:45 -08003454
3455 case DLT_CAN20B:
3456 case DLT_CAN_SOCKETCAN:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003457 bpf_error(cstate, "CAN link-layer type filtering not implemented");
JP Abgrall511eca32014-02-12 13:46:45 -08003458
3459 case DLT_IEEE802_15_4:
3460 case DLT_IEEE802_15_4_LINUX:
3461 case DLT_IEEE802_15_4_NONASK_PHY:
3462 case DLT_IEEE802_15_4_NOFCS:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003463 bpf_error(cstate, "IEEE 802.15.4 link-layer type filtering not implemented");
JP Abgrall511eca32014-02-12 13:46:45 -08003464
3465 case DLT_IEEE802_16_MAC_CPS_RADIO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003466 bpf_error(cstate, "IEEE 802.16 link-layer type filtering not implemented");
JP Abgrall511eca32014-02-12 13:46:45 -08003467
3468 case DLT_SITA:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003469 bpf_error(cstate, "SITA link-layer type filtering not implemented");
JP Abgrall511eca32014-02-12 13:46:45 -08003470
3471 case DLT_RAIF1:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003472 bpf_error(cstate, "RAIF1 link-layer type filtering not implemented");
JP Abgrall511eca32014-02-12 13:46:45 -08003473
3474 case DLT_IPMB:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003475 bpf_error(cstate, "IPMB link-layer type filtering not implemented");
JP Abgrall511eca32014-02-12 13:46:45 -08003476
3477 case DLT_AX25_KISS:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003478 bpf_error(cstate, "AX.25 link-layer type filtering not implemented");
Elliott Hughesd8845d72015-10-19 18:07:04 -07003479
3480 case DLT_NFLOG:
3481 /* Using the fixed-size NFLOG header it is possible to tell only
3482 * the address family of the packet, other meaningful data is
3483 * either missing or behind TLVs.
3484 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003485 bpf_error(cstate, "NFLOG link-layer type filtering not implemented");
Elliott Hughesd8845d72015-10-19 18:07:04 -07003486
3487 default:
3488 /*
3489 * Does this link-layer header type have a field
3490 * indicating the type of the next protocol? If
3491 * so, off_linktype.constant_part will be the offset of that
Elliott Hughes965a4b52017-05-15 10:37:39 -07003492 * field in the packet; if not, it will be OFFSET_NOT_SET.
Elliott Hughesd8845d72015-10-19 18:07:04 -07003493 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003494 if (cstate->off_linktype.constant_part != OFFSET_NOT_SET) {
Elliott Hughesd8845d72015-10-19 18:07:04 -07003495 /*
3496 * Yes; assume it's an Ethernet type. (If
3497 * it's not, it needs to be handled specially
3498 * above.)
3499 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003500 return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003501 } else {
3502 /*
3503 * No; report an error.
3504 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003505 description = pcap_datalink_val_to_description(cstate->linktype);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003506 if (description != NULL) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07003507 bpf_error(cstate, "%s link-layer type filtering not implemented",
Elliott Hughesd8845d72015-10-19 18:07:04 -07003508 description);
3509 } else {
Elliott Hughes965a4b52017-05-15 10:37:39 -07003510 bpf_error(cstate, "DLT %u link-layer type filtering not implemented",
3511 cstate->linktype);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003512 }
3513 }
3514 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003515 }
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003516}
3517
3518/*
3519 * Check for an LLC SNAP packet with a given organization code and
3520 * protocol type; we check the entire contents of the 802.2 LLC and
3521 * snap headers, checking for DSAP and SSAP of SNAP and a control
3522 * field of 0x03 in the LLC header, and for the specified organization
3523 * code and protocol type in the SNAP header.
3524 */
3525static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07003526gen_snap(compiler_state_t *cstate, bpf_u_int32 orgcode, bpf_u_int32 ptype)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003527{
3528 u_char snapblock[8];
3529
3530 snapblock[0] = LLCSAP_SNAP; /* DSAP = SNAP */
3531 snapblock[1] = LLCSAP_SNAP; /* SSAP = SNAP */
3532 snapblock[2] = 0x03; /* control = UI */
3533 snapblock[3] = (orgcode >> 16); /* upper 8 bits of organization code */
3534 snapblock[4] = (orgcode >> 8); /* middle 8 bits of organization code */
3535 snapblock[5] = (orgcode >> 0); /* lower 8 bits of organization code */
3536 snapblock[6] = (ptype >> 8); /* upper 8 bits of protocol type */
3537 snapblock[7] = (ptype >> 0); /* lower 8 bits of protocol type */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003538 return gen_bcmp(cstate, OR_LLC, 0, 8, snapblock);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003539}
3540
3541/*
3542 * Generate code to match frames with an LLC header.
3543 */
3544struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07003545gen_llc(compiler_state_t *cstate)
Elliott Hughesd8845d72015-10-19 18:07:04 -07003546{
3547 struct block *b0, *b1;
3548
Elliott Hughes965a4b52017-05-15 10:37:39 -07003549 switch (cstate->linktype) {
Elliott Hughesd8845d72015-10-19 18:07:04 -07003550
3551 case DLT_EN10MB:
3552 /*
3553 * We check for an Ethernet type field less than
3554 * 1500, which means it's an 802.3 length field.
3555 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003556 b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003557 gen_not(b0);
3558
3559 /*
3560 * Now check for the purported DSAP and SSAP not being
3561 * 0xFF, to rule out NetWare-over-802.3.
3562 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003563 b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003564 gen_not(b1);
3565 gen_and(b0, b1);
3566 return b1;
3567
3568 case DLT_SUNATM:
3569 /*
3570 * We check for LLC traffic.
3571 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003572 b0 = gen_atmtype_abbrev(cstate, A_LLC);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003573 return b0;
3574
3575 case DLT_IEEE802: /* Token Ring */
3576 /*
3577 * XXX - check for LLC frames.
3578 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003579 return gen_true(cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003580
3581 case DLT_FDDI:
3582 /*
3583 * XXX - check for LLC frames.
3584 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003585 return gen_true(cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003586
3587 case DLT_ATM_RFC1483:
3588 /*
3589 * For LLC encapsulation, these are defined to have an
3590 * 802.2 LLC header.
3591 *
3592 * For VC encapsulation, they don't, but there's no
3593 * way to check for that; the protocol used on the VC
3594 * is negotiated out of band.
3595 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003596 return gen_true(cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003597
3598 case DLT_IEEE802_11:
3599 case DLT_PRISM_HEADER:
3600 case DLT_IEEE802_11_RADIO:
3601 case DLT_IEEE802_11_RADIO_AVS:
3602 case DLT_PPI:
3603 /*
3604 * Check that we have a data frame.
3605 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003606 b0 = gen_check_802_11_data_frame(cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003607 return b0;
3608
3609 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003610 bpf_error(cstate, "'llc' not supported for linktype %d", cstate->linktype);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003611 /* NOTREACHED */
3612 }
3613}
3614
3615struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07003616gen_llc_i(compiler_state_t *cstate)
Elliott Hughesd8845d72015-10-19 18:07:04 -07003617{
3618 struct block *b0, *b1;
3619 struct slist *s;
3620
3621 /*
3622 * Check whether this is an LLC frame.
3623 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003624 b0 = gen_llc(cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003625
3626 /*
3627 * Load the control byte and test the low-order bit; it must
3628 * be clear for I frames.
3629 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003630 s = gen_load_a(cstate, OR_LLC, 2, BPF_B);
3631 b1 = new_block(cstate, JMP(BPF_JSET));
Elliott Hughesd8845d72015-10-19 18:07:04 -07003632 b1->s.k = 0x01;
3633 b1->stmts = s;
3634 gen_not(b1);
3635 gen_and(b0, b1);
3636 return b1;
3637}
3638
3639struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07003640gen_llc_s(compiler_state_t *cstate)
Elliott Hughesd8845d72015-10-19 18:07:04 -07003641{
3642 struct block *b0, *b1;
3643
3644 /*
3645 * Check whether this is an LLC frame.
3646 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003647 b0 = gen_llc(cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003648
3649 /*
3650 * Now compare the low-order 2 bit of the control byte against
3651 * the appropriate value for S frames.
3652 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003653 b1 = gen_mcmp(cstate, OR_LLC, 2, BPF_B, LLC_S_FMT, 0x03);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003654 gen_and(b0, b1);
3655 return b1;
3656}
3657
3658struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07003659gen_llc_u(compiler_state_t *cstate)
Elliott Hughesd8845d72015-10-19 18:07:04 -07003660{
3661 struct block *b0, *b1;
3662
3663 /*
3664 * Check whether this is an LLC frame.
3665 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003666 b0 = gen_llc(cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003667
3668 /*
3669 * Now compare the low-order 2 bit of the control byte against
3670 * the appropriate value for U frames.
3671 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003672 b1 = gen_mcmp(cstate, OR_LLC, 2, BPF_B, LLC_U_FMT, 0x03);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003673 gen_and(b0, b1);
3674 return b1;
3675}
3676
3677struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07003678gen_llc_s_subtype(compiler_state_t *cstate, bpf_u_int32 subtype)
Elliott Hughesd8845d72015-10-19 18:07:04 -07003679{
3680 struct block *b0, *b1;
3681
3682 /*
3683 * Check whether this is an LLC frame.
3684 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003685 b0 = gen_llc(cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003686
3687 /*
3688 * Now check for an S frame with the appropriate type.
3689 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003690 b1 = gen_mcmp(cstate, OR_LLC, 2, BPF_B, subtype, LLC_S_CMD_MASK);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003691 gen_and(b0, b1);
3692 return b1;
3693}
3694
3695struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07003696gen_llc_u_subtype(compiler_state_t *cstate, bpf_u_int32 subtype)
Elliott Hughesd8845d72015-10-19 18:07:04 -07003697{
3698 struct block *b0, *b1;
3699
3700 /*
3701 * Check whether this is an LLC frame.
3702 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003703 b0 = gen_llc(cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003704
3705 /*
3706 * Now check for a U frame with the appropriate type.
3707 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003708 b1 = gen_mcmp(cstate, OR_LLC, 2, BPF_B, subtype, LLC_U_CMD_MASK);
Elliott Hughesd8845d72015-10-19 18:07:04 -07003709 gen_and(b0, b1);
3710 return b1;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003711}
3712
3713/*
3714 * Generate code to match a particular packet type, for link-layer types
3715 * using 802.2 LLC headers.
3716 *
3717 * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used
3718 * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues.
3719 *
3720 * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
3721 * value, if <= ETHERMTU. We use that to determine whether to
3722 * match the DSAP or both DSAP and LSAP or to check the OUI and
3723 * protocol ID in a SNAP header.
3724 */
3725static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07003726gen_llc_linktype(compiler_state_t *cstate, int proto)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003727{
3728 /*
3729 * XXX - handle token-ring variable-length header.
3730 */
3731 switch (proto) {
3732
3733 case LLCSAP_IP:
3734 case LLCSAP_ISONS:
3735 case LLCSAP_NETBEUI:
3736 /*
3737 * XXX - should we check both the DSAP and the
3738 * SSAP, like this, or should we check just the
Elliott Hughesd8845d72015-10-19 18:07:04 -07003739 * DSAP, as we do for other SAP values?
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003740 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003741 return gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_u_int32)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003742 ((proto << 8) | proto));
3743
3744 case LLCSAP_IPX:
3745 /*
3746 * XXX - are there ever SNAP frames for IPX on
3747 * non-Ethernet 802.x networks?
3748 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003749 return gen_cmp(cstate, OR_LLC, 0, BPF_B,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003750 (bpf_int32)LLCSAP_IPX);
3751
3752 case ETHERTYPE_ATALK:
3753 /*
3754 * 802.2-encapsulated ETHERTYPE_ATALK packets are
3755 * SNAP packets with an organization code of
3756 * 0x080007 (Apple, for Appletalk) and a protocol
3757 * type of ETHERTYPE_ATALK (Appletalk).
3758 *
3759 * XXX - check for an organization code of
3760 * encapsulated Ethernet as well?
3761 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003762 return gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003763
3764 default:
3765 /*
3766 * XXX - we don't have to check for IPX 802.3
3767 * here, but should we check for the IPX Ethertype?
3768 */
3769 if (proto <= ETHERMTU) {
3770 /*
3771 * This is an LLC SAP value, so check
3772 * the DSAP.
3773 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003774 return gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003775 } else {
3776 /*
3777 * This is an Ethernet type; we assume that it's
3778 * unlikely that it'll appear in the right place
3779 * at random, and therefore check only the
3780 * location that would hold the Ethernet type
3781 * in a SNAP frame with an organization code of
3782 * 0x000000 (encapsulated Ethernet).
3783 *
3784 * XXX - if we were to check for the SNAP DSAP and
3785 * LSAP, as per XXX, and were also to check for an
3786 * organization code of 0x000000 (encapsulated
3787 * Ethernet), we'd do
3788 *
Elliott Hughes965a4b52017-05-15 10:37:39 -07003789 * return gen_snap(cstate, 0x000000, proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003790 *
3791 * here; for now, we don't, as per the above.
3792 * I don't know whether it's worth the extra CPU
3793 * time to do the right check or not.
3794 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07003795 return gen_cmp(cstate, OR_LLC, 6, BPF_H, (bpf_int32)proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003796 }
3797 }
3798}
3799
3800static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07003801gen_hostop(compiler_state_t *cstate, bpf_u_int32 addr, bpf_u_int32 mask,
3802 int dir, int proto, u_int src_off, u_int dst_off)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003803{
3804 struct block *b0, *b1;
3805 u_int offset;
3806
3807 switch (dir) {
3808
3809 case Q_SRC:
3810 offset = src_off;
3811 break;
3812
3813 case Q_DST:
3814 offset = dst_off;
3815 break;
3816
3817 case Q_AND:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003818 b0 = gen_hostop(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
3819 b1 = gen_hostop(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003820 gen_and(b0, b1);
3821 return b1;
3822
3823 case Q_OR:
3824 case Q_DEFAULT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003825 b0 = gen_hostop(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
3826 b1 = gen_hostop(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003827 gen_or(b0, b1);
3828 return b1;
3829
3830 default:
3831 abort();
3832 }
Elliott Hughes965a4b52017-05-15 10:37:39 -07003833 b0 = gen_linktype(cstate, proto);
3834 b1 = gen_mcmp(cstate, OR_LINKPL, offset, BPF_W, (bpf_int32)addr, mask);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003835 gen_and(b0, b1);
3836 return b1;
3837}
3838
3839#ifdef INET6
3840static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07003841gen_hostop6(compiler_state_t *cstate, struct in6_addr *addr,
3842 struct in6_addr *mask, int dir, int proto, u_int src_off, u_int dst_off)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003843{
3844 struct block *b0, *b1;
3845 u_int offset;
3846 u_int32_t *a, *m;
3847
3848 switch (dir) {
3849
3850 case Q_SRC:
3851 offset = src_off;
3852 break;
3853
3854 case Q_DST:
3855 offset = dst_off;
3856 break;
3857
3858 case Q_AND:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003859 b0 = gen_hostop6(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
3860 b1 = gen_hostop6(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003861 gen_and(b0, b1);
3862 return b1;
3863
3864 case Q_OR:
3865 case Q_DEFAULT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003866 b0 = gen_hostop6(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
3867 b1 = gen_hostop6(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003868 gen_or(b0, b1);
3869 return b1;
3870
3871 default:
3872 abort();
3873 }
3874 /* this order is important */
3875 a = (u_int32_t *)addr;
3876 m = (u_int32_t *)mask;
Elliott Hughes965a4b52017-05-15 10:37:39 -07003877 b1 = gen_mcmp(cstate, OR_LINKPL, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
3878 b0 = gen_mcmp(cstate, OR_LINKPL, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003879 gen_and(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07003880 b0 = gen_mcmp(cstate, OR_LINKPL, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003881 gen_and(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07003882 b0 = gen_mcmp(cstate, OR_LINKPL, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003883 gen_and(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07003884 b0 = gen_linktype(cstate, proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003885 gen_and(b0, b1);
3886 return b1;
3887}
JP Abgrall511eca32014-02-12 13:46:45 -08003888#endif
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003889
3890static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07003891gen_ehostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003892{
3893 register struct block *b0, *b1;
3894
3895 switch (dir) {
3896 case Q_SRC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003897 return gen_bcmp(cstate, OR_LINKHDR, 6, 6, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003898
3899 case Q_DST:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003900 return gen_bcmp(cstate, OR_LINKHDR, 0, 6, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003901
3902 case Q_AND:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003903 b0 = gen_ehostop(cstate, eaddr, Q_SRC);
3904 b1 = gen_ehostop(cstate, eaddr, Q_DST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003905 gen_and(b0, b1);
3906 return b1;
3907
3908 case Q_DEFAULT:
3909 case Q_OR:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003910 b0 = gen_ehostop(cstate, eaddr, Q_SRC);
3911 b1 = gen_ehostop(cstate, eaddr, Q_DST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003912 gen_or(b0, b1);
3913 return b1;
JP Abgrall511eca32014-02-12 13:46:45 -08003914
3915 case Q_ADDR1:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003916 bpf_error(cstate, "'addr1' is only supported on 802.11 with 802.11 headers");
JP Abgrall511eca32014-02-12 13:46:45 -08003917 break;
3918
3919 case Q_ADDR2:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003920 bpf_error(cstate, "'addr2' is only supported on 802.11 with 802.11 headers");
JP Abgrall511eca32014-02-12 13:46:45 -08003921 break;
3922
3923 case Q_ADDR3:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003924 bpf_error(cstate, "'addr3' is only supported on 802.11 with 802.11 headers");
JP Abgrall511eca32014-02-12 13:46:45 -08003925 break;
3926
3927 case Q_ADDR4:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003928 bpf_error(cstate, "'addr4' is only supported on 802.11 with 802.11 headers");
JP Abgrall511eca32014-02-12 13:46:45 -08003929 break;
3930
3931 case Q_RA:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003932 bpf_error(cstate, "'ra' is only supported on 802.11 with 802.11 headers");
JP Abgrall511eca32014-02-12 13:46:45 -08003933 break;
3934
3935 case Q_TA:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003936 bpf_error(cstate, "'ta' is only supported on 802.11 with 802.11 headers");
JP Abgrall511eca32014-02-12 13:46:45 -08003937 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003938 }
3939 abort();
3940 /* NOTREACHED */
3941}
3942
3943/*
3944 * Like gen_ehostop, but for DLT_FDDI
3945 */
3946static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07003947gen_fhostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003948{
3949 struct block *b0, *b1;
3950
3951 switch (dir) {
3952 case Q_SRC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003953 return gen_bcmp(cstate, OR_LINKHDR, 6 + 1 + cstate->pcap_fddipad, 6, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003954
3955 case Q_DST:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003956 return gen_bcmp(cstate, OR_LINKHDR, 0 + 1 + cstate->pcap_fddipad, 6, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003957
3958 case Q_AND:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003959 b0 = gen_fhostop(cstate, eaddr, Q_SRC);
3960 b1 = gen_fhostop(cstate, eaddr, Q_DST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003961 gen_and(b0, b1);
3962 return b1;
3963
3964 case Q_DEFAULT:
3965 case Q_OR:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003966 b0 = gen_fhostop(cstate, eaddr, Q_SRC);
3967 b1 = gen_fhostop(cstate, eaddr, Q_DST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003968 gen_or(b0, b1);
3969 return b1;
JP Abgrall511eca32014-02-12 13:46:45 -08003970
3971 case Q_ADDR1:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003972 bpf_error(cstate, "'addr1' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08003973 break;
3974
3975 case Q_ADDR2:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003976 bpf_error(cstate, "'addr2' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08003977 break;
3978
3979 case Q_ADDR3:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003980 bpf_error(cstate, "'addr3' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08003981 break;
3982
3983 case Q_ADDR4:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003984 bpf_error(cstate, "'addr4' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08003985 break;
3986
3987 case Q_RA:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003988 bpf_error(cstate, "'ra' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08003989 break;
3990
3991 case Q_TA:
Elliott Hughes965a4b52017-05-15 10:37:39 -07003992 bpf_error(cstate, "'ta' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08003993 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08003994 }
3995 abort();
3996 /* NOTREACHED */
3997}
3998
3999/*
4000 * Like gen_ehostop, but for DLT_IEEE802 (Token Ring)
4001 */
4002static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07004003gen_thostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004004{
4005 register struct block *b0, *b1;
4006
4007 switch (dir) {
4008 case Q_SRC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004009 return gen_bcmp(cstate, OR_LINKHDR, 8, 6, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004010
4011 case Q_DST:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004012 return gen_bcmp(cstate, OR_LINKHDR, 2, 6, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004013
4014 case Q_AND:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004015 b0 = gen_thostop(cstate, eaddr, Q_SRC);
4016 b1 = gen_thostop(cstate, eaddr, Q_DST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004017 gen_and(b0, b1);
4018 return b1;
4019
4020 case Q_DEFAULT:
4021 case Q_OR:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004022 b0 = gen_thostop(cstate, eaddr, Q_SRC);
4023 b1 = gen_thostop(cstate, eaddr, Q_DST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004024 gen_or(b0, b1);
4025 return b1;
JP Abgrall511eca32014-02-12 13:46:45 -08004026
4027 case Q_ADDR1:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004028 bpf_error(cstate, "'addr1' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08004029 break;
4030
4031 case Q_ADDR2:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004032 bpf_error(cstate, "'addr2' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08004033 break;
4034
4035 case Q_ADDR3:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004036 bpf_error(cstate, "'addr3' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08004037 break;
4038
4039 case Q_ADDR4:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004040 bpf_error(cstate, "'addr4' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08004041 break;
4042
4043 case Q_RA:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004044 bpf_error(cstate, "'ra' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08004045 break;
4046
4047 case Q_TA:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004048 bpf_error(cstate, "'ta' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08004049 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004050 }
4051 abort();
4052 /* NOTREACHED */
4053}
4054
4055/*
JP Abgrall511eca32014-02-12 13:46:45 -08004056 * Like gen_ehostop, but for DLT_IEEE802_11 (802.11 wireless LAN) and
4057 * various 802.11 + radio headers.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004058 */
4059static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07004060gen_wlanhostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004061{
4062 register struct block *b0, *b1, *b2;
4063 register struct slist *s;
4064
JP Abgrall511eca32014-02-12 13:46:45 -08004065#ifdef ENABLE_WLAN_FILTERING_PATCH
4066 /*
4067 * TODO GV 20070613
4068 * We need to disable the optimizer because the optimizer is buggy
4069 * and wipes out some LD instructions generated by the below
4070 * code to validate the Frame Control bits
4071 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004072 cstate->no_optimize = 1;
JP Abgrall511eca32014-02-12 13:46:45 -08004073#endif /* ENABLE_WLAN_FILTERING_PATCH */
4074
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004075 switch (dir) {
4076 case Q_SRC:
4077 /*
4078 * Oh, yuk.
4079 *
4080 * For control frames, there is no SA.
4081 *
4082 * For management frames, SA is at an
4083 * offset of 10 from the beginning of
4084 * the packet.
4085 *
4086 * For data frames, SA is at an offset
4087 * of 10 from the beginning of the packet
4088 * if From DS is clear, at an offset of
4089 * 16 from the beginning of the packet
4090 * if From DS is set and To DS is clear,
4091 * and an offset of 24 from the beginning
4092 * of the packet if From DS is set and To DS
4093 * is set.
4094 */
4095
4096 /*
4097 * Generate the tests to be done for data frames
4098 * with From DS set.
4099 *
4100 * First, check for To DS set, i.e. check "link[1] & 0x01".
4101 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004102 s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
4103 b1 = new_block(cstate, JMP(BPF_JSET));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004104 b1->s.k = 0x01; /* To DS */
4105 b1->stmts = s;
4106
4107 /*
4108 * If To DS is set, the SA is at 24.
4109 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004110 b0 = gen_bcmp(cstate, OR_LINKHDR, 24, 6, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004111 gen_and(b1, b0);
4112
4113 /*
4114 * Now, check for To DS not set, i.e. check
4115 * "!(link[1] & 0x01)".
4116 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004117 s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
4118 b2 = new_block(cstate, JMP(BPF_JSET));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004119 b2->s.k = 0x01; /* To DS */
4120 b2->stmts = s;
4121 gen_not(b2);
4122
4123 /*
4124 * If To DS is not set, the SA is at 16.
4125 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004126 b1 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004127 gen_and(b2, b1);
4128
4129 /*
4130 * Now OR together the last two checks. That gives
4131 * the complete set of checks for data frames with
4132 * From DS set.
4133 */
4134 gen_or(b1, b0);
4135
4136 /*
4137 * Now check for From DS being set, and AND that with
4138 * the ORed-together checks.
4139 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004140 s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
4141 b1 = new_block(cstate, JMP(BPF_JSET));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004142 b1->s.k = 0x02; /* From DS */
4143 b1->stmts = s;
4144 gen_and(b1, b0);
4145
4146 /*
4147 * Now check for data frames with From DS not set.
4148 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004149 s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
4150 b2 = new_block(cstate, JMP(BPF_JSET));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004151 b2->s.k = 0x02; /* From DS */
4152 b2->stmts = s;
4153 gen_not(b2);
4154
4155 /*
4156 * If From DS isn't set, the SA is at 10.
4157 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004158 b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004159 gen_and(b2, b1);
4160
4161 /*
4162 * Now OR together the checks for data frames with
4163 * From DS not set and for data frames with From DS
4164 * set; that gives the checks done for data frames.
4165 */
4166 gen_or(b1, b0);
4167
4168 /*
4169 * Now check for a data frame.
4170 * I.e, check "link[0] & 0x08".
4171 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004172 s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
4173 b1 = new_block(cstate, JMP(BPF_JSET));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004174 b1->s.k = 0x08;
4175 b1->stmts = s;
4176
4177 /*
4178 * AND that with the checks done for data frames.
4179 */
4180 gen_and(b1, b0);
4181
4182 /*
4183 * If the high-order bit of the type value is 0, this
4184 * is a management frame.
4185 * I.e, check "!(link[0] & 0x08)".
4186 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004187 s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
4188 b2 = new_block(cstate, JMP(BPF_JSET));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004189 b2->s.k = 0x08;
4190 b2->stmts = s;
4191 gen_not(b2);
4192
4193 /*
4194 * For management frames, the SA is at 10.
4195 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004196 b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004197 gen_and(b2, b1);
4198
4199 /*
4200 * OR that with the checks done for data frames.
4201 * That gives the checks done for management and
4202 * data frames.
4203 */
4204 gen_or(b1, b0);
4205
4206 /*
4207 * If the low-order bit of the type value is 1,
4208 * this is either a control frame or a frame
4209 * with a reserved type, and thus not a
4210 * frame with an SA.
4211 *
4212 * I.e., check "!(link[0] & 0x04)".
4213 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004214 s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
4215 b1 = new_block(cstate, JMP(BPF_JSET));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004216 b1->s.k = 0x04;
4217 b1->stmts = s;
4218 gen_not(b1);
4219
4220 /*
4221 * AND that with the checks for data and management
4222 * frames.
4223 */
4224 gen_and(b1, b0);
4225 return b0;
4226
4227 case Q_DST:
4228 /*
4229 * Oh, yuk.
4230 *
4231 * For control frames, there is no DA.
4232 *
4233 * For management frames, DA is at an
4234 * offset of 4 from the beginning of
4235 * the packet.
4236 *
4237 * For data frames, DA is at an offset
4238 * of 4 from the beginning of the packet
4239 * if To DS is clear and at an offset of
4240 * 16 from the beginning of the packet
4241 * if To DS is set.
4242 */
4243
4244 /*
4245 * Generate the tests to be done for data frames.
4246 *
4247 * First, check for To DS set, i.e. "link[1] & 0x01".
4248 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004249 s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
4250 b1 = new_block(cstate, JMP(BPF_JSET));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004251 b1->s.k = 0x01; /* To DS */
4252 b1->stmts = s;
4253
4254 /*
4255 * If To DS is set, the DA is at 16.
4256 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004257 b0 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004258 gen_and(b1, b0);
4259
4260 /*
4261 * Now, check for To DS not set, i.e. check
4262 * "!(link[1] & 0x01)".
4263 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004264 s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
4265 b2 = new_block(cstate, JMP(BPF_JSET));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004266 b2->s.k = 0x01; /* To DS */
4267 b2->stmts = s;
4268 gen_not(b2);
4269
4270 /*
4271 * If To DS is not set, the DA is at 4.
4272 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004273 b1 = gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004274 gen_and(b2, b1);
4275
4276 /*
4277 * Now OR together the last two checks. That gives
4278 * the complete set of checks for data frames.
4279 */
4280 gen_or(b1, b0);
4281
4282 /*
4283 * Now check for a data frame.
4284 * I.e, check "link[0] & 0x08".
4285 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004286 s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
4287 b1 = new_block(cstate, JMP(BPF_JSET));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004288 b1->s.k = 0x08;
4289 b1->stmts = s;
4290
4291 /*
4292 * AND that with the checks done for data frames.
4293 */
4294 gen_and(b1, b0);
4295
4296 /*
4297 * If the high-order bit of the type value is 0, this
4298 * is a management frame.
4299 * I.e, check "!(link[0] & 0x08)".
4300 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004301 s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
4302 b2 = new_block(cstate, JMP(BPF_JSET));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004303 b2->s.k = 0x08;
4304 b2->stmts = s;
4305 gen_not(b2);
4306
4307 /*
4308 * For management frames, the DA is at 4.
4309 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004310 b1 = gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004311 gen_and(b2, b1);
4312
4313 /*
4314 * OR that with the checks done for data frames.
4315 * That gives the checks done for management and
4316 * data frames.
4317 */
4318 gen_or(b1, b0);
4319
4320 /*
4321 * If the low-order bit of the type value is 1,
4322 * this is either a control frame or a frame
4323 * with a reserved type, and thus not a
4324 * frame with an SA.
4325 *
4326 * I.e., check "!(link[0] & 0x04)".
4327 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004328 s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
4329 b1 = new_block(cstate, JMP(BPF_JSET));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004330 b1->s.k = 0x04;
4331 b1->stmts = s;
4332 gen_not(b1);
4333
4334 /*
4335 * AND that with the checks for data and management
4336 * frames.
4337 */
4338 gen_and(b1, b0);
4339 return b0;
4340
JP Abgrall511eca32014-02-12 13:46:45 -08004341 case Q_RA:
4342 /*
4343 * Not present in management frames; addr1 in other
4344 * frames.
4345 */
4346
4347 /*
4348 * If the high-order bit of the type value is 0, this
4349 * is a management frame.
4350 * I.e, check "(link[0] & 0x08)".
4351 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004352 s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
4353 b1 = new_block(cstate, JMP(BPF_JSET));
JP Abgrall511eca32014-02-12 13:46:45 -08004354 b1->s.k = 0x08;
4355 b1->stmts = s;
4356
4357 /*
4358 * Check addr1.
4359 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004360 b0 = gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr);
JP Abgrall511eca32014-02-12 13:46:45 -08004361
4362 /*
4363 * AND that with the check of addr1.
4364 */
4365 gen_and(b1, b0);
4366 return (b0);
4367
4368 case Q_TA:
4369 /*
4370 * Not present in management frames; addr2, if present,
4371 * in other frames.
4372 */
4373
4374 /*
4375 * Not present in CTS or ACK control frames.
4376 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004377 b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
JP Abgrall511eca32014-02-12 13:46:45 -08004378 IEEE80211_FC0_TYPE_MASK);
4379 gen_not(b0);
Elliott Hughes965a4b52017-05-15 10:37:39 -07004380 b1 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
JP Abgrall511eca32014-02-12 13:46:45 -08004381 IEEE80211_FC0_SUBTYPE_MASK);
4382 gen_not(b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07004383 b2 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
JP Abgrall511eca32014-02-12 13:46:45 -08004384 IEEE80211_FC0_SUBTYPE_MASK);
4385 gen_not(b2);
4386 gen_and(b1, b2);
4387 gen_or(b0, b2);
4388
4389 /*
4390 * If the high-order bit of the type value is 0, this
4391 * is a management frame.
4392 * I.e, check "(link[0] & 0x08)".
4393 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004394 s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
4395 b1 = new_block(cstate, JMP(BPF_JSET));
JP Abgrall511eca32014-02-12 13:46:45 -08004396 b1->s.k = 0x08;
4397 b1->stmts = s;
4398
4399 /*
4400 * AND that with the check for frames other than
4401 * CTS and ACK frames.
4402 */
4403 gen_and(b1, b2);
4404
4405 /*
4406 * Check addr2.
4407 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004408 b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
JP Abgrall511eca32014-02-12 13:46:45 -08004409 gen_and(b2, b1);
4410 return b1;
4411
4412 /*
4413 * XXX - add BSSID keyword?
4414 */
4415 case Q_ADDR1:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004416 return (gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr));
JP Abgrall511eca32014-02-12 13:46:45 -08004417
4418 case Q_ADDR2:
4419 /*
4420 * Not present in CTS or ACK control frames.
4421 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004422 b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
JP Abgrall511eca32014-02-12 13:46:45 -08004423 IEEE80211_FC0_TYPE_MASK);
4424 gen_not(b0);
Elliott Hughes965a4b52017-05-15 10:37:39 -07004425 b1 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
JP Abgrall511eca32014-02-12 13:46:45 -08004426 IEEE80211_FC0_SUBTYPE_MASK);
4427 gen_not(b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07004428 b2 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
JP Abgrall511eca32014-02-12 13:46:45 -08004429 IEEE80211_FC0_SUBTYPE_MASK);
4430 gen_not(b2);
4431 gen_and(b1, b2);
4432 gen_or(b0, b2);
Elliott Hughes965a4b52017-05-15 10:37:39 -07004433 b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
JP Abgrall511eca32014-02-12 13:46:45 -08004434 gen_and(b2, b1);
4435 return b1;
4436
4437 case Q_ADDR3:
4438 /*
4439 * Not present in control frames.
4440 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004441 b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
JP Abgrall511eca32014-02-12 13:46:45 -08004442 IEEE80211_FC0_TYPE_MASK);
4443 gen_not(b0);
Elliott Hughes965a4b52017-05-15 10:37:39 -07004444 b1 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
JP Abgrall511eca32014-02-12 13:46:45 -08004445 gen_and(b0, b1);
4446 return b1;
4447
4448 case Q_ADDR4:
4449 /*
4450 * Present only if the direction mask has both "From DS"
4451 * and "To DS" set. Neither control frames nor management
4452 * frames should have both of those set, so we don't
4453 * check the frame type.
4454 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004455 b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B,
JP Abgrall511eca32014-02-12 13:46:45 -08004456 IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
Elliott Hughes965a4b52017-05-15 10:37:39 -07004457 b1 = gen_bcmp(cstate, OR_LINKHDR, 24, 6, eaddr);
JP Abgrall511eca32014-02-12 13:46:45 -08004458 gen_and(b0, b1);
4459 return b1;
4460
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004461 case Q_AND:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004462 b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
4463 b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004464 gen_and(b0, b1);
4465 return b1;
4466
4467 case Q_DEFAULT:
4468 case Q_OR:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004469 b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
4470 b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004471 gen_or(b0, b1);
4472 return b1;
4473 }
4474 abort();
4475 /* NOTREACHED */
4476}
4477
4478/*
4479 * Like gen_ehostop, but for RFC 2625 IP-over-Fibre-Channel.
4480 * (We assume that the addresses are IEEE 48-bit MAC addresses,
4481 * as the RFC states.)
4482 */
4483static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07004484gen_ipfchostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004485{
4486 register struct block *b0, *b1;
4487
4488 switch (dir) {
4489 case Q_SRC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004490 return gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004491
4492 case Q_DST:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004493 return gen_bcmp(cstate, OR_LINKHDR, 2, 6, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004494
4495 case Q_AND:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004496 b0 = gen_ipfchostop(cstate, eaddr, Q_SRC);
4497 b1 = gen_ipfchostop(cstate, eaddr, Q_DST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004498 gen_and(b0, b1);
4499 return b1;
4500
4501 case Q_DEFAULT:
4502 case Q_OR:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004503 b0 = gen_ipfchostop(cstate, eaddr, Q_SRC);
4504 b1 = gen_ipfchostop(cstate, eaddr, Q_DST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004505 gen_or(b0, b1);
4506 return b1;
JP Abgrall511eca32014-02-12 13:46:45 -08004507
4508 case Q_ADDR1:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004509 bpf_error(cstate, "'addr1' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08004510 break;
4511
4512 case Q_ADDR2:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004513 bpf_error(cstate, "'addr2' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08004514 break;
4515
4516 case Q_ADDR3:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004517 bpf_error(cstate, "'addr3' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08004518 break;
4519
4520 case Q_ADDR4:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004521 bpf_error(cstate, "'addr4' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08004522 break;
4523
4524 case Q_RA:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004525 bpf_error(cstate, "'ra' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08004526 break;
4527
4528 case Q_TA:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004529 bpf_error(cstate, "'ta' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08004530 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004531 }
4532 abort();
4533 /* NOTREACHED */
4534}
4535
4536/*
4537 * This is quite tricky because there may be pad bytes in front of the
4538 * DECNET header, and then there are two possible data packet formats that
4539 * carry both src and dst addresses, plus 5 packet types in a format that
4540 * carries only the src node, plus 2 types that use a different format and
4541 * also carry just the src node.
4542 *
4543 * Yuck.
4544 *
4545 * Instead of doing those all right, we just look for data packets with
4546 * 0 or 1 bytes of padding. If you want to look at other packets, that
4547 * will require a lot more hacking.
4548 *
4549 * To add support for filtering on DECNET "areas" (network numbers)
4550 * one would want to add a "mask" argument to this routine. That would
4551 * make the filter even more inefficient, although one could be clever
4552 * and not generate masking instructions if the mask is 0xFFFF.
4553 */
4554static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07004555gen_dnhostop(compiler_state_t *cstate, bpf_u_int32 addr, int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004556{
4557 struct block *b0, *b1, *b2, *tmp;
4558 u_int offset_lh; /* offset if long header is received */
4559 u_int offset_sh; /* offset if short header is received */
4560
4561 switch (dir) {
4562
4563 case Q_DST:
4564 offset_sh = 1; /* follows flags */
4565 offset_lh = 7; /* flgs,darea,dsubarea,HIORD */
4566 break;
4567
4568 case Q_SRC:
4569 offset_sh = 3; /* follows flags, dstnode */
4570 offset_lh = 15; /* flgs,darea,dsubarea,did,sarea,ssub,HIORD */
4571 break;
4572
4573 case Q_AND:
4574 /* Inefficient because we do our Calvinball dance twice */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004575 b0 = gen_dnhostop(cstate, addr, Q_SRC);
4576 b1 = gen_dnhostop(cstate, addr, Q_DST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004577 gen_and(b0, b1);
4578 return b1;
4579
4580 case Q_OR:
4581 case Q_DEFAULT:
4582 /* Inefficient because we do our Calvinball dance twice */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004583 b0 = gen_dnhostop(cstate, addr, Q_SRC);
4584 b1 = gen_dnhostop(cstate, addr, Q_DST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004585 gen_or(b0, b1);
4586 return b1;
4587
4588 case Q_ISO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004589 bpf_error(cstate, "ISO host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004590
4591 default:
4592 abort();
4593 }
Elliott Hughes965a4b52017-05-15 10:37:39 -07004594 b0 = gen_linktype(cstate, ETHERTYPE_DN);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004595 /* Check for pad = 1, long header case */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004596 tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_H,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004597 (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF));
Elliott Hughes965a4b52017-05-15 10:37:39 -07004598 b1 = gen_cmp(cstate, OR_LINKPL, 2 + 1 + offset_lh,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004599 BPF_H, (bpf_int32)ntohs((u_short)addr));
4600 gen_and(tmp, b1);
4601 /* Check for pad = 0, long header case */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004602 tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
4603 b2 = gen_cmp(cstate, OR_LINKPL, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004604 gen_and(tmp, b2);
4605 gen_or(b2, b1);
4606 /* Check for pad = 1, short header case */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004607 tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_H,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004608 (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF));
Elliott Hughes965a4b52017-05-15 10:37:39 -07004609 b2 = gen_cmp(cstate, OR_LINKPL, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004610 gen_and(tmp, b2);
4611 gen_or(b2, b1);
4612 /* Check for pad = 0, short header case */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004613 tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
4614 b2 = gen_cmp(cstate, OR_LINKPL, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004615 gen_and(tmp, b2);
4616 gen_or(b2, b1);
4617
Elliott Hughes965a4b52017-05-15 10:37:39 -07004618 /* Combine with test for cstate->linktype */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004619 gen_and(b0, b1);
4620 return b1;
4621}
4622
4623/*
4624 * Generate a check for IPv4 or IPv6 for MPLS-encapsulated packets;
4625 * test the bottom-of-stack bit, and then check the version number
4626 * field in the IP header.
4627 */
4628static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07004629gen_mpls_linktype(compiler_state_t *cstate, int proto)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004630{
4631 struct block *b0, *b1;
4632
4633 switch (proto) {
4634
4635 case Q_IP:
4636 /* match the bottom-of-stack bit */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004637 b0 = gen_mcmp(cstate, OR_LINKPL, -2, BPF_B, 0x01, 0x01);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004638 /* match the IPv4 version number */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004639 b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_B, 0x40, 0xf0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004640 gen_and(b0, b1);
4641 return b1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07004642
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004643 case Q_IPV6:
4644 /* match the bottom-of-stack bit */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004645 b0 = gen_mcmp(cstate, OR_LINKPL, -2, BPF_B, 0x01, 0x01);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004646 /* match the IPv4 version number */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004647 b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_B, 0x60, 0xf0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004648 gen_and(b0, b1);
4649 return b1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07004650
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004651 default:
4652 abort();
4653 }
4654}
4655
4656static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07004657gen_host(compiler_state_t *cstate, bpf_u_int32 addr, bpf_u_int32 mask,
4658 int proto, int dir, int type)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004659{
4660 struct block *b0, *b1;
4661 const char *typestr;
4662
4663 if (type == Q_NET)
4664 typestr = "net";
4665 else
4666 typestr = "host";
4667
4668 switch (proto) {
4669
4670 case Q_DEFAULT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004671 b0 = gen_host(cstate, addr, mask, Q_IP, dir, type);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004672 /*
4673 * Only check for non-IPv4 addresses if we're not
4674 * checking MPLS-encapsulated packets.
4675 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004676 if (cstate->label_stack_depth == 0) {
4677 b1 = gen_host(cstate, addr, mask, Q_ARP, dir, type);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004678 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07004679 b0 = gen_host(cstate, addr, mask, Q_RARP, dir, type);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004680 gen_or(b1, b0);
4681 }
4682 return b0;
4683
4684 case Q_IP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004685 return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_IP, 12, 16);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004686
4687 case Q_RARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004688 return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_REVARP, 14, 24);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004689
4690 case Q_ARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004691 return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_ARP, 14, 24);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004692
4693 case Q_TCP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004694 bpf_error(cstate, "'tcp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004695
4696 case Q_SCTP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004697 bpf_error(cstate, "'sctp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004698
4699 case Q_UDP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004700 bpf_error(cstate, "'udp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004701
4702 case Q_ICMP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004703 bpf_error(cstate, "'icmp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004704
4705 case Q_IGMP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004706 bpf_error(cstate, "'igmp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004707
4708 case Q_IGRP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004709 bpf_error(cstate, "'igrp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004710
4711 case Q_PIM:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004712 bpf_error(cstate, "'pim' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004713
4714 case Q_VRRP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004715 bpf_error(cstate, "'vrrp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004716
JP Abgrall511eca32014-02-12 13:46:45 -08004717 case Q_CARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004718 bpf_error(cstate, "'carp' modifier applied to %s", typestr);
JP Abgrall511eca32014-02-12 13:46:45 -08004719
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004720 case Q_ATALK:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004721 bpf_error(cstate, "ATALK host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004722
4723 case Q_AARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004724 bpf_error(cstate, "AARP host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004725
4726 case Q_DECNET:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004727 return gen_dnhostop(cstate, addr, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004728
4729 case Q_SCA:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004730 bpf_error(cstate, "SCA host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004731
4732 case Q_LAT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004733 bpf_error(cstate, "LAT host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004734
4735 case Q_MOPDL:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004736 bpf_error(cstate, "MOPDL host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004737
4738 case Q_MOPRC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004739 bpf_error(cstate, "MOPRC host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004740
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004741 case Q_IPV6:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004742 bpf_error(cstate, "'ip6' modifier applied to ip host");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004743
4744 case Q_ICMPV6:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004745 bpf_error(cstate, "'icmp6' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004746
4747 case Q_AH:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004748 bpf_error(cstate, "'ah' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004749
4750 case Q_ESP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004751 bpf_error(cstate, "'esp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004752
4753 case Q_ISO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004754 bpf_error(cstate, "ISO host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004755
4756 case Q_ESIS:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004757 bpf_error(cstate, "'esis' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004758
4759 case Q_ISIS:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004760 bpf_error(cstate, "'isis' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004761
4762 case Q_CLNP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004763 bpf_error(cstate, "'clnp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004764
4765 case Q_STP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004766 bpf_error(cstate, "'stp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004767
4768 case Q_IPX:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004769 bpf_error(cstate, "IPX host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004770
4771 case Q_NETBEUI:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004772 bpf_error(cstate, "'netbeui' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004773
4774 case Q_RADIO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004775 bpf_error(cstate, "'radio' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004776
4777 default:
4778 abort();
4779 }
4780 /* NOTREACHED */
4781}
4782
4783#ifdef INET6
4784static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07004785gen_host6(compiler_state_t *cstate, struct in6_addr *addr,
4786 struct in6_addr *mask, int proto, int dir, int type)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004787{
4788 const char *typestr;
4789
4790 if (type == Q_NET)
4791 typestr = "net";
4792 else
4793 typestr = "host";
4794
4795 switch (proto) {
4796
4797 case Q_DEFAULT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004798 return gen_host6(cstate, addr, mask, Q_IPV6, dir, type);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004799
JP Abgrall511eca32014-02-12 13:46:45 -08004800 case Q_LINK:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004801 bpf_error(cstate, "link-layer modifier applied to ip6 %s", typestr);
JP Abgrall511eca32014-02-12 13:46:45 -08004802
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004803 case Q_IP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004804 bpf_error(cstate, "'ip' modifier applied to ip6 %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004805
4806 case Q_RARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004807 bpf_error(cstate, "'rarp' modifier applied to ip6 %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004808
4809 case Q_ARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004810 bpf_error(cstate, "'arp' modifier applied to ip6 %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004811
4812 case Q_SCTP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004813 bpf_error(cstate, "'sctp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004814
4815 case Q_TCP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004816 bpf_error(cstate, "'tcp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004817
4818 case Q_UDP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004819 bpf_error(cstate, "'udp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004820
4821 case Q_ICMP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004822 bpf_error(cstate, "'icmp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004823
4824 case Q_IGMP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004825 bpf_error(cstate, "'igmp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004826
4827 case Q_IGRP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004828 bpf_error(cstate, "'igrp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004829
4830 case Q_PIM:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004831 bpf_error(cstate, "'pim' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004832
4833 case Q_VRRP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004834 bpf_error(cstate, "'vrrp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004835
JP Abgrall511eca32014-02-12 13:46:45 -08004836 case Q_CARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004837 bpf_error(cstate, "'carp' modifier applied to %s", typestr);
JP Abgrall511eca32014-02-12 13:46:45 -08004838
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004839 case Q_ATALK:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004840 bpf_error(cstate, "ATALK host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004841
4842 case Q_AARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004843 bpf_error(cstate, "AARP host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004844
4845 case Q_DECNET:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004846 bpf_error(cstate, "'decnet' modifier applied to ip6 %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004847
4848 case Q_SCA:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004849 bpf_error(cstate, "SCA host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004850
4851 case Q_LAT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004852 bpf_error(cstate, "LAT host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004853
4854 case Q_MOPDL:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004855 bpf_error(cstate, "MOPDL host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004856
4857 case Q_MOPRC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004858 bpf_error(cstate, "MOPRC host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004859
4860 case Q_IPV6:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004861 return gen_hostop6(cstate, addr, mask, dir, ETHERTYPE_IPV6, 8, 24);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004862
4863 case Q_ICMPV6:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004864 bpf_error(cstate, "'icmp6' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004865
4866 case Q_AH:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004867 bpf_error(cstate, "'ah' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004868
4869 case Q_ESP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004870 bpf_error(cstate, "'esp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004871
4872 case Q_ISO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004873 bpf_error(cstate, "ISO host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004874
4875 case Q_ESIS:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004876 bpf_error(cstate, "'esis' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004877
4878 case Q_ISIS:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004879 bpf_error(cstate, "'isis' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004880
4881 case Q_CLNP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004882 bpf_error(cstate, "'clnp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004883
4884 case Q_STP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004885 bpf_error(cstate, "'stp' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004886
4887 case Q_IPX:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004888 bpf_error(cstate, "IPX host filtering not implemented");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004889
4890 case Q_NETBEUI:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004891 bpf_error(cstate, "'netbeui' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004892
4893 case Q_RADIO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004894 bpf_error(cstate, "'radio' modifier applied to %s", typestr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004895
4896 default:
4897 abort();
4898 }
4899 /* NOTREACHED */
4900}
JP Abgrall511eca32014-02-12 13:46:45 -08004901#endif
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004902
4903#ifndef INET6
4904static struct block *
4905gen_gateway(eaddr, alist, proto, dir)
4906 const u_char *eaddr;
4907 bpf_u_int32 **alist;
4908 int proto;
4909 int dir;
4910{
4911 struct block *b0, *b1, *tmp;
4912
4913 if (dir != 0)
Elliott Hughes965a4b52017-05-15 10:37:39 -07004914 bpf_error(cstate, "direction applied to 'gateway'");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004915
4916 switch (proto) {
4917 case Q_DEFAULT:
4918 case Q_IP:
4919 case Q_ARP:
4920 case Q_RARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004921 switch (cstate->linktype) {
JP Abgrall511eca32014-02-12 13:46:45 -08004922 case DLT_EN10MB:
4923 case DLT_NETANALYZER:
4924 case DLT_NETANALYZER_TRANSPARENT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004925 b1 = gen_prevlinkhdr_check(cstate);
4926 b0 = gen_ehostop(cstate, eaddr, Q_OR);
Elliott Hughesd8845d72015-10-19 18:07:04 -07004927 if (b1 != NULL)
4928 gen_and(b1, b0);
JP Abgrall511eca32014-02-12 13:46:45 -08004929 break;
4930 case DLT_FDDI:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004931 b0 = gen_fhostop(cstate, eaddr, Q_OR);
JP Abgrall511eca32014-02-12 13:46:45 -08004932 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004933 case DLT_IEEE802:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004934 b0 = gen_thostop(cstate, eaddr, Q_OR);
JP Abgrall511eca32014-02-12 13:46:45 -08004935 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004936 case DLT_IEEE802_11:
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004937 case DLT_PRISM_HEADER:
JP Abgrall511eca32014-02-12 13:46:45 -08004938 case DLT_IEEE802_11_RADIO_AVS:
4939 case DLT_IEEE802_11_RADIO:
4940 case DLT_PPI:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004941 b0 = gen_wlanhostop(cstate, eaddr, Q_OR);
JP Abgrall511eca32014-02-12 13:46:45 -08004942 break;
4943 case DLT_SUNATM:
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004944 /*
Elliott Hughesd8845d72015-10-19 18:07:04 -07004945 * This is LLC-multiplexed traffic; if it were
Elliott Hughes965a4b52017-05-15 10:37:39 -07004946 * LANE, cstate->linktype would have been set to
Elliott Hughesd8845d72015-10-19 18:07:04 -07004947 * DLT_EN10MB.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004948 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07004949 bpf_error(cstate,
Elliott Hughesd8845d72015-10-19 18:07:04 -07004950 "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
JP Abgrall511eca32014-02-12 13:46:45 -08004951 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004952 case DLT_IP_OVER_FC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004953 b0 = gen_ipfchostop(cstate, eaddr, Q_OR);
JP Abgrall511eca32014-02-12 13:46:45 -08004954 break;
4955 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004956 bpf_error(cstate,
JP Abgrall511eca32014-02-12 13:46:45 -08004957 "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
4958 }
Elliott Hughes965a4b52017-05-15 10:37:39 -07004959 b1 = gen_host(cstate, **alist++, 0xffffffff, proto, Q_OR, Q_HOST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004960 while (*alist) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07004961 tmp = gen_host(cstate, **alist++, 0xffffffff, proto, Q_OR,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004962 Q_HOST);
4963 gen_or(b1, tmp);
4964 b1 = tmp;
4965 }
4966 gen_not(b1);
4967 gen_and(b0, b1);
4968 return b1;
4969 }
Elliott Hughes965a4b52017-05-15 10:37:39 -07004970 bpf_error(cstate, "illegal modifier of 'gateway'");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004971 /* NOTREACHED */
4972}
4973#endif
4974
4975struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07004976gen_proto_abbrev(compiler_state_t *cstate, int proto)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004977{
4978 struct block *b0;
4979 struct block *b1;
4980
4981 switch (proto) {
4982
4983 case Q_SCTP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004984 b1 = gen_proto(cstate, IPPROTO_SCTP, Q_IP, Q_DEFAULT);
4985 b0 = gen_proto(cstate, IPPROTO_SCTP, Q_IPV6, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004986 gen_or(b0, b1);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004987 break;
4988
4989 case Q_TCP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004990 b1 = gen_proto(cstate, IPPROTO_TCP, Q_IP, Q_DEFAULT);
4991 b0 = gen_proto(cstate, IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004992 gen_or(b0, b1);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004993 break;
4994
4995 case Q_UDP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07004996 b1 = gen_proto(cstate, IPPROTO_UDP, Q_IP, Q_DEFAULT);
4997 b0 = gen_proto(cstate, IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004998 gen_or(b0, b1);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08004999 break;
5000
5001 case Q_ICMP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005002 b1 = gen_proto(cstate, IPPROTO_ICMP, Q_IP, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005003 break;
5004
5005#ifndef IPPROTO_IGMP
5006#define IPPROTO_IGMP 2
5007#endif
5008
5009 case Q_IGMP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005010 b1 = gen_proto(cstate, IPPROTO_IGMP, Q_IP, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005011 break;
5012
5013#ifndef IPPROTO_IGRP
5014#define IPPROTO_IGRP 9
5015#endif
5016 case Q_IGRP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005017 b1 = gen_proto(cstate, IPPROTO_IGRP, Q_IP, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005018 break;
5019
5020#ifndef IPPROTO_PIM
5021#define IPPROTO_PIM 103
5022#endif
5023
5024 case Q_PIM:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005025 b1 = gen_proto(cstate, IPPROTO_PIM, Q_IP, Q_DEFAULT);
5026 b0 = gen_proto(cstate, IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005027 gen_or(b0, b1);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005028 break;
5029
5030#ifndef IPPROTO_VRRP
5031#define IPPROTO_VRRP 112
5032#endif
5033
5034 case Q_VRRP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005035 b1 = gen_proto(cstate, IPPROTO_VRRP, Q_IP, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005036 break;
5037
JP Abgrall511eca32014-02-12 13:46:45 -08005038#ifndef IPPROTO_CARP
5039#define IPPROTO_CARP 112
5040#endif
5041
5042 case Q_CARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005043 b1 = gen_proto(cstate, IPPROTO_CARP, Q_IP, Q_DEFAULT);
JP Abgrall511eca32014-02-12 13:46:45 -08005044 break;
5045
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005046 case Q_IP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005047 b1 = gen_linktype(cstate, ETHERTYPE_IP);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005048 break;
5049
5050 case Q_ARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005051 b1 = gen_linktype(cstate, ETHERTYPE_ARP);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005052 break;
5053
5054 case Q_RARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005055 b1 = gen_linktype(cstate, ETHERTYPE_REVARP);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005056 break;
5057
5058 case Q_LINK:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005059 bpf_error(cstate, "link layer applied in wrong context");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005060
5061 case Q_ATALK:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005062 b1 = gen_linktype(cstate, ETHERTYPE_ATALK);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005063 break;
5064
5065 case Q_AARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005066 b1 = gen_linktype(cstate, ETHERTYPE_AARP);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005067 break;
5068
5069 case Q_DECNET:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005070 b1 = gen_linktype(cstate, ETHERTYPE_DN);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005071 break;
5072
5073 case Q_SCA:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005074 b1 = gen_linktype(cstate, ETHERTYPE_SCA);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005075 break;
5076
5077 case Q_LAT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005078 b1 = gen_linktype(cstate, ETHERTYPE_LAT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005079 break;
5080
5081 case Q_MOPDL:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005082 b1 = gen_linktype(cstate, ETHERTYPE_MOPDL);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005083 break;
5084
5085 case Q_MOPRC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005086 b1 = gen_linktype(cstate, ETHERTYPE_MOPRC);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005087 break;
5088
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005089 case Q_IPV6:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005090 b1 = gen_linktype(cstate, ETHERTYPE_IPV6);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005091 break;
5092
5093#ifndef IPPROTO_ICMPV6
5094#define IPPROTO_ICMPV6 58
5095#endif
5096 case Q_ICMPV6:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005097 b1 = gen_proto(cstate, IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005098 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005099
5100#ifndef IPPROTO_AH
5101#define IPPROTO_AH 51
5102#endif
5103 case Q_AH:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005104 b1 = gen_proto(cstate, IPPROTO_AH, Q_IP, Q_DEFAULT);
5105 b0 = gen_proto(cstate, IPPROTO_AH, Q_IPV6, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005106 gen_or(b0, b1);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005107 break;
5108
5109#ifndef IPPROTO_ESP
5110#define IPPROTO_ESP 50
5111#endif
5112 case Q_ESP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005113 b1 = gen_proto(cstate, IPPROTO_ESP, Q_IP, Q_DEFAULT);
5114 b0 = gen_proto(cstate, IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005115 gen_or(b0, b1);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005116 break;
5117
5118 case Q_ISO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005119 b1 = gen_linktype(cstate, LLCSAP_ISONS);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005120 break;
5121
5122 case Q_ESIS:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005123 b1 = gen_proto(cstate, ISO9542_ESIS, Q_ISO, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005124 break;
5125
5126 case Q_ISIS:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005127 b1 = gen_proto(cstate, ISO10589_ISIS, Q_ISO, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005128 break;
5129
5130 case Q_ISIS_L1: /* all IS-IS Level1 PDU-Types */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005131 b0 = gen_proto(cstate, ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
5132 b1 = gen_proto(cstate, ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005133 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07005134 b0 = gen_proto(cstate, ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005135 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07005136 b0 = gen_proto(cstate, ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005137 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07005138 b0 = gen_proto(cstate, ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005139 gen_or(b0, b1);
5140 break;
5141
5142 case Q_ISIS_L2: /* all IS-IS Level2 PDU-Types */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005143 b0 = gen_proto(cstate, ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
5144 b1 = gen_proto(cstate, ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005145 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07005146 b0 = gen_proto(cstate, ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005147 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07005148 b0 = gen_proto(cstate, ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005149 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07005150 b0 = gen_proto(cstate, ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005151 gen_or(b0, b1);
5152 break;
5153
5154 case Q_ISIS_IIH: /* all IS-IS Hello PDU-Types */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005155 b0 = gen_proto(cstate, ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
5156 b1 = gen_proto(cstate, ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005157 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07005158 b0 = gen_proto(cstate, ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005159 gen_or(b0, b1);
5160 break;
5161
5162 case Q_ISIS_LSP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005163 b0 = gen_proto(cstate, ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
5164 b1 = gen_proto(cstate, ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005165 gen_or(b0, b1);
5166 break;
5167
5168 case Q_ISIS_SNP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005169 b0 = gen_proto(cstate, ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
5170 b1 = gen_proto(cstate, ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005171 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07005172 b0 = gen_proto(cstate, ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005173 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07005174 b0 = gen_proto(cstate, ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005175 gen_or(b0, b1);
5176 break;
5177
5178 case Q_ISIS_CSNP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005179 b0 = gen_proto(cstate, ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
5180 b1 = gen_proto(cstate, ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005181 gen_or(b0, b1);
5182 break;
5183
5184 case Q_ISIS_PSNP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005185 b0 = gen_proto(cstate, ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
5186 b1 = gen_proto(cstate, ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005187 gen_or(b0, b1);
5188 break;
5189
5190 case Q_CLNP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005191 b1 = gen_proto(cstate, ISO8473_CLNP, Q_ISO, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005192 break;
5193
5194 case Q_STP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005195 b1 = gen_linktype(cstate, LLCSAP_8021D);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005196 break;
5197
5198 case Q_IPX:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005199 b1 = gen_linktype(cstate, LLCSAP_IPX);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005200 break;
5201
5202 case Q_NETBEUI:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005203 b1 = gen_linktype(cstate, LLCSAP_NETBEUI);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005204 break;
5205
5206 case Q_RADIO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005207 bpf_error(cstate, "'radio' is not a valid protocol type");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005208
5209 default:
5210 abort();
5211 }
5212 return b1;
5213}
5214
5215static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07005216gen_ipfrag(compiler_state_t *cstate)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005217{
5218 struct slist *s;
5219 struct block *b;
5220
JP Abgrall511eca32014-02-12 13:46:45 -08005221 /* not IPv4 frag other than the first frag */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005222 s = gen_load_a(cstate, OR_LINKPL, 6, BPF_H);
5223 b = new_block(cstate, JMP(BPF_JSET));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005224 b->s.k = 0x1fff;
5225 b->stmts = s;
5226 gen_not(b);
5227
5228 return b;
5229}
5230
5231/*
5232 * Generate a comparison to a port value in the transport-layer header
5233 * at the specified offset from the beginning of that header.
5234 *
5235 * XXX - this handles a variable-length prefix preceding the link-layer
5236 * header, such as the radiotap or AVS radio prefix, but doesn't handle
5237 * variable-length link-layer headers (such as Token Ring or 802.11
5238 * headers).
5239 */
5240static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07005241gen_portatom(compiler_state_t *cstate, int off, bpf_int32 v)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005242{
Elliott Hughes965a4b52017-05-15 10:37:39 -07005243 return gen_cmp(cstate, OR_TRAN_IPV4, off, BPF_H, v);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005244}
5245
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005246static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07005247gen_portatom6(compiler_state_t *cstate, int off, bpf_int32 v)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005248{
Elliott Hughes965a4b52017-05-15 10:37:39 -07005249 return gen_cmp(cstate, OR_TRAN_IPV6, off, BPF_H, v);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005250}
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005251
5252struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07005253gen_portop(compiler_state_t *cstate, int port, int proto, int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005254{
5255 struct block *b0, *b1, *tmp;
5256
JP Abgrall511eca32014-02-12 13:46:45 -08005257 /* ip proto 'proto' and not a fragment other than the first fragment */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005258 tmp = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
5259 b0 = gen_ipfrag(cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005260 gen_and(tmp, b0);
5261
5262 switch (dir) {
5263 case Q_SRC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005264 b1 = gen_portatom(cstate, 0, (bpf_int32)port);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005265 break;
5266
5267 case Q_DST:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005268 b1 = gen_portatom(cstate, 2, (bpf_int32)port);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005269 break;
5270
5271 case Q_OR:
5272 case Q_DEFAULT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005273 tmp = gen_portatom(cstate, 0, (bpf_int32)port);
5274 b1 = gen_portatom(cstate, 2, (bpf_int32)port);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005275 gen_or(tmp, b1);
5276 break;
5277
5278 case Q_AND:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005279 tmp = gen_portatom(cstate, 0, (bpf_int32)port);
5280 b1 = gen_portatom(cstate, 2, (bpf_int32)port);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005281 gen_and(tmp, b1);
5282 break;
5283
5284 default:
5285 abort();
5286 }
5287 gen_and(b0, b1);
5288
5289 return b1;
5290}
5291
5292static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07005293gen_port(compiler_state_t *cstate, int port, int ip_proto, int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005294{
5295 struct block *b0, *b1, *tmp;
5296
5297 /*
5298 * ether proto ip
5299 *
5300 * For FDDI, RFC 1188 says that SNAP encapsulation is used,
5301 * not LLC encapsulation with LLCSAP_IP.
5302 *
5303 * For IEEE 802 networks - which includes 802.5 token ring
5304 * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042
5305 * says that SNAP encapsulation is used, not LLC encapsulation
5306 * with LLCSAP_IP.
5307 *
5308 * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and
5309 * RFC 2225 say that SNAP encapsulation is used, not LLC
5310 * encapsulation with LLCSAP_IP.
5311 *
5312 * So we always check for ETHERTYPE_IP.
5313 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005314 b0 = gen_linktype(cstate, ETHERTYPE_IP);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005315
5316 switch (ip_proto) {
5317 case IPPROTO_UDP:
5318 case IPPROTO_TCP:
5319 case IPPROTO_SCTP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005320 b1 = gen_portop(cstate, port, ip_proto, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005321 break;
5322
5323 case PROTO_UNDEF:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005324 tmp = gen_portop(cstate, port, IPPROTO_TCP, dir);
5325 b1 = gen_portop(cstate, port, IPPROTO_UDP, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005326 gen_or(tmp, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07005327 tmp = gen_portop(cstate, port, IPPROTO_SCTP, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005328 gen_or(tmp, b1);
5329 break;
5330
5331 default:
5332 abort();
5333 }
5334 gen_and(b0, b1);
5335 return b1;
5336}
5337
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005338struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07005339gen_portop6(compiler_state_t *cstate, int port, int proto, int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005340{
5341 struct block *b0, *b1, *tmp;
5342
5343 /* ip6 proto 'proto' */
JP Abgrall511eca32014-02-12 13:46:45 -08005344 /* XXX - catch the first fragment of a fragmented packet? */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005345 b0 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005346
5347 switch (dir) {
5348 case Q_SRC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005349 b1 = gen_portatom6(cstate, 0, (bpf_int32)port);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005350 break;
5351
5352 case Q_DST:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005353 b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005354 break;
5355
5356 case Q_OR:
5357 case Q_DEFAULT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005358 tmp = gen_portatom6(cstate, 0, (bpf_int32)port);
5359 b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005360 gen_or(tmp, b1);
5361 break;
5362
5363 case Q_AND:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005364 tmp = gen_portatom6(cstate, 0, (bpf_int32)port);
5365 b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005366 gen_and(tmp, b1);
5367 break;
5368
5369 default:
5370 abort();
5371 }
5372 gen_and(b0, b1);
5373
5374 return b1;
5375}
5376
5377static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07005378gen_port6(compiler_state_t *cstate, int port, int ip_proto, int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005379{
5380 struct block *b0, *b1, *tmp;
5381
5382 /* link proto ip6 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005383 b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005384
5385 switch (ip_proto) {
5386 case IPPROTO_UDP:
5387 case IPPROTO_TCP:
5388 case IPPROTO_SCTP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005389 b1 = gen_portop6(cstate, port, ip_proto, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005390 break;
5391
5392 case PROTO_UNDEF:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005393 tmp = gen_portop6(cstate, port, IPPROTO_TCP, dir);
5394 b1 = gen_portop6(cstate, port, IPPROTO_UDP, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005395 gen_or(tmp, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07005396 tmp = gen_portop6(cstate, port, IPPROTO_SCTP, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005397 gen_or(tmp, b1);
5398 break;
5399
5400 default:
5401 abort();
5402 }
5403 gen_and(b0, b1);
5404 return b1;
5405}
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005406
5407/* gen_portrange code */
5408static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07005409gen_portrangeatom(compiler_state_t *cstate, int off, bpf_int32 v1,
5410 bpf_int32 v2)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005411{
5412 struct block *b1, *b2;
5413
5414 if (v1 > v2) {
5415 /*
5416 * Reverse the order of the ports, so v1 is the lower one.
5417 */
5418 bpf_int32 vtemp;
5419
5420 vtemp = v1;
5421 v1 = v2;
5422 v2 = vtemp;
5423 }
5424
Elliott Hughes965a4b52017-05-15 10:37:39 -07005425 b1 = gen_cmp_ge(cstate, OR_TRAN_IPV4, off, BPF_H, v1);
5426 b2 = gen_cmp_le(cstate, OR_TRAN_IPV4, off, BPF_H, v2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005427
Elliott Hughesd8845d72015-10-19 18:07:04 -07005428 gen_and(b1, b2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005429
5430 return b2;
5431}
5432
5433struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07005434gen_portrangeop(compiler_state_t *cstate, int port1, int port2, int proto,
5435 int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005436{
5437 struct block *b0, *b1, *tmp;
5438
JP Abgrall511eca32014-02-12 13:46:45 -08005439 /* ip proto 'proto' and not a fragment other than the first fragment */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005440 tmp = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
5441 b0 = gen_ipfrag(cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005442 gen_and(tmp, b0);
5443
5444 switch (dir) {
5445 case Q_SRC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005446 b1 = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005447 break;
5448
5449 case Q_DST:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005450 b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005451 break;
5452
5453 case Q_OR:
5454 case Q_DEFAULT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005455 tmp = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
5456 b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005457 gen_or(tmp, b1);
5458 break;
5459
5460 case Q_AND:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005461 tmp = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
5462 b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005463 gen_and(tmp, b1);
5464 break;
5465
5466 default:
5467 abort();
5468 }
5469 gen_and(b0, b1);
5470
5471 return b1;
5472}
5473
5474static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07005475gen_portrange(compiler_state_t *cstate, int port1, int port2, int ip_proto,
5476 int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005477{
5478 struct block *b0, *b1, *tmp;
5479
5480 /* link proto ip */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005481 b0 = gen_linktype(cstate, ETHERTYPE_IP);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005482
5483 switch (ip_proto) {
5484 case IPPROTO_UDP:
5485 case IPPROTO_TCP:
5486 case IPPROTO_SCTP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005487 b1 = gen_portrangeop(cstate, port1, port2, ip_proto, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005488 break;
5489
5490 case PROTO_UNDEF:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005491 tmp = gen_portrangeop(cstate, port1, port2, IPPROTO_TCP, dir);
5492 b1 = gen_portrangeop(cstate, port1, port2, IPPROTO_UDP, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005493 gen_or(tmp, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07005494 tmp = gen_portrangeop(cstate, port1, port2, IPPROTO_SCTP, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005495 gen_or(tmp, b1);
5496 break;
5497
5498 default:
5499 abort();
5500 }
5501 gen_and(b0, b1);
5502 return b1;
5503}
5504
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005505static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07005506gen_portrangeatom6(compiler_state_t *cstate, int off, bpf_int32 v1,
5507 bpf_int32 v2)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005508{
5509 struct block *b1, *b2;
5510
5511 if (v1 > v2) {
5512 /*
5513 * Reverse the order of the ports, so v1 is the lower one.
5514 */
5515 bpf_int32 vtemp;
5516
5517 vtemp = v1;
5518 v1 = v2;
5519 v2 = vtemp;
5520 }
5521
Elliott Hughes965a4b52017-05-15 10:37:39 -07005522 b1 = gen_cmp_ge(cstate, OR_TRAN_IPV6, off, BPF_H, v1);
5523 b2 = gen_cmp_le(cstate, OR_TRAN_IPV6, off, BPF_H, v2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005524
Elliott Hughesd8845d72015-10-19 18:07:04 -07005525 gen_and(b1, b2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005526
5527 return b2;
5528}
5529
5530struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07005531gen_portrangeop6(compiler_state_t *cstate, int port1, int port2, int proto,
5532 int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005533{
5534 struct block *b0, *b1, *tmp;
5535
5536 /* ip6 proto 'proto' */
JP Abgrall511eca32014-02-12 13:46:45 -08005537 /* XXX - catch the first fragment of a fragmented packet? */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005538 b0 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005539
5540 switch (dir) {
5541 case Q_SRC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005542 b1 = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005543 break;
5544
5545 case Q_DST:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005546 b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005547 break;
5548
5549 case Q_OR:
5550 case Q_DEFAULT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005551 tmp = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
5552 b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005553 gen_or(tmp, b1);
5554 break;
5555
5556 case Q_AND:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005557 tmp = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
5558 b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005559 gen_and(tmp, b1);
5560 break;
5561
5562 default:
5563 abort();
5564 }
5565 gen_and(b0, b1);
5566
5567 return b1;
5568}
5569
5570static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07005571gen_portrange6(compiler_state_t *cstate, int port1, int port2, int ip_proto,
5572 int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005573{
5574 struct block *b0, *b1, *tmp;
5575
5576 /* link proto ip6 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005577 b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005578
5579 switch (ip_proto) {
5580 case IPPROTO_UDP:
5581 case IPPROTO_TCP:
5582 case IPPROTO_SCTP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005583 b1 = gen_portrangeop6(cstate, port1, port2, ip_proto, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005584 break;
5585
5586 case PROTO_UNDEF:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005587 tmp = gen_portrangeop6(cstate, port1, port2, IPPROTO_TCP, dir);
5588 b1 = gen_portrangeop6(cstate, port1, port2, IPPROTO_UDP, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005589 gen_or(tmp, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07005590 tmp = gen_portrangeop6(cstate, port1, port2, IPPROTO_SCTP, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005591 gen_or(tmp, b1);
5592 break;
5593
5594 default:
5595 abort();
5596 }
5597 gen_and(b0, b1);
5598 return b1;
5599}
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005600
5601static int
Elliott Hughes965a4b52017-05-15 10:37:39 -07005602lookup_proto(compiler_state_t *cstate, const char *name, int proto)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005603{
5604 register int v;
5605
5606 switch (proto) {
5607
5608 case Q_DEFAULT:
5609 case Q_IP:
5610 case Q_IPV6:
5611 v = pcap_nametoproto(name);
5612 if (v == PROTO_UNDEF)
Elliott Hughes965a4b52017-05-15 10:37:39 -07005613 bpf_error(cstate, "unknown ip proto '%s'", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005614 break;
5615
5616 case Q_LINK:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005617 /* XXX should look up h/w protocol type based on cstate->linktype */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005618 v = pcap_nametoeproto(name);
5619 if (v == PROTO_UNDEF) {
5620 v = pcap_nametollc(name);
5621 if (v == PROTO_UNDEF)
Elliott Hughes965a4b52017-05-15 10:37:39 -07005622 bpf_error(cstate, "unknown ether proto '%s'", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005623 }
5624 break;
5625
5626 case Q_ISO:
5627 if (strcmp(name, "esis") == 0)
5628 v = ISO9542_ESIS;
5629 else if (strcmp(name, "isis") == 0)
5630 v = ISO10589_ISIS;
5631 else if (strcmp(name, "clnp") == 0)
5632 v = ISO8473_CLNP;
5633 else
Elliott Hughes965a4b52017-05-15 10:37:39 -07005634 bpf_error(cstate, "unknown osi proto '%s'", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005635 break;
5636
5637 default:
5638 v = PROTO_UNDEF;
5639 break;
5640 }
5641 return v;
5642}
5643
5644#if 0
5645struct stmt *
5646gen_joinsp(s, n)
5647 struct stmt **s;
5648 int n;
5649{
5650 return NULL;
5651}
5652#endif
5653
5654static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07005655gen_protochain(compiler_state_t *cstate, int v, int proto, int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005656{
5657#ifdef NO_PROTOCHAIN
Elliott Hughes965a4b52017-05-15 10:37:39 -07005658 return gen_proto(cstate, v, proto, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005659#else
5660 struct block *b0, *b;
5661 struct slist *s[100];
5662 int fix2, fix3, fix4, fix5;
5663 int ahcheck, again, end;
5664 int i, max;
Elliott Hughes965a4b52017-05-15 10:37:39 -07005665 int reg2 = alloc_reg(cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005666
5667 memset(s, 0, sizeof(s));
Elliott Hughes965a4b52017-05-15 10:37:39 -07005668 fix3 = fix4 = fix5 = 0;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005669
5670 switch (proto) {
5671 case Q_IP:
5672 case Q_IPV6:
5673 break;
5674 case Q_DEFAULT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005675 b0 = gen_protochain(cstate, v, Q_IP, dir);
5676 b = gen_protochain(cstate, v, Q_IPV6, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005677 gen_or(b0, b);
5678 return b;
5679 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005680 bpf_error(cstate, "bad protocol applied for 'protochain'");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005681 /*NOTREACHED*/
5682 }
5683
5684 /*
JP Abgrall511eca32014-02-12 13:46:45 -08005685 * We don't handle variable-length prefixes before the link-layer
5686 * header, or variable-length link-layer headers, here yet.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005687 * We might want to add BPF instructions to do the protochain
5688 * work, to simplify that and, on platforms that have a BPF
5689 * interpreter with the new instructions, let the filtering
5690 * be done in the kernel. (We already require a modified BPF
5691 * engine to do the protochain stuff, to support backward
5692 * branches, and backward branch support is unlikely to appear
5693 * in kernel BPF engines.)
5694 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005695 if (cstate->off_linkpl.is_variable)
5696 bpf_error(cstate, "'protochain' not supported with variable length headers");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005697
Elliott Hughes965a4b52017-05-15 10:37:39 -07005698 cstate->no_optimize = 1; /*this code is not compatible with optimzer yet */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005699
5700 /*
5701 * s[0] is a dummy entry to protect other BPF insn from damage
5702 * by s[fix] = foo with uninitialized variable "fix". It is somewhat
5703 * hard to find interdependency made by jump table fixup.
5704 */
5705 i = 0;
Elliott Hughes965a4b52017-05-15 10:37:39 -07005706 s[i] = new_stmt(cstate, 0); /*dummy*/
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005707 i++;
5708
5709 switch (proto) {
5710 case Q_IP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005711 b0 = gen_linktype(cstate, ETHERTYPE_IP);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005712
5713 /* A = ip->ip_p */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005714 s[i] = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
5715 s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 9;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005716 i++;
5717 /* X = ip->ip_hl << 2 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005718 s[i] = new_stmt(cstate, BPF_LDX|BPF_MSH|BPF_B);
5719 s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005720 i++;
5721 break;
JP Abgrall511eca32014-02-12 13:46:45 -08005722
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005723 case Q_IPV6:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005724 b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005725
5726 /* A = ip6->ip_nxt */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005727 s[i] = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
5728 s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 6;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005729 i++;
5730 /* X = sizeof(struct ip6_hdr) */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005731 s[i] = new_stmt(cstate, BPF_LDX|BPF_IMM);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005732 s[i]->s.k = 40;
5733 i++;
5734 break;
JP Abgrall511eca32014-02-12 13:46:45 -08005735
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005736 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005737 bpf_error(cstate, "unsupported proto to gen_protochain");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005738 /*NOTREACHED*/
5739 }
5740
5741 /* again: if (A == v) goto end; else fall through; */
5742 again = i;
Elliott Hughes965a4b52017-05-15 10:37:39 -07005743 s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005744 s[i]->s.k = v;
5745 s[i]->s.jt = NULL; /*later*/
5746 s[i]->s.jf = NULL; /*update in next stmt*/
5747 fix5 = i;
5748 i++;
5749
5750#ifndef IPPROTO_NONE
5751#define IPPROTO_NONE 59
5752#endif
5753 /* if (A == IPPROTO_NONE) goto end */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005754 s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005755 s[i]->s.jt = NULL; /*later*/
5756 s[i]->s.jf = NULL; /*update in next stmt*/
5757 s[i]->s.k = IPPROTO_NONE;
5758 s[fix5]->s.jf = s[i];
5759 fix2 = i;
5760 i++;
5761
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005762 if (proto == Q_IPV6) {
5763 int v6start, v6end, v6advance, j;
5764
5765 v6start = i;
5766 /* if (A == IPPROTO_HOPOPTS) goto v6advance */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005767 s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005768 s[i]->s.jt = NULL; /*later*/
5769 s[i]->s.jf = NULL; /*update in next stmt*/
5770 s[i]->s.k = IPPROTO_HOPOPTS;
5771 s[fix2]->s.jf = s[i];
5772 i++;
5773 /* if (A == IPPROTO_DSTOPTS) goto v6advance */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005774 s[i - 1]->s.jf = s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005775 s[i]->s.jt = NULL; /*later*/
5776 s[i]->s.jf = NULL; /*update in next stmt*/
5777 s[i]->s.k = IPPROTO_DSTOPTS;
5778 i++;
5779 /* if (A == IPPROTO_ROUTING) goto v6advance */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005780 s[i - 1]->s.jf = s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005781 s[i]->s.jt = NULL; /*later*/
5782 s[i]->s.jf = NULL; /*update in next stmt*/
5783 s[i]->s.k = IPPROTO_ROUTING;
5784 i++;
5785 /* if (A == IPPROTO_FRAGMENT) goto v6advance; else goto ahcheck; */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005786 s[i - 1]->s.jf = s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005787 s[i]->s.jt = NULL; /*later*/
5788 s[i]->s.jf = NULL; /*later*/
5789 s[i]->s.k = IPPROTO_FRAGMENT;
5790 fix3 = i;
5791 v6end = i;
5792 i++;
5793
5794 /* v6advance: */
5795 v6advance = i;
5796
5797 /*
5798 * in short,
JP Abgrall511eca32014-02-12 13:46:45 -08005799 * A = P[X + packet head];
5800 * X = X + (P[X + packet head + 1] + 1) * 8;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005801 */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005802 /* A = P[X + packet head] */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005803 s[i] = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
5804 s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005805 i++;
5806 /* MEM[reg2] = A */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005807 s[i] = new_stmt(cstate, BPF_ST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005808 s[i]->s.k = reg2;
5809 i++;
JP Abgrall511eca32014-02-12 13:46:45 -08005810 /* A = P[X + packet head + 1]; */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005811 s[i] = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
5812 s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 1;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005813 i++;
5814 /* A += 1 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005815 s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005816 s[i]->s.k = 1;
5817 i++;
5818 /* A *= 8 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005819 s[i] = new_stmt(cstate, BPF_ALU|BPF_MUL|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005820 s[i]->s.k = 8;
5821 i++;
JP Abgrall511eca32014-02-12 13:46:45 -08005822 /* A += X */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005823 s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X);
JP Abgrall511eca32014-02-12 13:46:45 -08005824 s[i]->s.k = 0;
5825 i++;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005826 /* X = A; */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005827 s[i] = new_stmt(cstate, BPF_MISC|BPF_TAX);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005828 i++;
5829 /* A = MEM[reg2] */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005830 s[i] = new_stmt(cstate, BPF_LD|BPF_MEM);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005831 s[i]->s.k = reg2;
5832 i++;
5833
5834 /* goto again; (must use BPF_JA for backward jump) */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005835 s[i] = new_stmt(cstate, BPF_JMP|BPF_JA);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005836 s[i]->s.k = again - i - 1;
5837 s[i - 1]->s.jf = s[i];
5838 i++;
5839
5840 /* fixup */
5841 for (j = v6start; j <= v6end; j++)
5842 s[j]->s.jt = s[v6advance];
JP Abgrall511eca32014-02-12 13:46:45 -08005843 } else {
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005844 /* nop */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005845 s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005846 s[i]->s.k = 0;
5847 s[fix2]->s.jf = s[i];
5848 i++;
5849 }
5850
5851 /* ahcheck: */
5852 ahcheck = i;
5853 /* if (A == IPPROTO_AH) then fall through; else goto end; */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005854 s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005855 s[i]->s.jt = NULL; /*later*/
5856 s[i]->s.jf = NULL; /*later*/
5857 s[i]->s.k = IPPROTO_AH;
5858 if (fix3)
5859 s[fix3]->s.jf = s[ahcheck];
5860 fix4 = i;
5861 i++;
5862
5863 /*
5864 * in short,
5865 * A = P[X];
5866 * X = X + (P[X + 1] + 2) * 4;
5867 */
5868 /* A = X */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005869 s[i - 1]->s.jt = s[i] = new_stmt(cstate, BPF_MISC|BPF_TXA);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005870 i++;
5871 /* A = P[X + packet head]; */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005872 s[i] = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
5873 s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005874 i++;
5875 /* MEM[reg2] = A */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005876 s[i] = new_stmt(cstate, BPF_ST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005877 s[i]->s.k = reg2;
5878 i++;
5879 /* A = X */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005880 s[i - 1]->s.jt = s[i] = new_stmt(cstate, BPF_MISC|BPF_TXA);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005881 i++;
5882 /* A += 1 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005883 s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005884 s[i]->s.k = 1;
5885 i++;
5886 /* X = A */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005887 s[i] = new_stmt(cstate, BPF_MISC|BPF_TAX);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005888 i++;
5889 /* A = P[X + packet head] */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005890 s[i] = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
5891 s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005892 i++;
5893 /* A += 2 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005894 s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005895 s[i]->s.k = 2;
5896 i++;
5897 /* A *= 4 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005898 s[i] = new_stmt(cstate, BPF_ALU|BPF_MUL|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005899 s[i]->s.k = 4;
5900 i++;
5901 /* X = A; */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005902 s[i] = new_stmt(cstate, BPF_MISC|BPF_TAX);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005903 i++;
5904 /* A = MEM[reg2] */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005905 s[i] = new_stmt(cstate, BPF_LD|BPF_MEM);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005906 s[i]->s.k = reg2;
5907 i++;
5908
5909 /* goto again; (must use BPF_JA for backward jump) */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005910 s[i] = new_stmt(cstate, BPF_JMP|BPF_JA);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005911 s[i]->s.k = again - i - 1;
5912 i++;
5913
5914 /* end: nop */
5915 end = i;
Elliott Hughes965a4b52017-05-15 10:37:39 -07005916 s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005917 s[i]->s.k = 0;
5918 s[fix2]->s.jt = s[end];
5919 s[fix4]->s.jf = s[end];
5920 s[fix5]->s.jt = s[end];
5921 i++;
5922
5923 /*
5924 * make slist chain
5925 */
5926 max = i;
5927 for (i = 0; i < max - 1; i++)
5928 s[i]->next = s[i + 1];
5929 s[max - 1]->next = NULL;
5930
5931 /*
5932 * emit final check
5933 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005934 b = new_block(cstate, JMP(BPF_JEQ));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005935 b->stmts = s[1]; /*remember, s[0] is dummy*/
5936 b->s.k = v;
5937
Elliott Hughes965a4b52017-05-15 10:37:39 -07005938 free_reg(cstate, reg2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005939
5940 gen_and(b0, b);
5941 return b;
5942#endif
5943}
5944
JP Abgrall511eca32014-02-12 13:46:45 -08005945static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07005946gen_check_802_11_data_frame(compiler_state_t *cstate)
JP Abgrall511eca32014-02-12 13:46:45 -08005947{
5948 struct slist *s;
5949 struct block *b0, *b1;
5950
5951 /*
5952 * A data frame has the 0x08 bit (b3) in the frame control field set
5953 * and the 0x04 bit (b2) clear.
5954 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07005955 s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
5956 b0 = new_block(cstate, JMP(BPF_JSET));
JP Abgrall511eca32014-02-12 13:46:45 -08005957 b0->s.k = 0x08;
5958 b0->stmts = s;
Elliott Hughesd8845d72015-10-19 18:07:04 -07005959
Elliott Hughes965a4b52017-05-15 10:37:39 -07005960 s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
5961 b1 = new_block(cstate, JMP(BPF_JSET));
JP Abgrall511eca32014-02-12 13:46:45 -08005962 b1->s.k = 0x04;
5963 b1->stmts = s;
5964 gen_not(b1);
5965
5966 gen_and(b1, b0);
5967
5968 return b0;
5969}
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005970
5971/*
5972 * Generate code that checks whether the packet is a packet for protocol
5973 * <proto> and whether the type field in that protocol's header has
5974 * the value <v>, e.g. if <proto> is Q_IP, it checks whether it's an
5975 * IP packet and checks the protocol number in the IP header against <v>.
5976 *
5977 * If <proto> is Q_DEFAULT, i.e. just "proto" was specified, it checks
5978 * against Q_IP and Q_IPV6.
5979 */
5980static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07005981gen_proto(compiler_state_t *cstate, int v, int proto, int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005982{
5983 struct block *b0, *b1;
JP Abgrall511eca32014-02-12 13:46:45 -08005984#ifndef CHASE_CHAIN
5985 struct block *b2;
5986#endif
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005987
5988 if (dir != Q_DEFAULT)
Elliott Hughes965a4b52017-05-15 10:37:39 -07005989 bpf_error(cstate, "direction applied to 'proto'");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005990
5991 switch (proto) {
5992 case Q_DEFAULT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07005993 b0 = gen_proto(cstate, v, Q_IP, dir);
5994 b1 = gen_proto(cstate, v, Q_IPV6, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005995 gen_or(b0, b1);
5996 return b1;
JP Abgrall511eca32014-02-12 13:46:45 -08005997
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08005998 case Q_IP:
5999 /*
6000 * For FDDI, RFC 1188 says that SNAP encapsulation is used,
6001 * not LLC encapsulation with LLCSAP_IP.
6002 *
6003 * For IEEE 802 networks - which includes 802.5 token ring
6004 * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042
6005 * says that SNAP encapsulation is used, not LLC encapsulation
6006 * with LLCSAP_IP.
6007 *
6008 * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and
6009 * RFC 2225 say that SNAP encapsulation is used, not LLC
6010 * encapsulation with LLCSAP_IP.
6011 *
6012 * So we always check for ETHERTYPE_IP.
6013 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006014 b0 = gen_linktype(cstate, ETHERTYPE_IP);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006015#ifndef CHASE_CHAIN
Elliott Hughes965a4b52017-05-15 10:37:39 -07006016 b1 = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, (bpf_int32)v);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006017#else
Elliott Hughes965a4b52017-05-15 10:37:39 -07006018 b1 = gen_protochain(cstate, v, Q_IP);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006019#endif
6020 gen_and(b0, b1);
6021 return b1;
6022
6023 case Q_ISO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006024 switch (cstate->linktype) {
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006025
6026 case DLT_FRELAY:
6027 /*
6028 * Frame Relay packets typically have an OSI
Elliott Hughes965a4b52017-05-15 10:37:39 -07006029 * NLPID at the beginning; "gen_linktype(cstate, LLCSAP_ISONS)"
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006030 * generates code to check for all the OSI
6031 * NLPIDs, so calling it and then adding a check
6032 * for the particular NLPID for which we're
6033 * looking is bogus, as we can just check for
6034 * the NLPID.
6035 *
6036 * What we check for is the NLPID and a frame
6037 * control field value of UI, i.e. 0x03 followed
6038 * by the NLPID.
6039 *
6040 * XXX - assumes a 2-byte Frame Relay header with
6041 * DLCI and flags. What if the address is longer?
6042 *
6043 * XXX - what about SNAP-encapsulated frames?
6044 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006045 return gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | v);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006046 /*NOTREACHED*/
6047 break;
6048
6049 case DLT_C_HDLC:
6050 /*
6051 * Cisco uses an Ethertype lookalike - for OSI,
6052 * it's 0xfefe.
6053 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006054 b0 = gen_linktype(cstate, LLCSAP_ISONS<<8 | LLCSAP_ISONS);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006055 /* OSI in C-HDLC is stuffed with a fudge byte */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006056 b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 1, BPF_B, (long)v);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006057 gen_and(b0, b1);
6058 return b1;
6059
6060 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006061 b0 = gen_linktype(cstate, LLCSAP_ISONS);
6062 b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 0, BPF_B, (long)v);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006063 gen_and(b0, b1);
6064 return b1;
6065 }
6066
6067 case Q_ISIS:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006068 b0 = gen_proto(cstate, ISO10589_ISIS, Q_ISO, Q_DEFAULT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006069 /*
6070 * 4 is the offset of the PDU type relative to the IS-IS
6071 * header.
6072 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006073 b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 4, BPF_B, (long)v);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006074 gen_and(b0, b1);
6075 return b1;
6076
6077 case Q_ARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006078 bpf_error(cstate, "arp does not encapsulate another protocol");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006079 /* NOTREACHED */
6080
6081 case Q_RARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006082 bpf_error(cstate, "rarp does not encapsulate another protocol");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006083 /* NOTREACHED */
6084
6085 case Q_ATALK:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006086 bpf_error(cstate, "atalk encapsulation is not specifiable");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006087 /* NOTREACHED */
6088
6089 case Q_DECNET:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006090 bpf_error(cstate, "decnet encapsulation is not specifiable");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006091 /* NOTREACHED */
6092
6093 case Q_SCA:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006094 bpf_error(cstate, "sca does not encapsulate another protocol");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006095 /* NOTREACHED */
6096
6097 case Q_LAT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006098 bpf_error(cstate, "lat does not encapsulate another protocol");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006099 /* NOTREACHED */
6100
6101 case Q_MOPRC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006102 bpf_error(cstate, "moprc does not encapsulate another protocol");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006103 /* NOTREACHED */
6104
6105 case Q_MOPDL:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006106 bpf_error(cstate, "mopdl does not encapsulate another protocol");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006107 /* NOTREACHED */
6108
6109 case Q_LINK:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006110 return gen_linktype(cstate, v);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006111
6112 case Q_UDP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006113 bpf_error(cstate, "'udp proto' is bogus");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006114 /* NOTREACHED */
6115
6116 case Q_TCP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006117 bpf_error(cstate, "'tcp proto' is bogus");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006118 /* NOTREACHED */
6119
6120 case Q_SCTP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006121 bpf_error(cstate, "'sctp proto' is bogus");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006122 /* NOTREACHED */
6123
6124 case Q_ICMP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006125 bpf_error(cstate, "'icmp proto' is bogus");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006126 /* NOTREACHED */
6127
6128 case Q_IGMP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006129 bpf_error(cstate, "'igmp proto' is bogus");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006130 /* NOTREACHED */
6131
6132 case Q_IGRP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006133 bpf_error(cstate, "'igrp proto' is bogus");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006134 /* NOTREACHED */
6135
6136 case Q_PIM:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006137 bpf_error(cstate, "'pim proto' is bogus");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006138 /* NOTREACHED */
6139
6140 case Q_VRRP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006141 bpf_error(cstate, "'vrrp proto' is bogus");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006142 /* NOTREACHED */
6143
JP Abgrall511eca32014-02-12 13:46:45 -08006144 case Q_CARP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006145 bpf_error(cstate, "'carp proto' is bogus");
JP Abgrall511eca32014-02-12 13:46:45 -08006146 /* NOTREACHED */
6147
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006148 case Q_IPV6:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006149 b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006150#ifndef CHASE_CHAIN
JP Abgrall511eca32014-02-12 13:46:45 -08006151 /*
6152 * Also check for a fragment header before the final
6153 * header.
6154 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006155 b2 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, IPPROTO_FRAGMENT);
6156 b1 = gen_cmp(cstate, OR_LINKPL, 40, BPF_B, (bpf_int32)v);
JP Abgrall511eca32014-02-12 13:46:45 -08006157 gen_and(b2, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07006158 b2 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, (bpf_int32)v);
JP Abgrall511eca32014-02-12 13:46:45 -08006159 gen_or(b2, b1);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006160#else
Elliott Hughes965a4b52017-05-15 10:37:39 -07006161 b1 = gen_protochain(cstate, v, Q_IPV6);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006162#endif
6163 gen_and(b0, b1);
6164 return b1;
6165
6166 case Q_ICMPV6:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006167 bpf_error(cstate, "'icmp6 proto' is bogus");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006168
6169 case Q_AH:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006170 bpf_error(cstate, "'ah proto' is bogus");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006171
6172 case Q_ESP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006173 bpf_error(cstate, "'ah proto' is bogus");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006174
6175 case Q_STP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006176 bpf_error(cstate, "'stp proto' is bogus");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006177
6178 case Q_IPX:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006179 bpf_error(cstate, "'ipx proto' is bogus");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006180
6181 case Q_NETBEUI:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006182 bpf_error(cstate, "'netbeui proto' is bogus");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006183
6184 case Q_RADIO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006185 bpf_error(cstate, "'radio proto' is bogus");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006186
6187 default:
6188 abort();
6189 /* NOTREACHED */
6190 }
6191 /* NOTREACHED */
6192}
6193
6194struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07006195gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006196{
6197 int proto = q.proto;
6198 int dir = q.dir;
6199 int tproto;
6200 u_char *eaddr;
6201 bpf_u_int32 mask, addr;
6202#ifndef INET6
6203 bpf_u_int32 **alist;
6204#else
6205 int tproto6;
6206 struct sockaddr_in *sin4;
6207 struct sockaddr_in6 *sin6;
6208 struct addrinfo *res, *res0;
6209 struct in6_addr mask128;
6210#endif /*INET6*/
6211 struct block *b, *tmp;
6212 int port, real_proto;
6213 int port1, port2;
6214
6215 switch (q.addr) {
6216
6217 case Q_NET:
6218 addr = pcap_nametonetaddr(name);
6219 if (addr == 0)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006220 bpf_error(cstate, "unknown network '%s'", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006221 /* Left justify network addr and calculate its network mask */
6222 mask = 0xffffffff;
6223 while (addr && (addr & 0xff000000) == 0) {
6224 addr <<= 8;
6225 mask <<= 8;
6226 }
Elliott Hughes965a4b52017-05-15 10:37:39 -07006227 return gen_host(cstate, addr, mask, proto, dir, q.addr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006228
6229 case Q_DEFAULT:
6230 case Q_HOST:
6231 if (proto == Q_LINK) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07006232 switch (cstate->linktype) {
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006233
6234 case DLT_EN10MB:
JP Abgrall511eca32014-02-12 13:46:45 -08006235 case DLT_NETANALYZER:
6236 case DLT_NETANALYZER_TRANSPARENT:
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006237 eaddr = pcap_ether_hostton(name);
6238 if (eaddr == NULL)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006239 bpf_error(cstate,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006240 "unknown ether host '%s'", name);
Elliott Hughes965a4b52017-05-15 10:37:39 -07006241 tmp = gen_prevlinkhdr_check(cstate);
6242 b = gen_ehostop(cstate, eaddr, dir);
Elliott Hughesd8845d72015-10-19 18:07:04 -07006243 if (tmp != NULL)
6244 gen_and(tmp, b);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006245 free(eaddr);
6246 return b;
6247
6248 case DLT_FDDI:
6249 eaddr = pcap_ether_hostton(name);
6250 if (eaddr == NULL)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006251 bpf_error(cstate,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006252 "unknown FDDI host '%s'", name);
Elliott Hughes965a4b52017-05-15 10:37:39 -07006253 b = gen_fhostop(cstate, eaddr, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006254 free(eaddr);
6255 return b;
6256
6257 case DLT_IEEE802:
6258 eaddr = pcap_ether_hostton(name);
6259 if (eaddr == NULL)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006260 bpf_error(cstate,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006261 "unknown token ring host '%s'", name);
Elliott Hughes965a4b52017-05-15 10:37:39 -07006262 b = gen_thostop(cstate, eaddr, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006263 free(eaddr);
6264 return b;
6265
6266 case DLT_IEEE802_11:
JP Abgrall511eca32014-02-12 13:46:45 -08006267 case DLT_PRISM_HEADER:
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006268 case DLT_IEEE802_11_RADIO_AVS:
6269 case DLT_IEEE802_11_RADIO:
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006270 case DLT_PPI:
6271 eaddr = pcap_ether_hostton(name);
6272 if (eaddr == NULL)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006273 bpf_error(cstate,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006274 "unknown 802.11 host '%s'", name);
Elliott Hughes965a4b52017-05-15 10:37:39 -07006275 b = gen_wlanhostop(cstate, eaddr, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006276 free(eaddr);
6277 return b;
6278
6279 case DLT_IP_OVER_FC:
6280 eaddr = pcap_ether_hostton(name);
6281 if (eaddr == NULL)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006282 bpf_error(cstate,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006283 "unknown Fibre Channel host '%s'", name);
Elliott Hughes965a4b52017-05-15 10:37:39 -07006284 b = gen_ipfchostop(cstate, eaddr, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006285 free(eaddr);
6286 return b;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006287 }
6288
Elliott Hughes965a4b52017-05-15 10:37:39 -07006289 bpf_error(cstate, "only ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel supports link-level host name");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006290 } else if (proto == Q_DECNET) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07006291 unsigned short dn_addr;
6292
6293 if (!__pcap_nametodnaddr(name, &dn_addr)) {
6294#ifdef DECNETLIB
6295 bpf_error(cstate, "unknown decnet host name '%s'\n", name);
6296#else
6297 bpf_error(cstate, "decnet name support not included, '%s' cannot be translated\n",
6298 name);
6299#endif
6300 }
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006301 /*
6302 * I don't think DECNET hosts can be multihomed, so
6303 * there is no need to build up a list of addresses
6304 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006305 return (gen_host(cstate, dn_addr, 0, proto, dir, q.addr));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006306 } else {
6307#ifndef INET6
6308 alist = pcap_nametoaddr(name);
6309 if (alist == NULL || *alist == NULL)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006310 bpf_error(cstate, "unknown host '%s'", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006311 tproto = proto;
Elliott Hughes965a4b52017-05-15 10:37:39 -07006312 if (cstate->off_linktype.constant_part == OFFSET_NOT_SET &&
Elliott Hughesd8845d72015-10-19 18:07:04 -07006313 tproto == Q_DEFAULT)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006314 tproto = Q_IP;
Elliott Hughes965a4b52017-05-15 10:37:39 -07006315 b = gen_host(cstate, **alist++, 0xffffffff, tproto, dir, q.addr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006316 while (*alist) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07006317 tmp = gen_host(cstate, **alist++, 0xffffffff,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006318 tproto, dir, q.addr);
6319 gen_or(b, tmp);
6320 b = tmp;
6321 }
6322 return b;
6323#else
6324 memset(&mask128, 0xff, sizeof(mask128));
6325 res0 = res = pcap_nametoaddrinfo(name);
6326 if (res == NULL)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006327 bpf_error(cstate, "unknown host '%s'", name);
6328 cstate->ai = res;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006329 b = tmp = NULL;
6330 tproto = tproto6 = proto;
Elliott Hughes965a4b52017-05-15 10:37:39 -07006331 if (cstate->off_linktype.constant_part == OFFSET_NOT_SET &&
Elliott Hughesd8845d72015-10-19 18:07:04 -07006332 tproto == Q_DEFAULT) {
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006333 tproto = Q_IP;
6334 tproto6 = Q_IPV6;
6335 }
6336 for (res = res0; res; res = res->ai_next) {
6337 switch (res->ai_family) {
6338 case AF_INET:
6339 if (tproto == Q_IPV6)
6340 continue;
6341
6342 sin4 = (struct sockaddr_in *)
6343 res->ai_addr;
Elliott Hughes965a4b52017-05-15 10:37:39 -07006344 tmp = gen_host(cstate, ntohl(sin4->sin_addr.s_addr),
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006345 0xffffffff, tproto, dir, q.addr);
6346 break;
6347 case AF_INET6:
6348 if (tproto6 == Q_IP)
6349 continue;
6350
6351 sin6 = (struct sockaddr_in6 *)
6352 res->ai_addr;
Elliott Hughes965a4b52017-05-15 10:37:39 -07006353 tmp = gen_host6(cstate, &sin6->sin6_addr,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006354 &mask128, tproto6, dir, q.addr);
6355 break;
6356 default:
6357 continue;
6358 }
6359 if (b)
6360 gen_or(b, tmp);
6361 b = tmp;
6362 }
Elliott Hughes965a4b52017-05-15 10:37:39 -07006363 cstate->ai = NULL;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006364 freeaddrinfo(res0);
6365 if (b == NULL) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07006366 bpf_error(cstate, "unknown host '%s'%s", name,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006367 (proto == Q_DEFAULT)
6368 ? ""
6369 : " for specified address family");
6370 }
6371 return b;
6372#endif /*INET6*/
6373 }
6374
6375 case Q_PORT:
6376 if (proto != Q_DEFAULT &&
6377 proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006378 bpf_error(cstate, "illegal qualifier of 'port'");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006379 if (pcap_nametoport(name, &port, &real_proto) == 0)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006380 bpf_error(cstate, "unknown port '%s'", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006381 if (proto == Q_UDP) {
6382 if (real_proto == IPPROTO_TCP)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006383 bpf_error(cstate, "port '%s' is tcp", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006384 else if (real_proto == IPPROTO_SCTP)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006385 bpf_error(cstate, "port '%s' is sctp", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006386 else
6387 /* override PROTO_UNDEF */
6388 real_proto = IPPROTO_UDP;
6389 }
6390 if (proto == Q_TCP) {
6391 if (real_proto == IPPROTO_UDP)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006392 bpf_error(cstate, "port '%s' is udp", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006393
6394 else if (real_proto == IPPROTO_SCTP)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006395 bpf_error(cstate, "port '%s' is sctp", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006396 else
6397 /* override PROTO_UNDEF */
6398 real_proto = IPPROTO_TCP;
6399 }
6400 if (proto == Q_SCTP) {
6401 if (real_proto == IPPROTO_UDP)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006402 bpf_error(cstate, "port '%s' is udp", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006403
6404 else if (real_proto == IPPROTO_TCP)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006405 bpf_error(cstate, "port '%s' is tcp", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006406 else
6407 /* override PROTO_UNDEF */
6408 real_proto = IPPROTO_SCTP;
6409 }
JP Abgrall511eca32014-02-12 13:46:45 -08006410 if (port < 0)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006411 bpf_error(cstate, "illegal port number %d < 0", port);
JP Abgrall511eca32014-02-12 13:46:45 -08006412 if (port > 65535)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006413 bpf_error(cstate, "illegal port number %d > 65535", port);
6414 b = gen_port(cstate, port, real_proto, dir);
6415 gen_or(gen_port6(cstate, port, real_proto, dir), b);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006416 return b;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006417
6418 case Q_PORTRANGE:
6419 if (proto != Q_DEFAULT &&
6420 proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006421 bpf_error(cstate, "illegal qualifier of 'portrange'");
Elliott Hughesd8845d72015-10-19 18:07:04 -07006422 if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006423 bpf_error(cstate, "unknown port in range '%s'", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006424 if (proto == Q_UDP) {
6425 if (real_proto == IPPROTO_TCP)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006426 bpf_error(cstate, "port in range '%s' is tcp", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006427 else if (real_proto == IPPROTO_SCTP)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006428 bpf_error(cstate, "port in range '%s' is sctp", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006429 else
6430 /* override PROTO_UNDEF */
6431 real_proto = IPPROTO_UDP;
6432 }
6433 if (proto == Q_TCP) {
6434 if (real_proto == IPPROTO_UDP)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006435 bpf_error(cstate, "port in range '%s' is udp", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006436 else if (real_proto == IPPROTO_SCTP)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006437 bpf_error(cstate, "port in range '%s' is sctp", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006438 else
6439 /* override PROTO_UNDEF */
6440 real_proto = IPPROTO_TCP;
6441 }
6442 if (proto == Q_SCTP) {
6443 if (real_proto == IPPROTO_UDP)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006444 bpf_error(cstate, "port in range '%s' is udp", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006445 else if (real_proto == IPPROTO_TCP)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006446 bpf_error(cstate, "port in range '%s' is tcp", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006447 else
6448 /* override PROTO_UNDEF */
Elliott Hughesd8845d72015-10-19 18:07:04 -07006449 real_proto = IPPROTO_SCTP;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006450 }
JP Abgrall511eca32014-02-12 13:46:45 -08006451 if (port1 < 0)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006452 bpf_error(cstate, "illegal port number %d < 0", port1);
JP Abgrall511eca32014-02-12 13:46:45 -08006453 if (port1 > 65535)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006454 bpf_error(cstate, "illegal port number %d > 65535", port1);
JP Abgrall511eca32014-02-12 13:46:45 -08006455 if (port2 < 0)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006456 bpf_error(cstate, "illegal port number %d < 0", port2);
JP Abgrall511eca32014-02-12 13:46:45 -08006457 if (port2 > 65535)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006458 bpf_error(cstate, "illegal port number %d > 65535", port2);
JP Abgrall511eca32014-02-12 13:46:45 -08006459
Elliott Hughes965a4b52017-05-15 10:37:39 -07006460 b = gen_portrange(cstate, port1, port2, real_proto, dir);
6461 gen_or(gen_portrange6(cstate, port1, port2, real_proto, dir), b);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006462 return b;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006463
6464 case Q_GATEWAY:
6465#ifndef INET6
6466 eaddr = pcap_ether_hostton(name);
6467 if (eaddr == NULL)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006468 bpf_error(cstate, "unknown ether host: %s", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006469
6470 alist = pcap_nametoaddr(name);
6471 if (alist == NULL || *alist == NULL)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006472 bpf_error(cstate, "unknown host '%s'", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006473 b = gen_gateway(eaddr, alist, proto, dir);
6474 free(eaddr);
6475 return b;
6476#else
Elliott Hughes965a4b52017-05-15 10:37:39 -07006477 bpf_error(cstate, "'gateway' not supported in this configuration");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006478#endif /*INET6*/
6479
6480 case Q_PROTO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006481 real_proto = lookup_proto(cstate, name, proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006482 if (real_proto >= 0)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006483 return gen_proto(cstate, real_proto, proto, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006484 else
Elliott Hughes965a4b52017-05-15 10:37:39 -07006485 bpf_error(cstate, "unknown protocol: %s", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006486
6487 case Q_PROTOCHAIN:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006488 real_proto = lookup_proto(cstate, name, proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006489 if (real_proto >= 0)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006490 return gen_protochain(cstate, real_proto, proto, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006491 else
Elliott Hughes965a4b52017-05-15 10:37:39 -07006492 bpf_error(cstate, "unknown protocol: %s", name);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006493
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006494 case Q_UNDEF:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006495 syntax(cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006496 /* NOTREACHED */
6497 }
6498 abort();
6499 /* NOTREACHED */
6500}
6501
6502struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07006503gen_mcode(compiler_state_t *cstate, const char *s1, const char *s2,
6504 unsigned int masklen, struct qual q)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006505{
6506 register int nlen, mlen;
6507 bpf_u_int32 n, m;
6508
6509 nlen = __pcap_atoin(s1, &n);
6510 /* Promote short ipaddr */
6511 n <<= 32 - nlen;
6512
6513 if (s2 != NULL) {
6514 mlen = __pcap_atoin(s2, &m);
6515 /* Promote short ipaddr */
6516 m <<= 32 - mlen;
6517 if ((n & ~m) != 0)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006518 bpf_error(cstate, "non-network bits set in \"%s mask %s\"",
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006519 s1, s2);
6520 } else {
6521 /* Convert mask len to mask */
6522 if (masklen > 32)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006523 bpf_error(cstate, "mask length must be <= 32");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006524 if (masklen == 0) {
6525 /*
6526 * X << 32 is not guaranteed by C to be 0; it's
6527 * undefined.
6528 */
6529 m = 0;
6530 } else
6531 m = 0xffffffff << (32 - masklen);
6532 if ((n & ~m) != 0)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006533 bpf_error(cstate, "non-network bits set in \"%s/%d\"",
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006534 s1, masklen);
6535 }
6536
6537 switch (q.addr) {
6538
6539 case Q_NET:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006540 return gen_host(cstate, n, m, q.proto, q.dir, q.addr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006541
6542 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006543 bpf_error(cstate, "Mask syntax for networks only");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006544 /* NOTREACHED */
6545 }
6546 /* NOTREACHED */
6547 return NULL;
6548}
6549
6550struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07006551gen_ncode(compiler_state_t *cstate, const char *s, bpf_u_int32 v, struct qual q)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006552{
6553 bpf_u_int32 mask;
6554 int proto = q.proto;
6555 int dir = q.dir;
6556 register int vlen;
6557
6558 if (s == NULL)
6559 vlen = 32;
Elliott Hughes965a4b52017-05-15 10:37:39 -07006560 else if (q.proto == Q_DECNET) {
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006561 vlen = __pcap_atodn(s, &v);
Elliott Hughes965a4b52017-05-15 10:37:39 -07006562 if (vlen == 0)
6563 bpf_error(cstate, "malformed decnet address '%s'", s);
6564 } else
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006565 vlen = __pcap_atoin(s, &v);
6566
6567 switch (q.addr) {
6568
6569 case Q_DEFAULT:
6570 case Q_HOST:
6571 case Q_NET:
6572 if (proto == Q_DECNET)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006573 return gen_host(cstate, v, 0, proto, dir, q.addr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006574 else if (proto == Q_LINK) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07006575 bpf_error(cstate, "illegal link layer address");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006576 } else {
6577 mask = 0xffffffff;
6578 if (s == NULL && q.addr == Q_NET) {
6579 /* Promote short net number */
6580 while (v && (v & 0xff000000) == 0) {
6581 v <<= 8;
6582 mask <<= 8;
6583 }
6584 } else {
6585 /* Promote short ipaddr */
6586 v <<= 32 - vlen;
Elliott Hughes965a4b52017-05-15 10:37:39 -07006587 mask <<= 32 - vlen ;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006588 }
Elliott Hughes965a4b52017-05-15 10:37:39 -07006589 return gen_host(cstate, v, mask, proto, dir, q.addr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006590 }
6591
6592 case Q_PORT:
6593 if (proto == Q_UDP)
6594 proto = IPPROTO_UDP;
6595 else if (proto == Q_TCP)
6596 proto = IPPROTO_TCP;
6597 else if (proto == Q_SCTP)
6598 proto = IPPROTO_SCTP;
6599 else if (proto == Q_DEFAULT)
6600 proto = PROTO_UNDEF;
6601 else
Elliott Hughes965a4b52017-05-15 10:37:39 -07006602 bpf_error(cstate, "illegal qualifier of 'port'");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006603
JP Abgrall511eca32014-02-12 13:46:45 -08006604 if (v > 65535)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006605 bpf_error(cstate, "illegal port number %u > 65535", v);
JP Abgrall511eca32014-02-12 13:46:45 -08006606
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006607 {
6608 struct block *b;
Elliott Hughes965a4b52017-05-15 10:37:39 -07006609 b = gen_port(cstate, (int)v, proto, dir);
6610 gen_or(gen_port6(cstate, (int)v, proto, dir), b);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006611 return b;
6612 }
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006613
6614 case Q_PORTRANGE:
6615 if (proto == Q_UDP)
6616 proto = IPPROTO_UDP;
6617 else if (proto == Q_TCP)
6618 proto = IPPROTO_TCP;
6619 else if (proto == Q_SCTP)
6620 proto = IPPROTO_SCTP;
6621 else if (proto == Q_DEFAULT)
6622 proto = PROTO_UNDEF;
6623 else
Elliott Hughes965a4b52017-05-15 10:37:39 -07006624 bpf_error(cstate, "illegal qualifier of 'portrange'");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006625
JP Abgrall511eca32014-02-12 13:46:45 -08006626 if (v > 65535)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006627 bpf_error(cstate, "illegal port number %u > 65535", v);
JP Abgrall511eca32014-02-12 13:46:45 -08006628
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006629 {
6630 struct block *b;
Elliott Hughes965a4b52017-05-15 10:37:39 -07006631 b = gen_portrange(cstate, (int)v, (int)v, proto, dir);
6632 gen_or(gen_portrange6(cstate, (int)v, (int)v, proto, dir), b);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006633 return b;
6634 }
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006635
6636 case Q_GATEWAY:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006637 bpf_error(cstate, "'gateway' requires a name");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006638 /* NOTREACHED */
6639
6640 case Q_PROTO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006641 return gen_proto(cstate, (int)v, proto, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006642
6643 case Q_PROTOCHAIN:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006644 return gen_protochain(cstate, (int)v, proto, dir);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006645
6646 case Q_UNDEF:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006647 syntax(cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006648 /* NOTREACHED */
6649
6650 default:
6651 abort();
6652 /* NOTREACHED */
6653 }
6654 /* NOTREACHED */
6655}
6656
6657#ifdef INET6
6658struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07006659gen_mcode6(compiler_state_t *cstate, const char *s1, const char *s2,
6660 unsigned int masklen, struct qual q)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006661{
6662 struct addrinfo *res;
6663 struct in6_addr *addr;
6664 struct in6_addr mask;
6665 struct block *b;
6666 u_int32_t *a, *m;
6667
6668 if (s2)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006669 bpf_error(cstate, "no mask %s supported", s2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006670
6671 res = pcap_nametoaddrinfo(s1);
6672 if (!res)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006673 bpf_error(cstate, "invalid ip6 address %s", s1);
6674 cstate->ai = res;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006675 if (res->ai_next)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006676 bpf_error(cstate, "%s resolved to multiple address", s1);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006677 addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
6678
6679 if (sizeof(mask) * 8 < masklen)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006680 bpf_error(cstate, "mask length must be <= %u", (unsigned int)(sizeof(mask) * 8));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006681 memset(&mask, 0, sizeof(mask));
6682 memset(&mask, 0xff, masklen / 8);
6683 if (masklen % 8) {
6684 mask.s6_addr[masklen / 8] =
6685 (0xff << (8 - masklen % 8)) & 0xff;
6686 }
6687
6688 a = (u_int32_t *)addr;
6689 m = (u_int32_t *)&mask;
6690 if ((a[0] & ~m[0]) || (a[1] & ~m[1])
6691 || (a[2] & ~m[2]) || (a[3] & ~m[3])) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07006692 bpf_error(cstate, "non-network bits set in \"%s/%d\"", s1, masklen);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006693 }
6694
6695 switch (q.addr) {
6696
6697 case Q_DEFAULT:
6698 case Q_HOST:
6699 if (masklen != 128)
Elliott Hughes965a4b52017-05-15 10:37:39 -07006700 bpf_error(cstate, "Mask syntax for networks only");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006701 /* FALLTHROUGH */
6702
6703 case Q_NET:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006704 b = gen_host6(cstate, addr, &mask, q.proto, q.dir, q.addr);
6705 cstate->ai = NULL;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006706 freeaddrinfo(res);
6707 return b;
6708
6709 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006710 bpf_error(cstate, "invalid qualifier against IPv6 address");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006711 /* NOTREACHED */
6712 }
6713 return NULL;
6714}
6715#endif /*INET6*/
6716
6717struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07006718gen_ecode(compiler_state_t *cstate, const u_char *eaddr, struct qual q)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006719{
6720 struct block *b, *tmp;
6721
6722 if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07006723 switch (cstate->linktype) {
JP Abgrall511eca32014-02-12 13:46:45 -08006724 case DLT_EN10MB:
6725 case DLT_NETANALYZER:
6726 case DLT_NETANALYZER_TRANSPARENT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006727 tmp = gen_prevlinkhdr_check(cstate);
6728 b = gen_ehostop(cstate, eaddr, (int)q.dir);
Elliott Hughesd8845d72015-10-19 18:07:04 -07006729 if (tmp != NULL)
6730 gen_and(tmp, b);
6731 return b;
JP Abgrall511eca32014-02-12 13:46:45 -08006732 case DLT_FDDI:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006733 return gen_fhostop(cstate, eaddr, (int)q.dir);
JP Abgrall511eca32014-02-12 13:46:45 -08006734 case DLT_IEEE802:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006735 return gen_thostop(cstate, eaddr, (int)q.dir);
JP Abgrall511eca32014-02-12 13:46:45 -08006736 case DLT_IEEE802_11:
6737 case DLT_PRISM_HEADER:
6738 case DLT_IEEE802_11_RADIO_AVS:
6739 case DLT_IEEE802_11_RADIO:
6740 case DLT_PPI:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006741 return gen_wlanhostop(cstate, eaddr, (int)q.dir);
JP Abgrall511eca32014-02-12 13:46:45 -08006742 case DLT_IP_OVER_FC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006743 return gen_ipfchostop(cstate, eaddr, (int)q.dir);
JP Abgrall511eca32014-02-12 13:46:45 -08006744 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006745 bpf_error(cstate, "ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
JP Abgrall511eca32014-02-12 13:46:45 -08006746 break;
6747 }
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006748 }
Elliott Hughes965a4b52017-05-15 10:37:39 -07006749 bpf_error(cstate, "ethernet address used in non-ether expression");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006750 /* NOTREACHED */
6751 return NULL;
6752}
6753
6754void
6755sappend(s0, s1)
6756 struct slist *s0, *s1;
6757{
6758 /*
6759 * This is definitely not the best way to do this, but the
6760 * lists will rarely get long.
6761 */
6762 while (s0->next)
6763 s0 = s0->next;
6764 s0->next = s1;
6765}
6766
6767static struct slist *
Elliott Hughes965a4b52017-05-15 10:37:39 -07006768xfer_to_x(compiler_state_t *cstate, struct arth *a)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006769{
6770 struct slist *s;
6771
Elliott Hughes965a4b52017-05-15 10:37:39 -07006772 s = new_stmt(cstate, BPF_LDX|BPF_MEM);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006773 s->s.k = a->regno;
6774 return s;
6775}
6776
6777static struct slist *
Elliott Hughes965a4b52017-05-15 10:37:39 -07006778xfer_to_a(compiler_state_t *cstate, struct arth *a)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006779{
6780 struct slist *s;
6781
Elliott Hughes965a4b52017-05-15 10:37:39 -07006782 s = new_stmt(cstate, BPF_LD|BPF_MEM);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006783 s->s.k = a->regno;
6784 return s;
6785}
6786
6787/*
6788 * Modify "index" to use the value stored into its register as an
6789 * offset relative to the beginning of the header for the protocol
6790 * "proto", and allocate a register and put an item "size" bytes long
6791 * (1, 2, or 4) at that offset into that register, making it the register
6792 * for "index".
6793 */
6794struct arth *
Elliott Hughes965a4b52017-05-15 10:37:39 -07006795gen_load(compiler_state_t *cstate, int proto, struct arth *inst, int size)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006796{
6797 struct slist *s, *tmp;
6798 struct block *b;
Elliott Hughes965a4b52017-05-15 10:37:39 -07006799 int regno = alloc_reg(cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006800
Elliott Hughes965a4b52017-05-15 10:37:39 -07006801 free_reg(cstate, inst->regno);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006802 switch (size) {
6803
6804 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006805 bpf_error(cstate, "data size must be 1, 2, or 4");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006806
6807 case 1:
6808 size = BPF_B;
6809 break;
6810
6811 case 2:
6812 size = BPF_H;
6813 break;
6814
6815 case 4:
6816 size = BPF_W;
6817 break;
6818 }
6819 switch (proto) {
6820 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07006821 bpf_error(cstate, "unsupported index operation");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006822
6823 case Q_RADIO:
6824 /*
6825 * The offset is relative to the beginning of the packet
6826 * data, if we have a radio header. (If we don't, this
6827 * is an error.)
6828 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006829 if (cstate->linktype != DLT_IEEE802_11_RADIO_AVS &&
6830 cstate->linktype != DLT_IEEE802_11_RADIO &&
6831 cstate->linktype != DLT_PRISM_HEADER)
6832 bpf_error(cstate, "radio information not present in capture");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006833
6834 /*
6835 * Load into the X register the offset computed into the
JP Abgrall511eca32014-02-12 13:46:45 -08006836 * register specified by "index".
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006837 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006838 s = xfer_to_x(cstate, inst);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006839
6840 /*
6841 * Load the item at that offset.
6842 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006843 tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006844 sappend(s, tmp);
6845 sappend(inst->s, s);
6846 break;
6847
6848 case Q_LINK:
6849 /*
6850 * The offset is relative to the beginning of
6851 * the link-layer header.
6852 *
6853 * XXX - what about ATM LANE? Should the index be
6854 * relative to the beginning of the AAL5 frame, so
6855 * that 0 refers to the beginning of the LE Control
6856 * field, or relative to the beginning of the LAN
6857 * frame, so that 0 refers, for Ethernet LANE, to
6858 * the beginning of the destination address?
6859 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006860 s = gen_abs_offset_varpart(cstate, &cstate->off_linkhdr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006861
6862 /*
6863 * If "s" is non-null, it has code to arrange that the
6864 * X register contains the length of the prefix preceding
6865 * the link-layer header. Add to it the offset computed
6866 * into the register specified by "index", and move that
6867 * into the X register. Otherwise, just load into the X
JP Abgrall511eca32014-02-12 13:46:45 -08006868 * register the offset computed into the register specified
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006869 * by "index".
6870 */
6871 if (s != NULL) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07006872 sappend(s, xfer_to_a(cstate, inst));
6873 sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
6874 sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006875 } else
Elliott Hughes965a4b52017-05-15 10:37:39 -07006876 s = xfer_to_x(cstate, inst);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006877
6878 /*
6879 * Load the item at the sum of the offset we've put in the
6880 * X register and the offset of the start of the link
6881 * layer header (which is 0 if the radio header is
6882 * variable-length; that header length is what we put
6883 * into the X register and then added to the index).
6884 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006885 tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
6886 tmp->s.k = cstate->off_linkhdr.constant_part;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006887 sappend(s, tmp);
6888 sappend(inst->s, s);
6889 break;
6890
6891 case Q_IP:
6892 case Q_ARP:
6893 case Q_RARP:
6894 case Q_ATALK:
6895 case Q_DECNET:
6896 case Q_SCA:
6897 case Q_LAT:
6898 case Q_MOPRC:
6899 case Q_MOPDL:
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006900 case Q_IPV6:
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006901 /*
6902 * The offset is relative to the beginning of
6903 * the network-layer header.
6904 * XXX - are there any cases where we want
Elliott Hughes965a4b52017-05-15 10:37:39 -07006905 * cstate->off_nl_nosnap?
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006906 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006907 s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006908
6909 /*
6910 * If "s" is non-null, it has code to arrange that the
Elliott Hughesd8845d72015-10-19 18:07:04 -07006911 * X register contains the variable part of the offset
6912 * of the link-layer payload. Add to it the offset
6913 * computed into the register specified by "index",
6914 * and move that into the X register. Otherwise, just
6915 * load into the X register the offset computed into
6916 * the register specified by "index".
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006917 */
6918 if (s != NULL) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07006919 sappend(s, xfer_to_a(cstate, inst));
6920 sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
6921 sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006922 } else
Elliott Hughes965a4b52017-05-15 10:37:39 -07006923 s = xfer_to_x(cstate, inst);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006924
6925 /*
6926 * Load the item at the sum of the offset we've put in the
6927 * X register, the offset of the start of the network
Elliott Hughesd8845d72015-10-19 18:07:04 -07006928 * layer header from the beginning of the link-layer
6929 * payload, and the constant part of the offset of the
6930 * start of the link-layer payload.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006931 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006932 tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
6933 tmp->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006934 sappend(s, tmp);
6935 sappend(inst->s, s);
6936
6937 /*
6938 * Do the computation only if the packet contains
6939 * the protocol in question.
6940 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006941 b = gen_proto_abbrev(cstate, proto);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006942 if (inst->b)
6943 gen_and(inst->b, b);
6944 inst->b = b;
6945 break;
6946
6947 case Q_SCTP:
6948 case Q_TCP:
6949 case Q_UDP:
6950 case Q_ICMP:
6951 case Q_IGMP:
6952 case Q_IGRP:
6953 case Q_PIM:
6954 case Q_VRRP:
JP Abgrall511eca32014-02-12 13:46:45 -08006955 case Q_CARP:
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006956 /*
6957 * The offset is relative to the beginning of
6958 * the transport-layer header.
6959 *
6960 * Load the X register with the length of the IPv4 header
6961 * (plus the offset of the link-layer header, if it's
6962 * a variable-length header), in bytes.
6963 *
6964 * XXX - are there any cases where we want
Elliott Hughes965a4b52017-05-15 10:37:39 -07006965 * cstate->off_nl_nosnap?
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006966 * XXX - we should, if we're built with
6967 * IPv6 support, generate code to load either
6968 * IPv4, IPv6, or both, as appropriate.
6969 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006970 s = gen_loadx_iphdrlen(cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006971
6972 /*
Elliott Hughesd8845d72015-10-19 18:07:04 -07006973 * The X register now contains the sum of the variable
6974 * part of the offset of the link-layer payload and the
JP Abgrall511eca32014-02-12 13:46:45 -08006975 * length of the network-layer header.
6976 *
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006977 * Load into the A register the offset relative to
6978 * the beginning of the transport layer header,
6979 * add the X register to that, move that to the
6980 * X register, and load with an offset from the
Elliott Hughesd8845d72015-10-19 18:07:04 -07006981 * X register equal to the sum of the constant part of
6982 * the offset of the link-layer payload and the offset,
6983 * relative to the beginning of the link-layer payload,
6984 * of the network-layer header.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006985 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006986 sappend(s, xfer_to_a(cstate, inst));
6987 sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
6988 sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
6989 sappend(s, tmp = new_stmt(cstate, BPF_LD|BPF_IND|size));
6990 tmp->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08006991 sappend(inst->s, s);
6992
6993 /*
6994 * Do the computation only if the packet contains
6995 * the protocol in question - which is true only
6996 * if this is an IP datagram and is the first or
6997 * only fragment of that datagram.
6998 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07006999 gen_and(gen_proto_abbrev(cstate, proto), b = gen_ipfrag(cstate));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007000 if (inst->b)
7001 gen_and(inst->b, b);
Elliott Hughes965a4b52017-05-15 10:37:39 -07007002 gen_and(gen_proto_abbrev(cstate, Q_IP), b);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007003 inst->b = b;
7004 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007005 case Q_ICMPV6:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007006 bpf_error(cstate, "IPv6 upper-layer protocol is not supported by proto[x]");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007007 /*NOTREACHED*/
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007008 }
7009 inst->regno = regno;
Elliott Hughes965a4b52017-05-15 10:37:39 -07007010 s = new_stmt(cstate, BPF_ST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007011 s->s.k = regno;
7012 sappend(inst->s, s);
7013
7014 return inst;
7015}
7016
7017struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007018gen_relation(compiler_state_t *cstate, int code, struct arth *a0,
7019 struct arth *a1, int reversed)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007020{
7021 struct slist *s0, *s1, *s2;
7022 struct block *b, *tmp;
7023
Elliott Hughes965a4b52017-05-15 10:37:39 -07007024 s0 = xfer_to_x(cstate, a1);
7025 s1 = xfer_to_a(cstate, a0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007026 if (code == BPF_JEQ) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07007027 s2 = new_stmt(cstate, BPF_ALU|BPF_SUB|BPF_X);
7028 b = new_block(cstate, JMP(code));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007029 sappend(s1, s2);
7030 }
7031 else
Elliott Hughes965a4b52017-05-15 10:37:39 -07007032 b = new_block(cstate, BPF_JMP|code|BPF_X);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007033 if (reversed)
7034 gen_not(b);
7035
7036 sappend(s0, s1);
7037 sappend(a1->s, s0);
7038 sappend(a0->s, a1->s);
7039
7040 b->stmts = a0->s;
7041
Elliott Hughes965a4b52017-05-15 10:37:39 -07007042 free_reg(cstate, a0->regno);
7043 free_reg(cstate, a1->regno);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007044
7045 /* 'and' together protocol checks */
7046 if (a0->b) {
7047 if (a1->b) {
7048 gen_and(a0->b, tmp = a1->b);
7049 }
7050 else
7051 tmp = a0->b;
7052 } else
7053 tmp = a1->b;
7054
7055 if (tmp)
7056 gen_and(tmp, b);
7057
7058 return b;
7059}
7060
7061struct arth *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007062gen_loadlen(compiler_state_t *cstate)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007063{
Elliott Hughes965a4b52017-05-15 10:37:39 -07007064 int regno = alloc_reg(cstate);
7065 struct arth *a = (struct arth *)newchunk(cstate, sizeof(*a));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007066 struct slist *s;
7067
Elliott Hughes965a4b52017-05-15 10:37:39 -07007068 s = new_stmt(cstate, BPF_LD|BPF_LEN);
7069 s->next = new_stmt(cstate, BPF_ST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007070 s->next->s.k = regno;
7071 a->s = s;
7072 a->regno = regno;
7073
7074 return a;
7075}
7076
7077struct arth *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007078gen_loadi(compiler_state_t *cstate, int val)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007079{
7080 struct arth *a;
7081 struct slist *s;
7082 int reg;
7083
Elliott Hughes965a4b52017-05-15 10:37:39 -07007084 a = (struct arth *)newchunk(cstate, sizeof(*a));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007085
Elliott Hughes965a4b52017-05-15 10:37:39 -07007086 reg = alloc_reg(cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007087
Elliott Hughes965a4b52017-05-15 10:37:39 -07007088 s = new_stmt(cstate, BPF_LD|BPF_IMM);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007089 s->s.k = val;
Elliott Hughes965a4b52017-05-15 10:37:39 -07007090 s->next = new_stmt(cstate, BPF_ST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007091 s->next->s.k = reg;
7092 a->s = s;
7093 a->regno = reg;
7094
7095 return a;
7096}
7097
7098struct arth *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007099gen_neg(compiler_state_t *cstate, struct arth *a)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007100{
7101 struct slist *s;
7102
Elliott Hughes965a4b52017-05-15 10:37:39 -07007103 s = xfer_to_a(cstate, a);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007104 sappend(a->s, s);
Elliott Hughes965a4b52017-05-15 10:37:39 -07007105 s = new_stmt(cstate, BPF_ALU|BPF_NEG);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007106 s->s.k = 0;
7107 sappend(a->s, s);
Elliott Hughes965a4b52017-05-15 10:37:39 -07007108 s = new_stmt(cstate, BPF_ST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007109 s->s.k = a->regno;
7110 sappend(a->s, s);
7111
7112 return a;
7113}
7114
7115struct arth *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007116gen_arth(compiler_state_t *cstate, int code, struct arth *a0,
7117 struct arth *a1)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007118{
7119 struct slist *s0, *s1, *s2;
7120
Elliott Hughes965a4b52017-05-15 10:37:39 -07007121 /*
7122 * Disallow division by, or modulus by, zero; we do this here
7123 * so that it gets done even if the optimizer is disabled.
7124 */
7125 if (code == BPF_DIV) {
7126 if (a1->s->s.code == (BPF_LD|BPF_IMM) && a1->s->s.k == 0)
7127 bpf_error(cstate, "division by zero");
7128 } else if (code == BPF_MOD) {
7129 if (a1->s->s.code == (BPF_LD|BPF_IMM) && a1->s->s.k == 0)
7130 bpf_error(cstate, "modulus by zero");
7131 }
7132 s0 = xfer_to_x(cstate, a1);
7133 s1 = xfer_to_a(cstate, a0);
7134 s2 = new_stmt(cstate, BPF_ALU|BPF_X|code);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007135
7136 sappend(s1, s2);
7137 sappend(s0, s1);
7138 sappend(a1->s, s0);
7139 sappend(a0->s, a1->s);
7140
Elliott Hughes965a4b52017-05-15 10:37:39 -07007141 free_reg(cstate, a0->regno);
7142 free_reg(cstate, a1->regno);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007143
Elliott Hughes965a4b52017-05-15 10:37:39 -07007144 s0 = new_stmt(cstate, BPF_ST);
7145 a0->regno = s0->s.k = alloc_reg(cstate);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007146 sappend(a0->s, s0);
7147
7148 return a0;
7149}
7150
7151/*
JP Abgrall511eca32014-02-12 13:46:45 -08007152 * Initialize the table of used registers and the current register.
7153 */
7154static void
Elliott Hughes965a4b52017-05-15 10:37:39 -07007155init_regs(compiler_state_t *cstate)
JP Abgrall511eca32014-02-12 13:46:45 -08007156{
Elliott Hughes965a4b52017-05-15 10:37:39 -07007157 cstate->curreg = 0;
7158 memset(cstate->regused, 0, sizeof cstate->regused);
JP Abgrall511eca32014-02-12 13:46:45 -08007159}
7160
7161/*
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007162 * Return the next free register.
7163 */
7164static int
Elliott Hughes965a4b52017-05-15 10:37:39 -07007165alloc_reg(compiler_state_t *cstate)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007166{
7167 int n = BPF_MEMWORDS;
7168
7169 while (--n >= 0) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07007170 if (cstate->regused[cstate->curreg])
7171 cstate->curreg = (cstate->curreg + 1) % BPF_MEMWORDS;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007172 else {
Elliott Hughes965a4b52017-05-15 10:37:39 -07007173 cstate->regused[cstate->curreg] = 1;
7174 return cstate->curreg;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007175 }
7176 }
Elliott Hughes965a4b52017-05-15 10:37:39 -07007177 bpf_error(cstate, "too many registers needed to evaluate expression");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007178 /* NOTREACHED */
7179 return 0;
7180}
7181
7182/*
7183 * Return a register to the table so it can
7184 * be used later.
7185 */
7186static void
Elliott Hughes965a4b52017-05-15 10:37:39 -07007187free_reg(compiler_state_t *cstate, int n)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007188{
Elliott Hughes965a4b52017-05-15 10:37:39 -07007189 cstate->regused[n] = 0;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007190}
7191
7192static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007193gen_len(compiler_state_t *cstate, int jmp, int n)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007194{
7195 struct slist *s;
7196 struct block *b;
7197
Elliott Hughes965a4b52017-05-15 10:37:39 -07007198 s = new_stmt(cstate, BPF_LD|BPF_LEN);
7199 b = new_block(cstate, JMP(jmp));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007200 b->stmts = s;
7201 b->s.k = n;
7202
7203 return b;
7204}
7205
7206struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007207gen_greater(compiler_state_t *cstate, int n)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007208{
Elliott Hughes965a4b52017-05-15 10:37:39 -07007209 return gen_len(cstate, BPF_JGE, n);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007210}
7211
7212/*
7213 * Actually, this is less than or equal.
7214 */
7215struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007216gen_less(compiler_state_t *cstate, int n)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007217{
7218 struct block *b;
7219
Elliott Hughes965a4b52017-05-15 10:37:39 -07007220 b = gen_len(cstate, BPF_JGT, n);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007221 gen_not(b);
7222
7223 return b;
7224}
7225
7226/*
7227 * This is for "byte {idx} {op} {val}"; "idx" is treated as relative to
7228 * the beginning of the link-layer header.
7229 * XXX - that means you can't test values in the radiotap header, but
7230 * as that header is difficult if not impossible to parse generally
7231 * without a loop, that might not be a severe problem. A new keyword
7232 * "radio" could be added for that, although what you'd really want
7233 * would be a way of testing particular radio header values, which
7234 * would generate code appropriate to the radio header in question.
7235 */
7236struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007237gen_byteop(compiler_state_t *cstate, int op, int idx, int val)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007238{
7239 struct block *b;
7240 struct slist *s;
7241
7242 switch (op) {
7243 default:
7244 abort();
7245
7246 case '=':
Elliott Hughes965a4b52017-05-15 10:37:39 -07007247 return gen_cmp(cstate, OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007248
7249 case '<':
Elliott Hughes965a4b52017-05-15 10:37:39 -07007250 b = gen_cmp_lt(cstate, OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007251 return b;
7252
7253 case '>':
Elliott Hughes965a4b52017-05-15 10:37:39 -07007254 b = gen_cmp_gt(cstate, OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007255 return b;
7256
7257 case '|':
Elliott Hughes965a4b52017-05-15 10:37:39 -07007258 s = new_stmt(cstate, BPF_ALU|BPF_OR|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007259 break;
7260
7261 case '&':
Elliott Hughes965a4b52017-05-15 10:37:39 -07007262 s = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007263 break;
7264 }
7265 s->s.k = val;
Elliott Hughes965a4b52017-05-15 10:37:39 -07007266 b = new_block(cstate, JMP(BPF_JEQ));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007267 b->stmts = s;
7268 gen_not(b);
7269
7270 return b;
7271}
7272
Elliott Hughes965a4b52017-05-15 10:37:39 -07007273static const u_char abroadcast[] = { 0x0 };
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007274
7275struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007276gen_broadcast(compiler_state_t *cstate, int proto)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007277{
7278 bpf_u_int32 hostmask;
7279 struct block *b0, *b1, *b2;
Elliott Hughes965a4b52017-05-15 10:37:39 -07007280 static const u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007281
7282 switch (proto) {
7283
7284 case Q_DEFAULT:
7285 case Q_LINK:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007286 switch (cstate->linktype) {
JP Abgrall511eca32014-02-12 13:46:45 -08007287 case DLT_ARCNET:
7288 case DLT_ARCNET_LINUX:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007289 return gen_ahostop(cstate, abroadcast, Q_DST);
JP Abgrall511eca32014-02-12 13:46:45 -08007290 case DLT_EN10MB:
7291 case DLT_NETANALYZER:
7292 case DLT_NETANALYZER_TRANSPARENT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007293 b1 = gen_prevlinkhdr_check(cstate);
7294 b0 = gen_ehostop(cstate, ebroadcast, Q_DST);
Elliott Hughesd8845d72015-10-19 18:07:04 -07007295 if (b1 != NULL)
7296 gen_and(b1, b0);
7297 return b0;
JP Abgrall511eca32014-02-12 13:46:45 -08007298 case DLT_FDDI:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007299 return gen_fhostop(cstate, ebroadcast, Q_DST);
JP Abgrall511eca32014-02-12 13:46:45 -08007300 case DLT_IEEE802:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007301 return gen_thostop(cstate, ebroadcast, Q_DST);
JP Abgrall511eca32014-02-12 13:46:45 -08007302 case DLT_IEEE802_11:
7303 case DLT_PRISM_HEADER:
7304 case DLT_IEEE802_11_RADIO_AVS:
7305 case DLT_IEEE802_11_RADIO:
7306 case DLT_PPI:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007307 return gen_wlanhostop(cstate, ebroadcast, Q_DST);
JP Abgrall511eca32014-02-12 13:46:45 -08007308 case DLT_IP_OVER_FC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007309 return gen_ipfchostop(cstate, ebroadcast, Q_DST);
JP Abgrall511eca32014-02-12 13:46:45 -08007310 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007311 bpf_error(cstate, "not a broadcast link");
JP Abgrall511eca32014-02-12 13:46:45 -08007312 }
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007313 break;
7314
7315 case Q_IP:
JP Abgrall511eca32014-02-12 13:46:45 -08007316 /*
7317 * We treat a netmask of PCAP_NETMASK_UNKNOWN (0xffffffff)
7318 * as an indication that we don't know the netmask, and fail
7319 * in that case.
7320 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007321 if (cstate->netmask == PCAP_NETMASK_UNKNOWN)
7322 bpf_error(cstate, "netmask not known, so 'ip broadcast' not supported");
7323 b0 = gen_linktype(cstate, ETHERTYPE_IP);
7324 hostmask = ~cstate->netmask;
7325 b1 = gen_mcmp(cstate, OR_LINKPL, 16, BPF_W, (bpf_int32)0, hostmask);
7326 b2 = gen_mcmp(cstate, OR_LINKPL, 16, BPF_W,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007327 (bpf_int32)(~0 & hostmask), hostmask);
7328 gen_or(b1, b2);
7329 gen_and(b0, b2);
7330 return b2;
7331 }
Elliott Hughes965a4b52017-05-15 10:37:39 -07007332 bpf_error(cstate, "only link-layer/IP broadcast filters supported");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007333 /* NOTREACHED */
7334 return NULL;
7335}
7336
7337/*
7338 * Generate code to test the low-order bit of a MAC address (that's
7339 * the bottom bit of the *first* byte).
7340 */
7341static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007342gen_mac_multicast(compiler_state_t *cstate, int offset)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007343{
7344 register struct block *b0;
7345 register struct slist *s;
7346
7347 /* link[offset] & 1 != 0 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007348 s = gen_load_a(cstate, OR_LINKHDR, offset, BPF_B);
7349 b0 = new_block(cstate, JMP(BPF_JSET));
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007350 b0->s.k = 1;
7351 b0->stmts = s;
7352 return b0;
7353}
7354
7355struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007356gen_multicast(compiler_state_t *cstate, int proto)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007357{
7358 register struct block *b0, *b1, *b2;
7359 register struct slist *s;
7360
7361 switch (proto) {
7362
7363 case Q_DEFAULT:
7364 case Q_LINK:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007365 switch (cstate->linktype) {
JP Abgrall511eca32014-02-12 13:46:45 -08007366 case DLT_ARCNET:
7367 case DLT_ARCNET_LINUX:
7368 /* all ARCnet multicasts use the same address */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007369 return gen_ahostop(cstate, abroadcast, Q_DST);
JP Abgrall511eca32014-02-12 13:46:45 -08007370 case DLT_EN10MB:
7371 case DLT_NETANALYZER:
7372 case DLT_NETANALYZER_TRANSPARENT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007373 b1 = gen_prevlinkhdr_check(cstate);
JP Abgrall511eca32014-02-12 13:46:45 -08007374 /* ether[0] & 1 != 0 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007375 b0 = gen_mac_multicast(cstate, 0);
Elliott Hughesd8845d72015-10-19 18:07:04 -07007376 if (b1 != NULL)
7377 gen_and(b1, b0);
7378 return b0;
JP Abgrall511eca32014-02-12 13:46:45 -08007379 case DLT_FDDI:
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007380 /*
JP Abgrall511eca32014-02-12 13:46:45 -08007381 * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX
7382 *
7383 * XXX - was that referring to bit-order issues?
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007384 */
JP Abgrall511eca32014-02-12 13:46:45 -08007385 /* fddi[1] & 1 != 0 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007386 return gen_mac_multicast(cstate, 1);
JP Abgrall511eca32014-02-12 13:46:45 -08007387 case DLT_IEEE802:
7388 /* tr[2] & 1 != 0 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007389 return gen_mac_multicast(cstate, 2);
JP Abgrall511eca32014-02-12 13:46:45 -08007390 case DLT_IEEE802_11:
7391 case DLT_PRISM_HEADER:
7392 case DLT_IEEE802_11_RADIO_AVS:
7393 case DLT_IEEE802_11_RADIO:
7394 case DLT_PPI:
7395 /*
7396 * Oh, yuk.
7397 *
7398 * For control frames, there is no DA.
7399 *
7400 * For management frames, DA is at an
7401 * offset of 4 from the beginning of
7402 * the packet.
7403 *
7404 * For data frames, DA is at an offset
7405 * of 4 from the beginning of the packet
7406 * if To DS is clear and at an offset of
7407 * 16 from the beginning of the packet
7408 * if To DS is set.
7409 */
7410
7411 /*
7412 * Generate the tests to be done for data frames.
7413 *
7414 * First, check for To DS set, i.e. "link[1] & 0x01".
7415 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007416 s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
7417 b1 = new_block(cstate, JMP(BPF_JSET));
JP Abgrall511eca32014-02-12 13:46:45 -08007418 b1->s.k = 0x01; /* To DS */
7419 b1->stmts = s;
7420
7421 /*
7422 * If To DS is set, the DA is at 16.
7423 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007424 b0 = gen_mac_multicast(cstate, 16);
JP Abgrall511eca32014-02-12 13:46:45 -08007425 gen_and(b1, b0);
7426
7427 /*
7428 * Now, check for To DS not set, i.e. check
7429 * "!(link[1] & 0x01)".
7430 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007431 s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
7432 b2 = new_block(cstate, JMP(BPF_JSET));
JP Abgrall511eca32014-02-12 13:46:45 -08007433 b2->s.k = 0x01; /* To DS */
7434 b2->stmts = s;
7435 gen_not(b2);
7436
7437 /*
7438 * If To DS is not set, the DA is at 4.
7439 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007440 b1 = gen_mac_multicast(cstate, 4);
JP Abgrall511eca32014-02-12 13:46:45 -08007441 gen_and(b2, b1);
7442
7443 /*
7444 * Now OR together the last two checks. That gives
7445 * the complete set of checks for data frames.
7446 */
7447 gen_or(b1, b0);
7448
7449 /*
7450 * Now check for a data frame.
7451 * I.e, check "link[0] & 0x08".
7452 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007453 s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
7454 b1 = new_block(cstate, JMP(BPF_JSET));
JP Abgrall511eca32014-02-12 13:46:45 -08007455 b1->s.k = 0x08;
7456 b1->stmts = s;
7457
7458 /*
7459 * AND that with the checks done for data frames.
7460 */
7461 gen_and(b1, b0);
7462
7463 /*
7464 * If the high-order bit of the type value is 0, this
7465 * is a management frame.
7466 * I.e, check "!(link[0] & 0x08)".
7467 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007468 s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
7469 b2 = new_block(cstate, JMP(BPF_JSET));
JP Abgrall511eca32014-02-12 13:46:45 -08007470 b2->s.k = 0x08;
7471 b2->stmts = s;
7472 gen_not(b2);
7473
7474 /*
7475 * For management frames, the DA is at 4.
7476 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007477 b1 = gen_mac_multicast(cstate, 4);
JP Abgrall511eca32014-02-12 13:46:45 -08007478 gen_and(b2, b1);
7479
7480 /*
7481 * OR that with the checks done for data frames.
7482 * That gives the checks done for management and
7483 * data frames.
7484 */
7485 gen_or(b1, b0);
7486
7487 /*
7488 * If the low-order bit of the type value is 1,
7489 * this is either a control frame or a frame
7490 * with a reserved type, and thus not a
7491 * frame with an SA.
7492 *
7493 * I.e., check "!(link[0] & 0x04)".
7494 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007495 s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
7496 b1 = new_block(cstate, JMP(BPF_JSET));
JP Abgrall511eca32014-02-12 13:46:45 -08007497 b1->s.k = 0x04;
7498 b1->stmts = s;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007499 gen_not(b1);
7500
JP Abgrall511eca32014-02-12 13:46:45 -08007501 /*
7502 * AND that with the checks for data and management
7503 * frames.
7504 */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007505 gen_and(b1, b0);
7506 return b0;
JP Abgrall511eca32014-02-12 13:46:45 -08007507 case DLT_IP_OVER_FC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007508 b0 = gen_mac_multicast(cstate, 2);
JP Abgrall511eca32014-02-12 13:46:45 -08007509 return b0;
JP Abgrall511eca32014-02-12 13:46:45 -08007510 default:
7511 break;
7512 }
7513 /* Link not known to support multicasts */
7514 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007515
7516 case Q_IP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007517 b0 = gen_linktype(cstate, ETHERTYPE_IP);
7518 b1 = gen_cmp_ge(cstate, OR_LINKPL, 16, BPF_B, (bpf_int32)224);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007519 gen_and(b0, b1);
7520 return b1;
7521
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007522 case Q_IPV6:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007523 b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
7524 b1 = gen_cmp(cstate, OR_LINKPL, 24, BPF_B, (bpf_int32)255);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007525 gen_and(b0, b1);
7526 return b1;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007527 }
Elliott Hughes965a4b52017-05-15 10:37:39 -07007528 bpf_error(cstate, "link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007529 /* NOTREACHED */
7530 return NULL;
7531}
7532
7533/*
JP Abgrall511eca32014-02-12 13:46:45 -08007534 * Filter on inbound (dir == 0) or outbound (dir == 1) traffic.
7535 * Outbound traffic is sent by this machine, while inbound traffic is
7536 * sent by a remote machine (and may include packets destined for a
7537 * unicast or multicast link-layer address we are not subscribing to).
7538 * These are the same definitions implemented by pcap_setdirection().
7539 * Capturing only unicast traffic destined for this host is probably
7540 * better accomplished using a higher-layer filter.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007541 */
7542struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007543gen_inbound(compiler_state_t *cstate, int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007544{
7545 register struct block *b0;
7546
7547 /*
7548 * Only some data link types support inbound/outbound qualifiers.
7549 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007550 switch (cstate->linktype) {
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007551 case DLT_SLIP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007552 b0 = gen_relation(cstate, BPF_JEQ,
7553 gen_load(cstate, Q_LINK, gen_loadi(cstate, 0), 1),
7554 gen_loadi(cstate, 0),
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007555 dir);
7556 break;
7557
JP Abgrall511eca32014-02-12 13:46:45 -08007558 case DLT_IPNET:
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007559 if (dir) {
JP Abgrall511eca32014-02-12 13:46:45 -08007560 /* match outgoing packets */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007561 b0 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, IPNET_OUTBOUND);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007562 } else {
JP Abgrall511eca32014-02-12 13:46:45 -08007563 /* match incoming packets */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007564 b0 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, IPNET_INBOUND);
JP Abgrall511eca32014-02-12 13:46:45 -08007565 }
7566 break;
7567
7568 case DLT_LINUX_SLL:
7569 /* match outgoing packets */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007570 b0 = gen_cmp(cstate, OR_LINKHDR, 0, BPF_H, LINUX_SLL_OUTGOING);
JP Abgrall511eca32014-02-12 13:46:45 -08007571 if (!dir) {
7572 /* to filter on inbound traffic, invert the match */
7573 gen_not(b0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007574 }
7575 break;
7576
7577#ifdef HAVE_NET_PFVAR_H
7578 case DLT_PFLOG:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007579 b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, dir), BPF_B,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007580 (bpf_int32)((dir == 0) ? PF_IN : PF_OUT));
7581 break;
7582#endif
7583
7584 case DLT_PPP_PPPD:
7585 if (dir) {
7586 /* match outgoing packets */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007587 b0 = gen_cmp(cstate, OR_LINKHDR, 0, BPF_B, PPP_PPPD_OUT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007588 } else {
7589 /* match incoming packets */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007590 b0 = gen_cmp(cstate, OR_LINKHDR, 0, BPF_B, PPP_PPPD_IN);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007591 }
7592 break;
7593
7594 case DLT_JUNIPER_MFR:
7595 case DLT_JUNIPER_MLFR:
7596 case DLT_JUNIPER_MLPPP:
7597 case DLT_JUNIPER_ATM1:
7598 case DLT_JUNIPER_ATM2:
7599 case DLT_JUNIPER_PPPOE:
7600 case DLT_JUNIPER_PPPOE_ATM:
7601 case DLT_JUNIPER_GGSN:
7602 case DLT_JUNIPER_ES:
7603 case DLT_JUNIPER_MONITOR:
7604 case DLT_JUNIPER_SERVICES:
7605 case DLT_JUNIPER_ETHER:
7606 case DLT_JUNIPER_PPP:
7607 case DLT_JUNIPER_FRELAY:
7608 case DLT_JUNIPER_CHDLC:
7609 case DLT_JUNIPER_VP:
JP Abgrall511eca32014-02-12 13:46:45 -08007610 case DLT_JUNIPER_ST:
7611 case DLT_JUNIPER_ISM:
7612 case DLT_JUNIPER_VS:
7613 case DLT_JUNIPER_SRX_E2E:
7614 case DLT_JUNIPER_FIBRECHANNEL:
7615 case DLT_JUNIPER_ATM_CEMIC:
7616
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007617 /* juniper flags (including direction) are stored
7618 * the byte after the 3-byte magic number */
7619 if (dir) {
7620 /* match outgoing packets */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007621 b0 = gen_mcmp(cstate, OR_LINKHDR, 3, BPF_B, 0, 0x01);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007622 } else {
7623 /* match incoming packets */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007624 b0 = gen_mcmp(cstate, OR_LINKHDR, 3, BPF_B, 1, 0x01);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007625 }
JP Abgrall511eca32014-02-12 13:46:45 -08007626 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007627
7628 default:
JP Abgrall511eca32014-02-12 13:46:45 -08007629 /*
7630 * If we have packet meta-data indicating a direction,
7631 * check it, otherwise give up as this link-layer type
7632 * has nothing in the packet data.
7633 */
7634#if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
7635 /*
7636 * This is Linux with PF_PACKET support.
7637 * If this is a *live* capture, we can look at
7638 * special meta-data in the filter expression;
7639 * if it's a savefile, we can't.
7640 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007641 if (cstate->bpf_pcap->rfile != NULL) {
JP Abgrall511eca32014-02-12 13:46:45 -08007642 /* We have a FILE *, so this is a savefile */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007643 bpf_error(cstate, "inbound/outbound not supported on linktype %d when reading savefiles",
7644 cstate->linktype);
JP Abgrall511eca32014-02-12 13:46:45 -08007645 b0 = NULL;
7646 /* NOTREACHED */
7647 }
7648 /* match outgoing packets */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007649 b0 = gen_cmp(cstate, OR_LINKHDR, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H,
JP Abgrall511eca32014-02-12 13:46:45 -08007650 PACKET_OUTGOING);
7651 if (!dir) {
7652 /* to filter on inbound traffic, invert the match */
7653 gen_not(b0);
7654 }
7655#else /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007656 bpf_error(cstate, "inbound/outbound not supported on linktype %d",
7657 cstate->linktype);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007658 b0 = NULL;
7659 /* NOTREACHED */
JP Abgrall511eca32014-02-12 13:46:45 -08007660#endif /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007661 }
7662 return (b0);
7663}
7664
7665#ifdef HAVE_NET_PFVAR_H
7666/* PF firewall log matched interface */
7667struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007668gen_pf_ifname(compiler_state_t *cstate, const char *ifname)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007669{
7670 struct block *b0;
7671 u_int len, off;
7672
Elliott Hughes965a4b52017-05-15 10:37:39 -07007673 if (cstate->linktype != DLT_PFLOG) {
7674 bpf_error(cstate, "ifname supported only on PF linktype");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007675 /* NOTREACHED */
7676 }
JP Abgrall511eca32014-02-12 13:46:45 -08007677 len = sizeof(((struct pfloghdr *)0)->ifname);
7678 off = offsetof(struct pfloghdr, ifname);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007679 if (strlen(ifname) >= len) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07007680 bpf_error(cstate, "ifname interface names can only be %d characters",
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007681 len-1);
7682 /* NOTREACHED */
7683 }
Elliott Hughes965a4b52017-05-15 10:37:39 -07007684 b0 = gen_bcmp(cstate, OR_LINKHDR, off, strlen(ifname), (const u_char *)ifname);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007685 return (b0);
7686}
7687
7688/* PF firewall log ruleset name */
7689struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007690gen_pf_ruleset(compiler_state_t *cstate, char *ruleset)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007691{
7692 struct block *b0;
7693
Elliott Hughes965a4b52017-05-15 10:37:39 -07007694 if (cstate->linktype != DLT_PFLOG) {
7695 bpf_error(cstate, "ruleset supported only on PF linktype");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007696 /* NOTREACHED */
7697 }
JP Abgrall511eca32014-02-12 13:46:45 -08007698
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007699 if (strlen(ruleset) >= sizeof(((struct pfloghdr *)0)->ruleset)) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07007700 bpf_error(cstate, "ruleset names can only be %ld characters",
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007701 (long)(sizeof(((struct pfloghdr *)0)->ruleset) - 1));
7702 /* NOTREACHED */
7703 }
JP Abgrall511eca32014-02-12 13:46:45 -08007704
Elliott Hughes965a4b52017-05-15 10:37:39 -07007705 b0 = gen_bcmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, ruleset),
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007706 strlen(ruleset), (const u_char *)ruleset);
7707 return (b0);
7708}
7709
7710/* PF firewall log rule number */
7711struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007712gen_pf_rnr(compiler_state_t *cstate, int rnr)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007713{
7714 struct block *b0;
7715
Elliott Hughes965a4b52017-05-15 10:37:39 -07007716 if (cstate->linktype != DLT_PFLOG) {
7717 bpf_error(cstate, "rnr supported only on PF linktype");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007718 /* NOTREACHED */
7719 }
7720
Elliott Hughes965a4b52017-05-15 10:37:39 -07007721 b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, rulenr), BPF_W,
JP Abgrall511eca32014-02-12 13:46:45 -08007722 (bpf_int32)rnr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007723 return (b0);
7724}
7725
7726/* PF firewall log sub-rule number */
7727struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007728gen_pf_srnr(compiler_state_t *cstate, int srnr)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007729{
7730 struct block *b0;
7731
Elliott Hughes965a4b52017-05-15 10:37:39 -07007732 if (cstate->linktype != DLT_PFLOG) {
7733 bpf_error(cstate, "srnr supported only on PF linktype");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007734 /* NOTREACHED */
7735 }
7736
Elliott Hughes965a4b52017-05-15 10:37:39 -07007737 b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, subrulenr), BPF_W,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007738 (bpf_int32)srnr);
7739 return (b0);
7740}
7741
7742/* PF firewall log reason code */
7743struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007744gen_pf_reason(compiler_state_t *cstate, int reason)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007745{
7746 struct block *b0;
7747
Elliott Hughes965a4b52017-05-15 10:37:39 -07007748 if (cstate->linktype != DLT_PFLOG) {
7749 bpf_error(cstate, "reason supported only on PF linktype");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007750 /* NOTREACHED */
7751 }
7752
Elliott Hughes965a4b52017-05-15 10:37:39 -07007753 b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, reason), BPF_B,
JP Abgrall511eca32014-02-12 13:46:45 -08007754 (bpf_int32)reason);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007755 return (b0);
7756}
7757
7758/* PF firewall log action */
7759struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007760gen_pf_action(compiler_state_t *cstate, int action)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007761{
7762 struct block *b0;
7763
Elliott Hughes965a4b52017-05-15 10:37:39 -07007764 if (cstate->linktype != DLT_PFLOG) {
7765 bpf_error(cstate, "action supported only on PF linktype");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007766 /* NOTREACHED */
7767 }
7768
Elliott Hughes965a4b52017-05-15 10:37:39 -07007769 b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, action), BPF_B,
JP Abgrall511eca32014-02-12 13:46:45 -08007770 (bpf_int32)action);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007771 return (b0);
7772}
7773#else /* !HAVE_NET_PFVAR_H */
7774struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007775gen_pf_ifname(compiler_state_t *cstate, const char *ifname)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007776{
Elliott Hughes965a4b52017-05-15 10:37:39 -07007777 bpf_error(cstate, "libpcap was compiled without pf support");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007778 /* NOTREACHED */
7779 return (NULL);
7780}
7781
7782struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007783gen_pf_ruleset(compiler_state_t *cstate, char *ruleset)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007784{
Elliott Hughes965a4b52017-05-15 10:37:39 -07007785 bpf_error(cstate, "libpcap was compiled on a machine without pf support");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007786 /* NOTREACHED */
7787 return (NULL);
7788}
7789
7790struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007791gen_pf_rnr(compiler_state_t *cstate, int rnr)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007792{
Elliott Hughes965a4b52017-05-15 10:37:39 -07007793 bpf_error(cstate, "libpcap was compiled on a machine without pf support");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007794 /* NOTREACHED */
7795 return (NULL);
7796}
7797
7798struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007799gen_pf_srnr(compiler_state_t *cstate, int srnr)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007800{
Elliott Hughes965a4b52017-05-15 10:37:39 -07007801 bpf_error(cstate, "libpcap was compiled on a machine without pf support");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007802 /* NOTREACHED */
7803 return (NULL);
7804}
7805
7806struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007807gen_pf_reason(compiler_state_t *cstate, int reason)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007808{
Elliott Hughes965a4b52017-05-15 10:37:39 -07007809 bpf_error(cstate, "libpcap was compiled on a machine without pf support");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007810 /* NOTREACHED */
7811 return (NULL);
7812}
7813
7814struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007815gen_pf_action(compiler_state_t *cstate, int action)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007816{
Elliott Hughes965a4b52017-05-15 10:37:39 -07007817 bpf_error(cstate, "libpcap was compiled on a machine without pf support");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007818 /* NOTREACHED */
7819 return (NULL);
7820}
7821#endif /* HAVE_NET_PFVAR_H */
7822
JP Abgrall511eca32014-02-12 13:46:45 -08007823/* IEEE 802.11 wireless header */
7824struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007825gen_p80211_type(compiler_state_t *cstate, int type, int mask)
JP Abgrall511eca32014-02-12 13:46:45 -08007826{
7827 struct block *b0;
7828
Elliott Hughes965a4b52017-05-15 10:37:39 -07007829 switch (cstate->linktype) {
JP Abgrall511eca32014-02-12 13:46:45 -08007830
7831 case DLT_IEEE802_11:
7832 case DLT_PRISM_HEADER:
7833 case DLT_IEEE802_11_RADIO_AVS:
7834 case DLT_IEEE802_11_RADIO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007835 b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, (bpf_int32)type,
JP Abgrall511eca32014-02-12 13:46:45 -08007836 (bpf_int32)mask);
7837 break;
7838
7839 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007840 bpf_error(cstate, "802.11 link-layer types supported only on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08007841 /* NOTREACHED */
7842 }
7843
7844 return (b0);
7845}
7846
7847struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007848gen_p80211_fcdir(compiler_state_t *cstate, int fcdir)
JP Abgrall511eca32014-02-12 13:46:45 -08007849{
7850 struct block *b0;
7851
Elliott Hughes965a4b52017-05-15 10:37:39 -07007852 switch (cstate->linktype) {
JP Abgrall511eca32014-02-12 13:46:45 -08007853
7854 case DLT_IEEE802_11:
7855 case DLT_PRISM_HEADER:
7856 case DLT_IEEE802_11_RADIO_AVS:
7857 case DLT_IEEE802_11_RADIO:
7858 break;
7859
7860 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007861 bpf_error(cstate, "frame direction supported only with 802.11 headers");
JP Abgrall511eca32014-02-12 13:46:45 -08007862 /* NOTREACHED */
7863 }
7864
Elliott Hughes965a4b52017-05-15 10:37:39 -07007865 b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B, (bpf_int32)fcdir,
JP Abgrall511eca32014-02-12 13:46:45 -08007866 (bpf_u_int32)IEEE80211_FC1_DIR_MASK);
7867
7868 return (b0);
7869}
7870
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007871struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007872gen_acode(compiler_state_t *cstate, const u_char *eaddr, struct qual q)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007873{
Elliott Hughes965a4b52017-05-15 10:37:39 -07007874 switch (cstate->linktype) {
JP Abgrall511eca32014-02-12 13:46:45 -08007875
7876 case DLT_ARCNET:
7877 case DLT_ARCNET_LINUX:
7878 if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) &&
7879 q.proto == Q_LINK)
Elliott Hughes965a4b52017-05-15 10:37:39 -07007880 return (gen_ahostop(cstate, eaddr, (int)q.dir));
JP Abgrall511eca32014-02-12 13:46:45 -08007881 else {
Elliott Hughes965a4b52017-05-15 10:37:39 -07007882 bpf_error(cstate, "ARCnet address used in non-arc expression");
JP Abgrall511eca32014-02-12 13:46:45 -08007883 /* NOTREACHED */
7884 }
7885 break;
7886
7887 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007888 bpf_error(cstate, "aid supported only on ARCnet");
JP Abgrall511eca32014-02-12 13:46:45 -08007889 /* NOTREACHED */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007890 }
Elliott Hughes965a4b52017-05-15 10:37:39 -07007891 bpf_error(cstate, "ARCnet address used in non-arc expression");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007892 /* NOTREACHED */
7893 return NULL;
7894}
7895
7896static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007897gen_ahostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007898{
7899 register struct block *b0, *b1;
7900
7901 switch (dir) {
7902 /* src comes first, different from Ethernet */
7903 case Q_SRC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007904 return gen_bcmp(cstate, OR_LINKHDR, 0, 1, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007905
7906 case Q_DST:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007907 return gen_bcmp(cstate, OR_LINKHDR, 1, 1, eaddr);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007908
7909 case Q_AND:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007910 b0 = gen_ahostop(cstate, eaddr, Q_SRC);
7911 b1 = gen_ahostop(cstate, eaddr, Q_DST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007912 gen_and(b0, b1);
7913 return b1;
7914
7915 case Q_DEFAULT:
7916 case Q_OR:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007917 b0 = gen_ahostop(cstate, eaddr, Q_SRC);
7918 b1 = gen_ahostop(cstate, eaddr, Q_DST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007919 gen_or(b0, b1);
7920 return b1;
JP Abgrall511eca32014-02-12 13:46:45 -08007921
7922 case Q_ADDR1:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007923 bpf_error(cstate, "'addr1' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08007924 break;
7925
7926 case Q_ADDR2:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007927 bpf_error(cstate, "'addr2' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08007928 break;
7929
7930 case Q_ADDR3:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007931 bpf_error(cstate, "'addr3' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08007932 break;
7933
7934 case Q_ADDR4:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007935 bpf_error(cstate, "'addr4' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08007936 break;
7937
7938 case Q_RA:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007939 bpf_error(cstate, "'ra' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08007940 break;
7941
7942 case Q_TA:
Elliott Hughes965a4b52017-05-15 10:37:39 -07007943 bpf_error(cstate, "'ta' is only supported on 802.11");
JP Abgrall511eca32014-02-12 13:46:45 -08007944 break;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08007945 }
7946 abort();
7947 /* NOTREACHED */
7948}
7949
Elliott Hughesd8845d72015-10-19 18:07:04 -07007950#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
7951static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007952gen_vlan_bpf_extensions(compiler_state_t *cstate, int vlan_num)
Elliott Hughesd8845d72015-10-19 18:07:04 -07007953{
7954 struct block *b0, *b1;
7955 struct slist *s;
7956
7957 /* generate new filter code based on extracting packet
7958 * metadata */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007959 s = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
Elliott Hughesd8845d72015-10-19 18:07:04 -07007960 s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT;
7961
Elliott Hughes965a4b52017-05-15 10:37:39 -07007962 b0 = new_block(cstate, JMP(BPF_JEQ));
Elliott Hughesd8845d72015-10-19 18:07:04 -07007963 b0->stmts = s;
7964 b0->s.k = 1;
7965
7966 if (vlan_num >= 0) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07007967 s = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
Elliott Hughesd8845d72015-10-19 18:07:04 -07007968 s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG;
7969
Elliott Hughes965a4b52017-05-15 10:37:39 -07007970 b1 = new_block(cstate, JMP(BPF_JEQ));
Elliott Hughesd8845d72015-10-19 18:07:04 -07007971 b1->stmts = s;
7972 b1->s.k = (bpf_int32) vlan_num;
7973
7974 gen_and(b0,b1);
7975 b0 = b1;
7976 }
7977
7978 return b0;
7979}
7980#endif
7981
7982static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07007983gen_vlan_no_bpf_extensions(compiler_state_t *cstate, int vlan_num)
Elliott Hughesd8845d72015-10-19 18:07:04 -07007984{
7985 struct block *b0, *b1;
7986
7987 /* check for VLAN, including QinQ */
Elliott Hughes965a4b52017-05-15 10:37:39 -07007988 b0 = gen_linktype(cstate, ETHERTYPE_8021Q);
7989 b1 = gen_linktype(cstate, ETHERTYPE_8021AD);
7990 gen_or(b0,b1);
7991 b0 = b1;
7992 b1 = gen_linktype(cstate, ETHERTYPE_8021QINQ);
Elliott Hughesd8845d72015-10-19 18:07:04 -07007993 gen_or(b0,b1);
7994 b0 = b1;
7995
7996 /* If a specific VLAN is requested, check VLAN id */
7997 if (vlan_num >= 0) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07007998 b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_H,
Elliott Hughesd8845d72015-10-19 18:07:04 -07007999 (bpf_int32)vlan_num, 0x0fff);
8000 gen_and(b0, b1);
8001 b0 = b1;
8002 }
8003
8004 /*
8005 * The payload follows the full header, including the
8006 * VLAN tags, so skip past this VLAN tag.
8007 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008008 cstate->off_linkpl.constant_part += 4;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008009
8010 /*
8011 * The link-layer type information follows the VLAN tags, so
8012 * skip past this VLAN tag.
8013 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008014 cstate->off_linktype.constant_part += 4;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008015
8016 return b0;
8017}
8018
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008019/*
8020 * support IEEE 802.1Q VLAN trunk over ethernet
8021 */
8022struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07008023gen_vlan(compiler_state_t *cstate, int vlan_num)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008024{
Elliott Hughesd8845d72015-10-19 18:07:04 -07008025 struct block *b0;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008026
8027 /* can't check for VLAN-encapsulated packets inside MPLS */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008028 if (cstate->label_stack_depth > 0)
8029 bpf_error(cstate, "no VLAN match after MPLS");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008030
8031 /*
JP Abgrall511eca32014-02-12 13:46:45 -08008032 * Check for a VLAN packet, and then change the offsets to point
8033 * to the type and data fields within the VLAN packet. Just
8034 * increment the offsets, so that we can support a hierarchy, e.g.
8035 * "vlan 300 && vlan 200" to capture VLAN 200 encapsulated within
8036 * VLAN 100.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008037 *
8038 * XXX - this is a bit of a kludge. If we were to split the
8039 * compiler into a parser that parses an expression and
8040 * generates an expression tree, and a code generator that
8041 * takes an expression tree (which could come from our
8042 * parser or from some other parser) and generates BPF code,
8043 * we could perhaps make the offsets parameters of routines
8044 * and, in the handler for an "AND" node, pass to subnodes
8045 * other than the VLAN node the adjusted offsets.
8046 *
8047 * This would mean that "vlan" would, instead of changing the
8048 * behavior of *all* tests after it, change only the behavior
8049 * of tests ANDed with it. That would change the documented
8050 * semantics of "vlan", which might break some expressions.
8051 * However, it would mean that "(vlan and ip) or ip" would check
8052 * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
8053 * checking only for VLAN-encapsulated IP, so that could still
8054 * be considered worth doing; it wouldn't break expressions
8055 * that are of the form "vlan and ..." or "vlan N and ...",
8056 * which I suspect are the most common expressions involving
8057 * "vlan". "vlan or ..." doesn't necessarily do what the user
8058 * would really want, now, as all the "or ..." tests would
8059 * be done assuming a VLAN, even though the "or" could be viewed
8060 * as meaning "or, if this isn't a VLAN packet...".
8061 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008062 switch (cstate->linktype) {
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008063
8064 case DLT_EN10MB:
JP Abgrall511eca32014-02-12 13:46:45 -08008065 case DLT_NETANALYZER:
8066 case DLT_NETANALYZER_TRANSPARENT:
Elliott Hughesd8845d72015-10-19 18:07:04 -07008067#if defined(SKF_AD_VLAN_TAG) && defined(SKF_AD_VLAN_TAG_PRESENT)
8068 /* Verify that this is the outer part of the packet and
8069 * not encapsulated somehow. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008070 if (cstate->vlan_stack_depth == 0 && !cstate->off_linkhdr.is_variable &&
8071 cstate->off_linkhdr.constant_part ==
8072 cstate->off_outermostlinkhdr.constant_part) {
Elliott Hughesd8845d72015-10-19 18:07:04 -07008073 /*
8074 * Do we need special VLAN handling?
8075 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008076 if (cstate->bpf_pcap->bpf_codegen_flags & BPF_SPECIAL_VLAN_HANDLING)
8077 b0 = gen_vlan_bpf_extensions(cstate, vlan_num);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008078 else
Elliott Hughes965a4b52017-05-15 10:37:39 -07008079 b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008080 } else
JP Abgrall511eca32014-02-12 13:46:45 -08008081#endif
Elliott Hughes965a4b52017-05-15 10:37:39 -07008082 b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008083 break;
8084
8085 case DLT_IEEE802_11:
8086 case DLT_PRISM_HEADER:
8087 case DLT_IEEE802_11_RADIO_AVS:
8088 case DLT_IEEE802_11_RADIO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008089 b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008090 break;
8091
8092 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008093 bpf_error(cstate, "no VLAN support for data link type %d",
8094 cstate->linktype);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008095 /*NOTREACHED*/
8096 }
8097
Elliott Hughes965a4b52017-05-15 10:37:39 -07008098 cstate->vlan_stack_depth++;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008099
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008100 return (b0);
8101}
8102
8103/*
8104 * support for MPLS
8105 */
8106struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07008107gen_mpls(compiler_state_t *cstate, int label_num)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008108{
Elliott Hughesd8845d72015-10-19 18:07:04 -07008109 struct block *b0, *b1;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008110
Elliott Hughes965a4b52017-05-15 10:37:39 -07008111 if (cstate->label_stack_depth > 0) {
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008112 /* just match the bottom-of-stack bit clear */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008113 b0 = gen_mcmp(cstate, OR_PREVMPLSHDR, 2, BPF_B, 0, 0x01);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008114 } else {
8115 /*
Elliott Hughesd8845d72015-10-19 18:07:04 -07008116 * We're not in an MPLS stack yet, so check the link-layer
8117 * type against MPLS.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008118 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008119 switch (cstate->linktype) {
Elliott Hughesd8845d72015-10-19 18:07:04 -07008120
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008121 case DLT_C_HDLC: /* fall through */
8122 case DLT_EN10MB:
JP Abgrall511eca32014-02-12 13:46:45 -08008123 case DLT_NETANALYZER:
8124 case DLT_NETANALYZER_TRANSPARENT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008125 b0 = gen_linktype(cstate, ETHERTYPE_MPLS);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008126 break;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008127
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008128 case DLT_PPP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008129 b0 = gen_linktype(cstate, PPP_MPLS_UCAST);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008130 break;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008131
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008132 /* FIXME add other DLT_s ...
8133 * for Frame-Relay/and ATM this may get messy due to SNAP headers
8134 * leave it for now */
Elliott Hughesd8845d72015-10-19 18:07:04 -07008135
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008136 default:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008137 bpf_error(cstate, "no MPLS support for data link type %d",
8138 cstate->linktype);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008139 b0 = NULL;
8140 /*NOTREACHED*/
8141 break;
8142 }
8143 }
8144
8145 /* If a specific MPLS label is requested, check it */
8146 if (label_num >= 0) {
8147 label_num = label_num << 12; /* label is shifted 12 bits on the wire */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008148 b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_W, (bpf_int32)label_num,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008149 0xfffff000); /* only compare the first 20 bits */
8150 gen_and(b0, b1);
8151 b0 = b1;
8152 }
8153
Elliott Hughesd8845d72015-10-19 18:07:04 -07008154 /*
8155 * Change the offsets to point to the type and data fields within
8156 * the MPLS packet. Just increment the offsets, so that we
8157 * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to
8158 * capture packets with an outer label of 100000 and an inner
8159 * label of 1024.
8160 *
8161 * Increment the MPLS stack depth as well; this indicates that
8162 * we're checking MPLS-encapsulated headers, to make sure higher
8163 * level code generators don't try to match against IP-related
8164 * protocols such as Q_ARP, Q_RARP etc.
8165 *
8166 * XXX - this is a bit of a kludge. See comments in gen_vlan().
8167 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008168 cstate->off_nl_nosnap += 4;
8169 cstate->off_nl += 4;
8170 cstate->label_stack_depth++;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008171 return (b0);
8172}
8173
8174/*
8175 * Support PPPOE discovery and session.
8176 */
8177struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07008178gen_pppoed(compiler_state_t *cstate)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008179{
8180 /* check for PPPoE discovery */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008181 return gen_linktype(cstate, (bpf_int32)ETHERTYPE_PPPOED);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008182}
8183
8184struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07008185gen_pppoes(compiler_state_t *cstate, int sess_num)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008186{
JP Abgrall511eca32014-02-12 13:46:45 -08008187 struct block *b0, *b1;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008188
8189 /*
8190 * Test against the PPPoE session link-layer type.
8191 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008192 b0 = gen_linktype(cstate, (bpf_int32)ETHERTYPE_PPPOES);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008193
Elliott Hughesd8845d72015-10-19 18:07:04 -07008194 /* If a specific session is requested, check PPPoE session id */
8195 if (sess_num >= 0) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07008196 b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_W,
Elliott Hughesd8845d72015-10-19 18:07:04 -07008197 (bpf_int32)sess_num, 0x0000ffff);
8198 gen_and(b0, b1);
8199 b0 = b1;
8200 }
8201
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008202 /*
8203 * Change the offsets to point to the type and data fields within
JP Abgrall511eca32014-02-12 13:46:45 -08008204 * the PPP packet, and note that this is PPPoE rather than
8205 * raw PPP.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008206 *
8207 * XXX - this is a bit of a kludge. If we were to split the
8208 * compiler into a parser that parses an expression and
8209 * generates an expression tree, and a code generator that
8210 * takes an expression tree (which could come from our
8211 * parser or from some other parser) and generates BPF code,
8212 * we could perhaps make the offsets parameters of routines
8213 * and, in the handler for an "AND" node, pass to subnodes
8214 * other than the PPPoE node the adjusted offsets.
8215 *
8216 * This would mean that "pppoes" would, instead of changing the
8217 * behavior of *all* tests after it, change only the behavior
8218 * of tests ANDed with it. That would change the documented
8219 * semantics of "pppoes", which might break some expressions.
8220 * However, it would mean that "(pppoes and ip) or ip" would check
8221 * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
8222 * checking only for VLAN-encapsulated IP, so that could still
8223 * be considered worth doing; it wouldn't break expressions
8224 * that are of the form "pppoes and ..." which I suspect are the
8225 * most common expressions involving "pppoes". "pppoes or ..."
8226 * doesn't necessarily do what the user would really want, now,
8227 * as all the "or ..." tests would be done assuming PPPoE, even
8228 * though the "or" could be viewed as meaning "or, if this isn't
8229 * a PPPoE packet...".
Elliott Hughesd8845d72015-10-19 18:07:04 -07008230 *
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008231 * The "network-layer" protocol is PPPoE, which has a 6-byte
JP Abgrall511eca32014-02-12 13:46:45 -08008232 * PPPoE header, followed by a PPP packet.
8233 *
8234 * There is no HDLC encapsulation for the PPP packet (it's
8235 * encapsulated in PPPoES instead), so the link-layer type
8236 * starts at the first byte of the PPP packet. For PPPoE,
8237 * that offset is relative to the beginning of the total
8238 * link-layer payload, including any 802.2 LLC header, so
Elliott Hughes965a4b52017-05-15 10:37:39 -07008239 * it's 6 bytes past cstate->off_nl.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008240 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008241 PUSH_LINKHDR(cstate, DLT_PPP, cstate->off_linkpl.is_variable,
8242 cstate->off_linkpl.constant_part + cstate->off_nl + 6, /* 6 bytes past the PPPoE header */
8243 cstate->off_linkpl.reg);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008244
Elliott Hughes965a4b52017-05-15 10:37:39 -07008245 cstate->off_linktype = cstate->off_linkhdr;
8246 cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 2;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008247
Elliott Hughes965a4b52017-05-15 10:37:39 -07008248 cstate->off_nl = 0;
8249 cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
Elliott Hughesd8845d72015-10-19 18:07:04 -07008250
8251 return b0;
8252}
8253
8254/* Check that this is Geneve and the VNI is correct if
8255 * specified. Parameterized to handle both IPv4 and IPv6. */
8256static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07008257gen_geneve_check(compiler_state_t *cstate,
8258 struct block *(*gen_portfn)(compiler_state_t *, int, int, int),
8259 enum e_offrel offrel, int vni)
Elliott Hughesd8845d72015-10-19 18:07:04 -07008260{
8261 struct block *b0, *b1;
8262
Elliott Hughes965a4b52017-05-15 10:37:39 -07008263 b0 = gen_portfn(cstate, GENEVE_PORT, IPPROTO_UDP, Q_DST);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008264
8265 /* Check that we are operating on version 0. Otherwise, we
8266 * can't decode the rest of the fields. The version is 2 bits
8267 * in the first byte of the Geneve header. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008268 b1 = gen_mcmp(cstate, offrel, 8, BPF_B, (bpf_int32)0, 0xc0);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008269 gen_and(b0, b1);
8270 b0 = b1;
8271
8272 if (vni >= 0) {
8273 vni <<= 8; /* VNI is in the upper 3 bytes */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008274 b1 = gen_mcmp(cstate, offrel, 12, BPF_W, (bpf_int32)vni,
Elliott Hughesd8845d72015-10-19 18:07:04 -07008275 0xffffff00);
8276 gen_and(b0, b1);
8277 b0 = b1;
8278 }
8279
8280 return b0;
8281}
8282
8283/* The IPv4 and IPv6 Geneve checks need to do two things:
8284 * - Verify that this actually is Geneve with the right VNI.
8285 * - Place the IP header length (plus variable link prefix if
8286 * needed) into register A to be used later to compute
8287 * the inner packet offsets. */
8288static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07008289gen_geneve4(compiler_state_t *cstate, int vni)
Elliott Hughesd8845d72015-10-19 18:07:04 -07008290{
8291 struct block *b0, *b1;
8292 struct slist *s, *s1;
8293
Elliott Hughes965a4b52017-05-15 10:37:39 -07008294 b0 = gen_geneve_check(cstate, gen_port, OR_TRAN_IPV4, vni);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008295
8296 /* Load the IP header length into A. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008297 s = gen_loadx_iphdrlen(cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008298
Elliott Hughes965a4b52017-05-15 10:37:39 -07008299 s1 = new_stmt(cstate, BPF_MISC|BPF_TXA);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008300 sappend(s, s1);
8301
8302 /* Forcibly append these statements to the true condition
8303 * of the protocol check by creating a new block that is
8304 * always true and ANDing them. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008305 b1 = new_block(cstate, BPF_JMP|BPF_JEQ|BPF_X);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008306 b1->stmts = s;
8307 b1->s.k = 0;
8308
8309 gen_and(b0, b1);
8310
8311 return b1;
8312}
8313
8314static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07008315gen_geneve6(compiler_state_t *cstate, int vni)
Elliott Hughesd8845d72015-10-19 18:07:04 -07008316{
8317 struct block *b0, *b1;
8318 struct slist *s, *s1;
8319
Elliott Hughes965a4b52017-05-15 10:37:39 -07008320 b0 = gen_geneve_check(cstate, gen_port6, OR_TRAN_IPV6, vni);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008321
8322 /* Load the IP header length. We need to account for a
8323 * variable length link prefix if there is one. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008324 s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008325 if (s) {
Elliott Hughes965a4b52017-05-15 10:37:39 -07008326 s1 = new_stmt(cstate, BPF_LD|BPF_IMM);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008327 s1->s.k = 40;
8328 sappend(s, s1);
8329
Elliott Hughes965a4b52017-05-15 10:37:39 -07008330 s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008331 s1->s.k = 0;
8332 sappend(s, s1);
8333 } else {
Elliott Hughes965a4b52017-05-15 10:37:39 -07008334 s = new_stmt(cstate, BPF_LD|BPF_IMM);
8335 s->s.k = 40;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008336 }
8337
8338 /* Forcibly append these statements to the true condition
8339 * of the protocol check by creating a new block that is
8340 * always true and ANDing them. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008341 s1 = new_stmt(cstate, BPF_MISC|BPF_TAX);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008342 sappend(s, s1);
8343
Elliott Hughes965a4b52017-05-15 10:37:39 -07008344 b1 = new_block(cstate, BPF_JMP|BPF_JEQ|BPF_X);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008345 b1->stmts = s;
8346 b1->s.k = 0;
8347
8348 gen_and(b0, b1);
8349
8350 return b1;
8351}
8352
8353/* We need to store three values based on the Geneve header::
8354 * - The offset of the linktype.
8355 * - The offset of the end of the Geneve header.
8356 * - The offset of the end of the encapsulated MAC header. */
8357static struct slist *
Elliott Hughes965a4b52017-05-15 10:37:39 -07008358gen_geneve_offsets(compiler_state_t *cstate)
Elliott Hughesd8845d72015-10-19 18:07:04 -07008359{
8360 struct slist *s, *s1, *s_proto;
8361
8362 /* First we need to calculate the offset of the Geneve header
8363 * itself. This is composed of the IP header previously calculated
8364 * (include any variable link prefix) and stored in A plus the
8365 * fixed sized headers (fixed link prefix, MAC length, and UDP
8366 * header). */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008367 s = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
8368 s->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 8;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008369
8370 /* Stash this in X since we'll need it later. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008371 s1 = new_stmt(cstate, BPF_MISC|BPF_TAX);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008372 sappend(s, s1);
8373
8374 /* The EtherType in Geneve is 2 bytes in. Calculate this and
8375 * store it. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008376 s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008377 s1->s.k = 2;
8378 sappend(s, s1);
8379
Elliott Hughes965a4b52017-05-15 10:37:39 -07008380 cstate->off_linktype.reg = alloc_reg(cstate);
8381 cstate->off_linktype.is_variable = 1;
8382 cstate->off_linktype.constant_part = 0;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008383
Elliott Hughes965a4b52017-05-15 10:37:39 -07008384 s1 = new_stmt(cstate, BPF_ST);
8385 s1->s.k = cstate->off_linktype.reg;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008386 sappend(s, s1);
8387
8388 /* Load the Geneve option length and mask and shift to get the
8389 * number of bytes. It is stored in the first byte of the Geneve
8390 * header. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008391 s1 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008392 s1->s.k = 0;
8393 sappend(s, s1);
8394
Elliott Hughes965a4b52017-05-15 10:37:39 -07008395 s1 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008396 s1->s.k = 0x3f;
8397 sappend(s, s1);
8398
Elliott Hughes965a4b52017-05-15 10:37:39 -07008399 s1 = new_stmt(cstate, BPF_ALU|BPF_MUL|BPF_K);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008400 s1->s.k = 4;
8401 sappend(s, s1);
8402
8403 /* Add in the rest of the Geneve base header. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008404 s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008405 s1->s.k = 8;
8406 sappend(s, s1);
8407
8408 /* Add the Geneve header length to its offset and store. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008409 s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008410 s1->s.k = 0;
8411 sappend(s, s1);
8412
8413 /* Set the encapsulated type as Ethernet. Even though we may
8414 * not actually have Ethernet inside there are two reasons this
8415 * is useful:
8416 * - The linktype field is always in EtherType format regardless
8417 * of whether it is in Geneve or an inner Ethernet frame.
8418 * - The only link layer that we have specific support for is
8419 * Ethernet. We will confirm that the packet actually is
8420 * Ethernet at runtime before executing these checks. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008421 PUSH_LINKHDR(cstate, DLT_EN10MB, 1, 0, alloc_reg(cstate));
Elliott Hughesd8845d72015-10-19 18:07:04 -07008422
Elliott Hughes965a4b52017-05-15 10:37:39 -07008423 s1 = new_stmt(cstate, BPF_ST);
8424 s1->s.k = cstate->off_linkhdr.reg;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008425 sappend(s, s1);
8426
8427 /* Calculate whether we have an Ethernet header or just raw IP/
8428 * MPLS/etc. If we have Ethernet, advance the end of the MAC offset
8429 * and linktype by 14 bytes so that the network header can be found
8430 * seamlessly. Otherwise, keep what we've calculated already. */
8431
8432 /* We have a bare jmp so we can't use the optimizer. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008433 cstate->no_optimize = 1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008434
8435 /* Load the EtherType in the Geneve header, 2 bytes in. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008436 s1 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_H);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008437 s1->s.k = 2;
8438 sappend(s, s1);
8439
8440 /* Load X with the end of the Geneve header. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008441 s1 = new_stmt(cstate, BPF_LDX|BPF_MEM);
8442 s1->s.k = cstate->off_linkhdr.reg;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008443 sappend(s, s1);
8444
8445 /* Check if the EtherType is Transparent Ethernet Bridging. At the
8446 * end of this check, we should have the total length in X. In
8447 * the non-Ethernet case, it's already there. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008448 s_proto = new_stmt(cstate, JMP(BPF_JEQ));
Elliott Hughesd8845d72015-10-19 18:07:04 -07008449 s_proto->s.k = ETHERTYPE_TEB;
8450 sappend(s, s_proto);
8451
Elliott Hughes965a4b52017-05-15 10:37:39 -07008452 s1 = new_stmt(cstate, BPF_MISC|BPF_TXA);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008453 sappend(s, s1);
8454 s_proto->s.jt = s1;
8455
8456 /* Since this is Ethernet, use the EtherType of the payload
8457 * directly as the linktype. Overwrite what we already have. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008458 s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008459 s1->s.k = 12;
8460 sappend(s, s1);
8461
Elliott Hughes965a4b52017-05-15 10:37:39 -07008462 s1 = new_stmt(cstate, BPF_ST);
8463 s1->s.k = cstate->off_linktype.reg;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008464 sappend(s, s1);
8465
8466 /* Advance two bytes further to get the end of the Ethernet
8467 * header. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008468 s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008469 s1->s.k = 2;
8470 sappend(s, s1);
8471
8472 /* Move the result to X. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008473 s1 = new_stmt(cstate, BPF_MISC|BPF_TAX);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008474 sappend(s, s1);
8475
8476 /* Store the final result of our linkpl calculation. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008477 cstate->off_linkpl.reg = alloc_reg(cstate);
8478 cstate->off_linkpl.is_variable = 1;
8479 cstate->off_linkpl.constant_part = 0;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008480
Elliott Hughes965a4b52017-05-15 10:37:39 -07008481 s1 = new_stmt(cstate, BPF_STX);
8482 s1->s.k = cstate->off_linkpl.reg;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008483 sappend(s, s1);
8484 s_proto->s.jf = s1;
8485
Elliott Hughes965a4b52017-05-15 10:37:39 -07008486 cstate->off_nl = 0;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008487
8488 return s;
8489}
8490
8491/* Check to see if this is a Geneve packet. */
8492struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07008493gen_geneve(compiler_state_t *cstate, int vni)
Elliott Hughesd8845d72015-10-19 18:07:04 -07008494{
8495 struct block *b0, *b1;
8496 struct slist *s;
8497
Elliott Hughes965a4b52017-05-15 10:37:39 -07008498 b0 = gen_geneve4(cstate, vni);
8499 b1 = gen_geneve6(cstate, vni);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008500
8501 gen_or(b0, b1);
8502 b0 = b1;
8503
8504 /* Later filters should act on the payload of the Geneve frame,
8505 * update all of the header pointers. Attach this code so that
8506 * it gets executed in the event that the Geneve filter matches. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008507 s = gen_geneve_offsets(cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008508
Elliott Hughes965a4b52017-05-15 10:37:39 -07008509 b1 = gen_true(cstate);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008510 sappend(s, b1->stmts);
8511 b1->stmts = s;
8512
8513 gen_and(b0, b1);
8514
Elliott Hughes965a4b52017-05-15 10:37:39 -07008515 cstate->is_geneve = 1;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008516
8517 return b1;
8518}
8519
8520/* Check that the encapsulated frame has a link layer header
8521 * for Ethernet filters. */
8522static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07008523gen_geneve_ll_check(compiler_state_t *cstate)
Elliott Hughesd8845d72015-10-19 18:07:04 -07008524{
8525 struct block *b0;
8526 struct slist *s, *s1;
8527
8528 /* The easiest way to see if there is a link layer present
8529 * is to check if the link layer header and payload are not
8530 * the same. */
8531
8532 /* Geneve always generates pure variable offsets so we can
8533 * compare only the registers. */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008534 s = new_stmt(cstate, BPF_LD|BPF_MEM);
8535 s->s.k = cstate->off_linkhdr.reg;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008536
Elliott Hughes965a4b52017-05-15 10:37:39 -07008537 s1 = new_stmt(cstate, BPF_LDX|BPF_MEM);
8538 s1->s.k = cstate->off_linkpl.reg;
Elliott Hughesd8845d72015-10-19 18:07:04 -07008539 sappend(s, s1);
8540
Elliott Hughes965a4b52017-05-15 10:37:39 -07008541 b0 = new_block(cstate, BPF_JMP|BPF_JEQ|BPF_X);
Elliott Hughesd8845d72015-10-19 18:07:04 -07008542 b0->stmts = s;
8543 b0->s.k = 0;
8544 gen_not(b0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008545
8546 return b0;
8547}
8548
8549struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07008550gen_atmfield_code(compiler_state_t *cstate, int atmfield, bpf_int32 jvalue,
8551 bpf_u_int32 jtype, int reverse)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008552{
8553 struct block *b0;
8554
8555 switch (atmfield) {
8556
8557 case A_VPI:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008558 if (!cstate->is_atm)
8559 bpf_error(cstate, "'vpi' supported only on raw ATM");
8560 if (cstate->off_vpi == (u_int)-1)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008561 abort();
Elliott Hughes965a4b52017-05-15 10:37:39 -07008562 b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_vpi, BPF_B, 0xffffffff, jtype,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008563 reverse, jvalue);
8564 break;
8565
8566 case A_VCI:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008567 if (!cstate->is_atm)
8568 bpf_error(cstate, "'vci' supported only on raw ATM");
8569 if (cstate->off_vci == (u_int)-1)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008570 abort();
Elliott Hughes965a4b52017-05-15 10:37:39 -07008571 b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_vci, BPF_H, 0xffffffff, jtype,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008572 reverse, jvalue);
8573 break;
8574
8575 case A_PROTOTYPE:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008576 if (cstate->off_proto == (u_int)-1)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008577 abort(); /* XXX - this isn't on FreeBSD */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008578 b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_proto, BPF_B, 0x0f, jtype,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008579 reverse, jvalue);
8580 break;
8581
8582 case A_MSGTYPE:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008583 if (cstate->off_payload == (u_int)-1)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008584 abort();
Elliott Hughes965a4b52017-05-15 10:37:39 -07008585 b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_payload + MSG_TYPE_POS, BPF_B,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008586 0xffffffff, jtype, reverse, jvalue);
8587 break;
8588
8589 case A_CALLREFTYPE:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008590 if (!cstate->is_atm)
8591 bpf_error(cstate, "'callref' supported only on raw ATM");
8592 if (cstate->off_proto == (u_int)-1)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008593 abort();
Elliott Hughes965a4b52017-05-15 10:37:39 -07008594 b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_proto, BPF_B, 0xffffffff,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008595 jtype, reverse, jvalue);
8596 break;
8597
8598 default:
8599 abort();
8600 }
8601 return b0;
8602}
8603
8604struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07008605gen_atmtype_abbrev(compiler_state_t *cstate, int type)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008606{
8607 struct block *b0, *b1;
8608
8609 switch (type) {
8610
8611 case A_METAC:
8612 /* Get all packets in Meta signalling Circuit */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008613 if (!cstate->is_atm)
8614 bpf_error(cstate, "'metac' supported only on raw ATM");
8615 b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
8616 b1 = gen_atmfield_code(cstate, A_VCI, 1, BPF_JEQ, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008617 gen_and(b0, b1);
8618 break;
8619
8620 case A_BCC:
8621 /* Get all packets in Broadcast Circuit*/
Elliott Hughes965a4b52017-05-15 10:37:39 -07008622 if (!cstate->is_atm)
8623 bpf_error(cstate, "'bcc' supported only on raw ATM");
8624 b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
8625 b1 = gen_atmfield_code(cstate, A_VCI, 2, BPF_JEQ, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008626 gen_and(b0, b1);
8627 break;
8628
8629 case A_OAMF4SC:
8630 /* Get all cells in Segment OAM F4 circuit*/
Elliott Hughes965a4b52017-05-15 10:37:39 -07008631 if (!cstate->is_atm)
8632 bpf_error(cstate, "'oam4sc' supported only on raw ATM");
8633 b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
8634 b1 = gen_atmfield_code(cstate, A_VCI, 3, BPF_JEQ, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008635 gen_and(b0, b1);
8636 break;
8637
8638 case A_OAMF4EC:
8639 /* Get all cells in End-to-End OAM F4 Circuit*/
Elliott Hughes965a4b52017-05-15 10:37:39 -07008640 if (!cstate->is_atm)
8641 bpf_error(cstate, "'oam4ec' supported only on raw ATM");
8642 b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
8643 b1 = gen_atmfield_code(cstate, A_VCI, 4, BPF_JEQ, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008644 gen_and(b0, b1);
8645 break;
8646
8647 case A_SC:
8648 /* Get all packets in connection Signalling Circuit */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008649 if (!cstate->is_atm)
8650 bpf_error(cstate, "'sc' supported only on raw ATM");
8651 b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
8652 b1 = gen_atmfield_code(cstate, A_VCI, 5, BPF_JEQ, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008653 gen_and(b0, b1);
8654 break;
8655
8656 case A_ILMIC:
8657 /* Get all packets in ILMI Circuit */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008658 if (!cstate->is_atm)
8659 bpf_error(cstate, "'ilmic' supported only on raw ATM");
8660 b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
8661 b1 = gen_atmfield_code(cstate, A_VCI, 16, BPF_JEQ, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008662 gen_and(b0, b1);
8663 break;
8664
8665 case A_LANE:
8666 /* Get all LANE packets */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008667 if (!cstate->is_atm)
8668 bpf_error(cstate, "'lane' supported only on raw ATM");
8669 b1 = gen_atmfield_code(cstate, A_PROTOTYPE, PT_LANE, BPF_JEQ, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008670
8671 /*
8672 * Arrange that all subsequent tests assume LANE
8673 * rather than LLC-encapsulated packets, and set
8674 * the offsets appropriately for LANE-encapsulated
8675 * Ethernet.
8676 *
Elliott Hughesd8845d72015-10-19 18:07:04 -07008677 * We assume LANE means Ethernet, not Token Ring.
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008678 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008679 PUSH_LINKHDR(cstate, DLT_EN10MB, 0,
8680 cstate->off_payload + 2, /* Ethernet header */
Elliott Hughesd8845d72015-10-19 18:07:04 -07008681 -1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07008682 cstate->off_linktype.constant_part = cstate->off_linkhdr.constant_part + 12;
8683 cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 14; /* Ethernet */
8684 cstate->off_nl = 0; /* Ethernet II */
8685 cstate->off_nl_nosnap = 3; /* 802.3+802.2 */
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008686 break;
8687
8688 case A_LLC:
8689 /* Get all LLC-encapsulated packets */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008690 if (!cstate->is_atm)
8691 bpf_error(cstate, "'llc' supported only on raw ATM");
8692 b1 = gen_atmfield_code(cstate, A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
8693 cstate->linktype = cstate->prevlinktype;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008694 break;
8695
8696 default:
8697 abort();
8698 }
8699 return b1;
8700}
8701
Elliott Hughesd8845d72015-10-19 18:07:04 -07008702/*
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008703 * Filtering for MTP2 messages based on li value
8704 * FISU, length is null
8705 * LSSU, length is 1 or 2
8706 * MSU, length is 3 or more
JP Abgrall511eca32014-02-12 13:46:45 -08008707 * For MTP2_HSL, sequences are on 2 bytes, and length on 9 bits
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008708 */
8709struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07008710gen_mtp2type_abbrev(compiler_state_t *cstate, int type)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008711{
8712 struct block *b0, *b1;
8713
8714 switch (type) {
8715
8716 case M_FISU:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008717 if ( (cstate->linktype != DLT_MTP2) &&
8718 (cstate->linktype != DLT_ERF) &&
8719 (cstate->linktype != DLT_MTP2_WITH_PHDR) )
8720 bpf_error(cstate, "'fisu' supported only on MTP2");
8721 /* gen_ncmp(cstate, offrel, offset, size, mask, jtype, reverse, value) */
8722 b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B, 0x3f, BPF_JEQ, 0, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008723 break;
8724
8725 case M_LSSU:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008726 if ( (cstate->linktype != DLT_MTP2) &&
8727 (cstate->linktype != DLT_ERF) &&
8728 (cstate->linktype != DLT_MTP2_WITH_PHDR) )
8729 bpf_error(cstate, "'lssu' supported only on MTP2");
8730 b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B, 0x3f, BPF_JGT, 1, 2);
8731 b1 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B, 0x3f, BPF_JGT, 0, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008732 gen_and(b1, b0);
8733 break;
8734
8735 case M_MSU:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008736 if ( (cstate->linktype != DLT_MTP2) &&
8737 (cstate->linktype != DLT_ERF) &&
8738 (cstate->linktype != DLT_MTP2_WITH_PHDR) )
8739 bpf_error(cstate, "'msu' supported only on MTP2");
8740 b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B, 0x3f, BPF_JGT, 0, 2);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008741 break;
8742
JP Abgrall511eca32014-02-12 13:46:45 -08008743 case MH_FISU:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008744 if ( (cstate->linktype != DLT_MTP2) &&
8745 (cstate->linktype != DLT_ERF) &&
8746 (cstate->linktype != DLT_MTP2_WITH_PHDR) )
8747 bpf_error(cstate, "'hfisu' supported only on MTP2_HSL");
8748 /* gen_ncmp(cstate, offrel, offset, size, mask, jtype, reverse, value) */
8749 b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H, 0xff80, BPF_JEQ, 0, 0);
JP Abgrall511eca32014-02-12 13:46:45 -08008750 break;
8751
8752 case MH_LSSU:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008753 if ( (cstate->linktype != DLT_MTP2) &&
8754 (cstate->linktype != DLT_ERF) &&
8755 (cstate->linktype != DLT_MTP2_WITH_PHDR) )
8756 bpf_error(cstate, "'hlssu' supported only on MTP2_HSL");
8757 b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H, 0xff80, BPF_JGT, 1, 0x0100);
8758 b1 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0);
JP Abgrall511eca32014-02-12 13:46:45 -08008759 gen_and(b1, b0);
8760 break;
8761
8762 case MH_MSU:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008763 if ( (cstate->linktype != DLT_MTP2) &&
8764 (cstate->linktype != DLT_ERF) &&
8765 (cstate->linktype != DLT_MTP2_WITH_PHDR) )
8766 bpf_error(cstate, "'hmsu' supported only on MTP2_HSL");
8767 b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0x0100);
JP Abgrall511eca32014-02-12 13:46:45 -08008768 break;
8769
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008770 default:
8771 abort();
8772 }
8773 return b0;
8774}
8775
8776struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07008777gen_mtp3field_code(compiler_state_t *cstate, int mtp3field, bpf_u_int32 jvalue,
8778 bpf_u_int32 jtype, int reverse)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008779{
8780 struct block *b0;
8781 bpf_u_int32 val1 , val2 , val3;
Elliott Hughes965a4b52017-05-15 10:37:39 -07008782 u_int newoff_sio = cstate->off_sio;
8783 u_int newoff_opc = cstate->off_opc;
8784 u_int newoff_dpc = cstate->off_dpc;
8785 u_int newoff_sls = cstate->off_sls;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008786
8787 switch (mtp3field) {
8788
JP Abgrall511eca32014-02-12 13:46:45 -08008789 case MH_SIO:
8790 newoff_sio += 3; /* offset for MTP2_HSL */
8791 /* FALLTHROUGH */
8792
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008793 case M_SIO:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008794 if (cstate->off_sio == (u_int)-1)
8795 bpf_error(cstate, "'sio' supported only on SS7");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008796 /* sio coded on 1 byte so max value 255 */
8797 if(jvalue > 255)
Elliott Hughes965a4b52017-05-15 10:37:39 -07008798 bpf_error(cstate, "sio value %u too big; max value = 255",
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008799 jvalue);
Elliott Hughes965a4b52017-05-15 10:37:39 -07008800 b0 = gen_ncmp(cstate, OR_PACKET, newoff_sio, BPF_B, 0xffffffff,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008801 (u_int)jtype, reverse, (u_int)jvalue);
8802 break;
8803
JP Abgrall511eca32014-02-12 13:46:45 -08008804 case MH_OPC:
8805 newoff_opc+=3;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008806 case M_OPC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008807 if (cstate->off_opc == (u_int)-1)
8808 bpf_error(cstate, "'opc' supported only on SS7");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008809 /* opc coded on 14 bits so max value 16383 */
8810 if (jvalue > 16383)
Elliott Hughes965a4b52017-05-15 10:37:39 -07008811 bpf_error(cstate, "opc value %u too big; max value = 16383",
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008812 jvalue);
8813 /* the following instructions are made to convert jvalue
8814 * to the form used to write opc in an ss7 message*/
8815 val1 = jvalue & 0x00003c00;
8816 val1 = val1 >>10;
8817 val2 = jvalue & 0x000003fc;
8818 val2 = val2 <<6;
8819 val3 = jvalue & 0x00000003;
8820 val3 = val3 <<22;
8821 jvalue = val1 + val2 + val3;
Elliott Hughes965a4b52017-05-15 10:37:39 -07008822 b0 = gen_ncmp(cstate, OR_PACKET, newoff_opc, BPF_W, 0x00c0ff0f,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008823 (u_int)jtype, reverse, (u_int)jvalue);
8824 break;
8825
JP Abgrall511eca32014-02-12 13:46:45 -08008826 case MH_DPC:
8827 newoff_dpc += 3;
8828 /* FALLTHROUGH */
8829
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008830 case M_DPC:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008831 if (cstate->off_dpc == (u_int)-1)
8832 bpf_error(cstate, "'dpc' supported only on SS7");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008833 /* dpc coded on 14 bits so max value 16383 */
8834 if (jvalue > 16383)
Elliott Hughes965a4b52017-05-15 10:37:39 -07008835 bpf_error(cstate, "dpc value %u too big; max value = 16383",
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008836 jvalue);
8837 /* the following instructions are made to convert jvalue
8838 * to the forme used to write dpc in an ss7 message*/
8839 val1 = jvalue & 0x000000ff;
8840 val1 = val1 << 24;
8841 val2 = jvalue & 0x00003f00;
8842 val2 = val2 << 8;
8843 jvalue = val1 + val2;
Elliott Hughes965a4b52017-05-15 10:37:39 -07008844 b0 = gen_ncmp(cstate, OR_PACKET, newoff_dpc, BPF_W, 0xff3f0000,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008845 (u_int)jtype, reverse, (u_int)jvalue);
8846 break;
8847
JP Abgrall511eca32014-02-12 13:46:45 -08008848 case MH_SLS:
8849 newoff_sls+=3;
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008850 case M_SLS:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008851 if (cstate->off_sls == (u_int)-1)
8852 bpf_error(cstate, "'sls' supported only on SS7");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008853 /* sls coded on 4 bits so max value 15 */
8854 if (jvalue > 15)
Elliott Hughes965a4b52017-05-15 10:37:39 -07008855 bpf_error(cstate, "sls value %u too big; max value = 15",
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008856 jvalue);
8857 /* the following instruction is made to convert jvalue
8858 * to the forme used to write sls in an ss7 message*/
8859 jvalue = jvalue << 4;
Elliott Hughes965a4b52017-05-15 10:37:39 -07008860 b0 = gen_ncmp(cstate, OR_PACKET, newoff_sls, BPF_B, 0xf0,
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008861 (u_int)jtype,reverse, (u_int)jvalue);
8862 break;
8863
8864 default:
8865 abort();
8866 }
8867 return b0;
8868}
8869
8870static struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07008871gen_msg_abbrev(compiler_state_t *cstate, int type)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008872{
8873 struct block *b1;
8874
8875 /*
8876 * Q.2931 signalling protocol messages for handling virtual circuits
8877 * establishment and teardown
8878 */
8879 switch (type) {
8880
8881 case A_SETUP:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008882 b1 = gen_atmfield_code(cstate, A_MSGTYPE, SETUP, BPF_JEQ, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008883 break;
8884
8885 case A_CALLPROCEED:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008886 b1 = gen_atmfield_code(cstate, A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008887 break;
8888
8889 case A_CONNECT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008890 b1 = gen_atmfield_code(cstate, A_MSGTYPE, CONNECT, BPF_JEQ, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008891 break;
8892
8893 case A_CONNECTACK:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008894 b1 = gen_atmfield_code(cstate, A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008895 break;
8896
8897 case A_RELEASE:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008898 b1 = gen_atmfield_code(cstate, A_MSGTYPE, RELEASE, BPF_JEQ, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008899 break;
8900
8901 case A_RELEASE_DONE:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008902 b1 = gen_atmfield_code(cstate, A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008903 break;
8904
8905 default:
8906 abort();
8907 }
8908 return b1;
8909}
8910
8911struct block *
Elliott Hughes965a4b52017-05-15 10:37:39 -07008912gen_atmmulti_abbrev(compiler_state_t *cstate, int type)
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008913{
8914 struct block *b0, *b1;
8915
8916 switch (type) {
8917
8918 case A_OAM:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008919 if (!cstate->is_atm)
8920 bpf_error(cstate, "'oam' supported only on raw ATM");
8921 b1 = gen_atmmulti_abbrev(cstate, A_OAMF4);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008922 break;
8923
8924 case A_OAMF4:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008925 if (!cstate->is_atm)
8926 bpf_error(cstate, "'oamf4' supported only on raw ATM");
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008927 /* OAM F4 type */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008928 b0 = gen_atmfield_code(cstate, A_VCI, 3, BPF_JEQ, 0);
8929 b1 = gen_atmfield_code(cstate, A_VCI, 4, BPF_JEQ, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008930 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07008931 b0 = gen_atmfield_code(cstate, A_VPI, 0, BPF_JEQ, 0);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008932 gen_and(b0, b1);
8933 break;
8934
8935 case A_CONNECTMSG:
8936 /*
8937 * Get Q.2931 signalling messages for switched
8938 * virtual connection
8939 */
Elliott Hughes965a4b52017-05-15 10:37:39 -07008940 if (!cstate->is_atm)
8941 bpf_error(cstate, "'connectmsg' supported only on raw ATM");
8942 b0 = gen_msg_abbrev(cstate, A_SETUP);
8943 b1 = gen_msg_abbrev(cstate, A_CALLPROCEED);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008944 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07008945 b0 = gen_msg_abbrev(cstate, A_CONNECT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008946 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07008947 b0 = gen_msg_abbrev(cstate, A_CONNECTACK);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008948 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07008949 b0 = gen_msg_abbrev(cstate, A_RELEASE);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008950 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07008951 b0 = gen_msg_abbrev(cstate, A_RELEASE_DONE);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008952 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07008953 b0 = gen_atmtype_abbrev(cstate, A_SC);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008954 gen_and(b0, b1);
8955 break;
8956
8957 case A_METACONNECT:
Elliott Hughes965a4b52017-05-15 10:37:39 -07008958 if (!cstate->is_atm)
8959 bpf_error(cstate, "'metaconnect' supported only on raw ATM");
8960 b0 = gen_msg_abbrev(cstate, A_SETUP);
8961 b1 = gen_msg_abbrev(cstate, A_CALLPROCEED);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008962 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07008963 b0 = gen_msg_abbrev(cstate, A_CONNECT);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008964 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07008965 b0 = gen_msg_abbrev(cstate, A_RELEASE);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008966 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07008967 b0 = gen_msg_abbrev(cstate, A_RELEASE_DONE);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008968 gen_or(b0, b1);
Elliott Hughes965a4b52017-05-15 10:37:39 -07008969 b0 = gen_atmtype_abbrev(cstate, A_METAC);
The Android Open Source Project478ab6c2009-03-03 19:30:05 -08008970 gen_and(b0, b1);
8971 break;
8972
8973 default:
8974 abort();
8975 }
8976 return b1;
8977}