156891Sfenner/*#define CHASE_CHAIN*/
217683Spst/*
339294Sfenner * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
417683Spst *	The Regents of the University of California.  All rights reserved.
517683Spst *
617683Spst * Redistribution and use in source and binary forms, with or without
717683Spst * modification, are permitted provided that: (1) source code distributions
817683Spst * retain the above copyright notice and this paragraph in its entirety, (2)
917683Spst * distributions including binary code include the above copyright notice and
1017683Spst * this paragraph in its entirety in the documentation or other materials
1117683Spst * provided with the distribution, and (3) all advertising materials mentioning
1217683Spst * features or use of this software display the following acknowledgement:
1317683Spst * ``This product includes software developed by the University of California,
1417683Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1517683Spst * the University nor the names of its contributors may be used to endorse
1617683Spst * or promote products derived from this software without specific prior
1717683Spst * written permission.
1817683Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1917683Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
2017683Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2156891Sfenner *
2256891Sfenner * $FreeBSD$
2317683Spst */
2417683Spst#ifndef lint
25127667Sbmsstatic const char rcsid[] _U_ =
26214518Srpaulo    "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.309 2008-12-23 20:13:29 guy Exp $ (LBL)";
2717683Spst#endif
2817683Spst
2975110Sfenner#ifdef HAVE_CONFIG_H
3075110Sfenner#include "config.h"
3175110Sfenner#endif
3275110Sfenner
33127667Sbms#ifdef WIN32
34127667Sbms#include <pcap-stdinc.h>
35127667Sbms#else /* WIN32 */
36214518Srpaulo#if HAVE_INTTYPES_H
37214518Srpaulo#include <inttypes.h>
38214518Srpaulo#elif HAVE_STDINT_H
39214518Srpaulo#include <stdint.h>
40214518Srpaulo#endif
41214518Srpaulo#ifdef HAVE_SYS_BITYPES_H
42214518Srpaulo#include <sys/bitypes.h>
43214518Srpaulo#endif
4417683Spst#include <sys/types.h>
4517683Spst#include <sys/socket.h>
46127667Sbms#endif /* WIN32 */
47127667Sbms
48127667Sbms/*
49127667Sbms * XXX - why was this included even on UNIX?
50127667Sbms */
51127667Sbms#ifdef __MINGW32__
52236167Sdelphij#include "ip6_misc.h"
53127667Sbms#endif
54127667Sbms
55127667Sbms#ifndef WIN32
56127667Sbms
5756891Sfenner#ifdef __NetBSD__
5856891Sfenner#include <sys/param.h>
5956891Sfenner#endif
6017683Spst
6117683Spst#include <netinet/in.h>
62214518Srpaulo#include <arpa/inet.h>
6317683Spst
64127667Sbms#endif /* WIN32 */
65127667Sbms
6617683Spst#include <stdlib.h>
6775110Sfenner#include <string.h>
6817683Spst#include <memory.h>
6917683Spst#include <setjmp.h>
7017683Spst#include <stdarg.h>
7117683Spst
72146771Ssam#ifdef MSDOS
73146771Ssam#include "pcap-dos.h"
74146771Ssam#endif
75146771Ssam
7617683Spst#include "pcap-int.h"
7717683Spst
7817683Spst#include "ethertype.h"
7917749Spst#include "nlpid.h"
8098533Sfenner#include "llc.h"
8117683Spst#include "gencode.h"
82190225Srpaulo#include "ieee80211.h"
83127667Sbms#include "atmuni31.h"
84127667Sbms#include "sunatmpos.h"
8539294Sfenner#include "ppp.h"
86190225Srpaulo#include "pcap/sll.h"
87214518Srpaulo#include "pcap/ipnet.h"
8898533Sfenner#include "arcnet.h"
89242484Sdelphij#if defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
90242484Sdelphij#include <linux/types.h>
91242484Sdelphij#include <linux/if_packet.h>
92242484Sdelphij#include <linux/filter.h>
93242484Sdelphij#endif
94172680Smlaier#ifdef HAVE_NET_PFVAR_H
95172680Smlaier#include <sys/socket.h>
96172680Smlaier#include <net/if.h>
97172680Smlaier#include <net/pfvar.h>
98172680Smlaier#include <net/if_pflog.h>
99172680Smlaier#endif
100127667Sbms#ifndef offsetof
101127667Sbms#define offsetof(s, e) ((size_t)&((s *)0)->e)
102127667Sbms#endif
10356891Sfenner#ifdef INET6
104127667Sbms#ifndef WIN32
105127667Sbms#include <netdb.h>	/* for "struct addrinfo" */
106127667Sbms#endif /* WIN32 */
10756891Sfenner#endif /*INET6*/
108190225Srpaulo#include <pcap/namedb.h>
10917683Spst
11075110Sfenner#define ETHERMTU	1500
11175110Sfenner
112252281Sdelphij#ifndef IPPROTO_HOPOPTS
113252281Sdelphij#define IPPROTO_HOPOPTS 0
114252281Sdelphij#endif
115252281Sdelphij#ifndef IPPROTO_ROUTING
116252281Sdelphij#define IPPROTO_ROUTING 43
117252281Sdelphij#endif
118252281Sdelphij#ifndef IPPROTO_FRAGMENT
119252281Sdelphij#define IPPROTO_FRAGMENT 44
120252281Sdelphij#endif
121252281Sdelphij#ifndef IPPROTO_DSTOPTS
122252281Sdelphij#define IPPROTO_DSTOPTS 60
123252281Sdelphij#endif
12498533Sfenner#ifndef IPPROTO_SCTP
12598533Sfenner#define IPPROTO_SCTP 132
12698533Sfenner#endif
12798533Sfenner
12817683Spst#ifdef HAVE_OS_PROTO_H
12917683Spst#include "os-proto.h"
13017683Spst#endif
13117683Spst
13217683Spst#define JMP(c) ((c)|BPF_JMP|BPF_K)
13317683Spst
13417683Spst/* Locals */
13517683Spststatic jmp_buf top_ctx;
13617683Spststatic pcap_t *bpf_pcap;
13717683Spst
138190225Srpaulo/* Hack for updating VLAN, MPLS, and PPPoE offsets. */
139172680Smlaier#ifdef WIN32
140172680Smlaierstatic u_int	orig_linktype = (u_int)-1, orig_nl = (u_int)-1, label_stack_depth = (u_int)-1;
141172680Smlaier#else
142162015Ssamstatic u_int	orig_linktype = -1U, orig_nl = -1U, label_stack_depth = -1U;
143172680Smlaier#endif
14498533Sfenner
14517683Spst/* XXX */
14617683Spst#ifdef PCAP_FDDIPAD
147146771Ssamstatic int	pcap_fddipad;
14817683Spst#endif
14917683Spst
15017683Spst/* VARARGS */
15175110Sfennervoid
15217683Spstbpf_error(const char *fmt, ...)
15317683Spst{
15417683Spst	va_list ap;
15517683Spst
15617683Spst	va_start(ap, fmt);
15717683Spst	if (bpf_pcap != NULL)
15875110Sfenner		(void)vsnprintf(pcap_geterr(bpf_pcap), PCAP_ERRBUF_SIZE,
15975110Sfenner		    fmt, ap);
16017683Spst	va_end(ap);
16117683Spst	longjmp(top_ctx, 1);
16217683Spst	/* NOTREACHED */
16317683Spst}
16417683Spst
165146771Ssamstatic void init_linktype(pcap_t *);
16617683Spst
167190225Srpaulostatic void init_regs(void);
16817683Spststatic int alloc_reg(void);
16917683Spststatic void free_reg(int);
17017683Spst
17117683Spststatic struct block *root;
17217683Spst
17317683Spst/*
174147897Ssam * Value passed to gen_load_a() to indicate what the offset argument
175147897Ssam * is relative to.
176147897Ssam */
177147897Ssamenum e_offrel {
178147897Ssam	OR_PACKET,	/* relative to the beginning of the packet */
179190225Srpaulo	OR_LINK,	/* relative to the beginning of the link-layer header */
180190225Srpaulo	OR_MACPL,	/* relative to the end of the MAC-layer header */
181147897Ssam	OR_NET,		/* relative to the network-layer header */
182147897Ssam	OR_NET_NOSNAP,	/* relative to the network-layer header, with no SNAP header at the link layer */
183147897Ssam	OR_TRAN_IPV4,	/* relative to the transport-layer header, with IPv4 network layer */
184147897Ssam	OR_TRAN_IPV6	/* relative to the transport-layer header, with IPv6 network layer */
185147897Ssam};
186147897Ssam
187214518Srpaulo#ifdef INET6
188147897Ssam/*
189214518Srpaulo * As errors are handled by a longjmp, anything allocated must be freed
190214518Srpaulo * in the longjmp handler, so it must be reachable from that handler.
191214518Srpaulo * One thing that's allocated is the result of pcap_nametoaddrinfo();
192214518Srpaulo * it must be freed with freeaddrinfo().  This variable points to any
193214518Srpaulo * addrinfo structure that would need to be freed.
194214518Srpaulo */
195214518Srpaulostatic struct addrinfo *ai;
196214518Srpaulo#endif
197214518Srpaulo
198214518Srpaulo/*
19917683Spst * We divy out chunks of memory rather than call malloc each time so
20017683Spst * we don't have to worry about leaking memory.  It's probably
201146771Ssam * not a big deal if all this memory was wasted but if this ever
20217683Spst * goes into a library that would probably not be a good idea.
203146771Ssam *
204146771Ssam * XXX - this *is* in a library....
20517683Spst */
20617683Spst#define NCHUNKS 16
20717683Spst#define CHUNK0SIZE 1024
20817683Spststruct chunk {
20917683Spst	u_int n_left;
21017683Spst	void *m;
21117683Spst};
21217683Spst
21317683Spststatic struct chunk chunks[NCHUNKS];
21417683Spststatic int cur_chunk;
21517683Spst
21617683Spststatic void *newchunk(u_int);
21717683Spststatic void freechunks(void);
21817683Spststatic inline struct block *new_block(int);
21917683Spststatic inline struct slist *new_stmt(int);
22017683Spststatic struct block *gen_retblk(int);
22117683Spststatic inline void syntax(void);
22217683Spst
22317683Spststatic void backpatch(struct block *, struct block *);
22417683Spststatic void merge(struct block *, struct block *);
225147897Ssamstatic struct block *gen_cmp(enum e_offrel, u_int, u_int, bpf_int32);
226147897Ssamstatic struct block *gen_cmp_gt(enum e_offrel, u_int, u_int, bpf_int32);
227147897Ssamstatic struct block *gen_cmp_ge(enum e_offrel, u_int, u_int, bpf_int32);
228147897Ssamstatic struct block *gen_cmp_lt(enum e_offrel, u_int, u_int, bpf_int32);
229147897Ssamstatic struct block *gen_cmp_le(enum e_offrel, u_int, u_int, bpf_int32);
230147897Ssamstatic struct block *gen_mcmp(enum e_offrel, u_int, u_int, bpf_int32,
231147897Ssam    bpf_u_int32);
232147897Ssamstatic struct block *gen_bcmp(enum e_offrel, u_int, u_int, const u_char *);
233147897Ssamstatic struct block *gen_ncmp(enum e_offrel, bpf_u_int32, bpf_u_int32,
234147897Ssam    bpf_u_int32, bpf_u_int32, int, bpf_int32);
235147897Ssamstatic struct slist *gen_load_llrel(u_int, u_int);
236190225Srpaulostatic struct slist *gen_load_macplrel(u_int, u_int);
237147897Ssamstatic struct slist *gen_load_a(enum e_offrel, u_int, u_int);
238147897Ssamstatic struct slist *gen_loadx_iphdrlen(void);
23917683Spststatic struct block *gen_uncond(int);
24017683Spststatic inline struct block *gen_true(void);
24117683Spststatic inline struct block *gen_false(void);
242127667Sbmsstatic struct block *gen_ether_linktype(int);
243214518Srpaulostatic struct block *gen_ipnet_linktype(int);
244146771Ssamstatic struct block *gen_linux_sll_linktype(int);
245190225Srpaulostatic struct slist *gen_load_prism_llprefixlen(void);
246190225Srpaulostatic struct slist *gen_load_avs_llprefixlen(void);
247190225Srpaulostatic struct slist *gen_load_radiotap_llprefixlen(void);
248190225Srpaulostatic struct slist *gen_load_ppi_llprefixlen(void);
249190225Srpaulostatic void insert_compute_vloffsets(struct block *);
250147897Ssamstatic struct slist *gen_llprefixlen(void);
251190225Srpaulostatic struct slist *gen_off_macpl(void);
252190225Srpaulostatic int ethertype_to_ppptype(int);
25317683Spststatic struct block *gen_linktype(int);
254190225Srpaulostatic struct block *gen_snap(bpf_u_int32, bpf_u_int32);
255147897Ssamstatic struct block *gen_llc_linktype(int);
25617683Spststatic struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int);
25756891Sfenner#ifdef INET6
25856891Sfennerstatic struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int);
25956891Sfenner#endif
26098533Sfennerstatic struct block *gen_ahostop(const u_char *, int);
26117683Spststatic struct block *gen_ehostop(const u_char *, int);
26217683Spststatic struct block *gen_fhostop(const u_char *, int);
26375110Sfennerstatic struct block *gen_thostop(const u_char *, int);
264127667Sbmsstatic struct block *gen_wlanhostop(const u_char *, int);
265127667Sbmsstatic struct block *gen_ipfchostop(const u_char *, int);
266147897Ssamstatic struct block *gen_dnhostop(bpf_u_int32, int);
267162015Ssamstatic struct block *gen_mpls_linktype(int);
268172680Smlaierstatic struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int, int);
26956891Sfenner#ifdef INET6
270172680Smlaierstatic struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int, int);
27156891Sfenner#endif
27275110Sfenner#ifndef INET6
27317683Spststatic struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);
27475110Sfenner#endif
27517683Spststatic struct block *gen_ipfrag(void);
27617683Spststatic struct block *gen_portatom(int, bpf_int32);
277147897Ssamstatic struct block *gen_portrangeatom(int, bpf_int32, bpf_int32);
27856891Sfennerstatic struct block *gen_portatom6(int, bpf_int32);
279147897Ssamstatic struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32);
28017683Spststruct block *gen_portop(int, int, int);
28117683Spststatic struct block *gen_port(int, int, int);
282147897Ssamstruct block *gen_portrangeop(int, int, int, int);
283147897Ssamstatic struct block *gen_portrange(int, int, int, int);
28456891Sfennerstruct block *gen_portop6(int, int, int);
28556891Sfennerstatic struct block *gen_port6(int, int, int);
286147897Ssamstruct block *gen_portrangeop6(int, int, int, int);
287147897Ssamstatic struct block *gen_portrange6(int, int, int, int);
28817683Spststatic int lookup_proto(const char *, int);
28975110Sfennerstatic struct block *gen_protochain(int, int, int);
29017683Spststatic struct block *gen_proto(int, int, int);
29117683Spststatic struct slist *xfer_to_x(struct arth *);
29217683Spststatic struct slist *xfer_to_a(struct arth *);
293127667Sbmsstatic struct block *gen_mac_multicast(int);
29417683Spststatic struct block *gen_len(int, int);
295190225Srpaulostatic struct block *gen_check_802_11_data_frame(void);
29617683Spst
297172680Smlaierstatic struct block *gen_ppi_dlt_check(void);
298127667Sbmsstatic struct block *gen_msg_abbrev(int type);
299127667Sbms
30017683Spststatic void *
30117683Spstnewchunk(n)
30217683Spst	u_int n;
30317683Spst{
30417683Spst	struct chunk *cp;
305127667Sbms	int k;
306127667Sbms	size_t size;
30717683Spst
30856891Sfenner#ifndef __NetBSD__
30917683Spst	/* XXX Round up to nearest long. */
31017683Spst	n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);
31156891Sfenner#else
31256891Sfenner	/* XXX Round up to structure boundary. */
31356891Sfenner	n = ALIGN(n);
31456891Sfenner#endif
31517683Spst
31617683Spst	cp = &chunks[cur_chunk];
31717683Spst	if (n > cp->n_left) {
31817683Spst		++cp, k = ++cur_chunk;
31917683Spst		if (k >= NCHUNKS)
32017683Spst			bpf_error("out of memory");
32117683Spst		size = CHUNK0SIZE << k;
32217683Spst		cp->m = (void *)malloc(size);
323127667Sbms		if (cp->m == NULL)
324127667Sbms			bpf_error("out of memory");
32517683Spst		memset((char *)cp->m, 0, size);
32617683Spst		cp->n_left = size;
32717683Spst		if (n > size)
32817683Spst			bpf_error("out of memory");
32917683Spst	}
33017683Spst	cp->n_left -= n;
33117683Spst	return (void *)((char *)cp->m + cp->n_left);
33217683Spst}
33317683Spst
33417683Spststatic void
33517683Spstfreechunks()
33617683Spst{
33717683Spst	int i;
33817683Spst
33917683Spst	cur_chunk = 0;
34017683Spst	for (i = 0; i < NCHUNKS; ++i)
34117683Spst		if (chunks[i].m != NULL) {
34217683Spst			free(chunks[i].m);
34317683Spst			chunks[i].m = NULL;
34417683Spst		}
34517683Spst}
34617683Spst
34717683Spst/*
34817683Spst * A strdup whose allocations are freed after code generation is over.
34917683Spst */
35017683Spstchar *
35117683Spstsdup(s)
35217683Spst	register const char *s;
35317683Spst{
35417683Spst	int n = strlen(s) + 1;
35517683Spst	char *cp = newchunk(n);
35617683Spst
35775110Sfenner	strlcpy(cp, s, n);
35817683Spst	return (cp);
35917683Spst}
36017683Spst
36117683Spststatic inline struct block *
36217683Spstnew_block(code)
36317683Spst	int code;
36417683Spst{
36517683Spst	struct block *p;
36617683Spst
36717683Spst	p = (struct block *)newchunk(sizeof(*p));
36817683Spst	p->s.code = code;
36917683Spst	p->head = p;
37017683Spst
37117683Spst	return p;
37217683Spst}
37317683Spst
37417683Spststatic inline struct slist *
37517683Spstnew_stmt(code)
37617683Spst	int code;
37717683Spst{
37817683Spst	struct slist *p;
37917683Spst
38017683Spst	p = (struct slist *)newchunk(sizeof(*p));
38117683Spst	p->s.code = code;
38217683Spst
38317683Spst	return p;
38417683Spst}
38517683Spst
38617683Spststatic struct block *
38717683Spstgen_retblk(v)
38817683Spst	int v;
38917683Spst{
39017683Spst	struct block *b = new_block(BPF_RET|BPF_K);
39117683Spst
39217683Spst	b->s.k = v;
39317683Spst	return b;
39417683Spst}
39517683Spst
39617683Spststatic inline void
39717683Spstsyntax()
39817683Spst{
39917683Spst	bpf_error("syntax error in filter expression");
40017683Spst}
40117683Spst
40217683Spststatic bpf_u_int32 netmask;
40317683Spststatic int snaplen;
40456891Sfennerint no_optimize;
405214518Srpaulo#ifdef WIN32
406214518Srpaulostatic int
407214518Srpaulopcap_compile_unsafe(pcap_t *p, struct bpf_program *program,
408214518Srpaulo	     const char *buf, int optimize, bpf_u_int32 mask);
40917683Spst
41017683Spstint
41117683Spstpcap_compile(pcap_t *p, struct bpf_program *program,
412172680Smlaier	     const char *buf, int optimize, bpf_u_int32 mask)
41317683Spst{
414214518Srpaulo	int result;
415214518Srpaulo
416214518Srpaulo	EnterCriticalSection(&g_PcapCompileCriticalSection);
417214518Srpaulo
418214518Srpaulo	result = pcap_compile_unsafe(p, program, buf, optimize, mask);
419214518Srpaulo
420214518Srpaulo	LeaveCriticalSection(&g_PcapCompileCriticalSection);
421214518Srpaulo
422214518Srpaulo	return result;
423214518Srpaulo}
424214518Srpaulo
425214518Srpaulostatic int
426214518Srpaulopcap_compile_unsafe(pcap_t *p, struct bpf_program *program,
427214518Srpaulo	     const char *buf, int optimize, bpf_u_int32 mask)
428214518Srpaulo#else /* WIN32 */
429214518Srpauloint
430214518Srpaulopcap_compile(pcap_t *p, struct bpf_program *program,
431214518Srpaulo	     const char *buf, int optimize, bpf_u_int32 mask)
432214518Srpaulo#endif /* WIN32 */
433214518Srpaulo{
43417683Spst	extern int n_errors;
435172680Smlaier	const char * volatile xbuf = buf;
436242484Sdelphij	u_int len;
43717683Spst
438252281Sdelphij	/*
439252281Sdelphij	 * If this pcap_t hasn't been activated, it doesn't have a
440252281Sdelphij	 * link-layer type, so we can't use it.
441252281Sdelphij	 */
442252281Sdelphij	if (!p->activated) {
443252281Sdelphij		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
444252281Sdelphij		    "not-yet-activated pcap_t passed to pcap_compile");
445252281Sdelphij		return (-1);
446252281Sdelphij	}
44756891Sfenner	no_optimize = 0;
44817683Spst	n_errors = 0;
44917683Spst	root = NULL;
45017683Spst	bpf_pcap = p;
451190225Srpaulo	init_regs();
45217683Spst	if (setjmp(top_ctx)) {
453214518Srpaulo#ifdef INET6
454214518Srpaulo		if (ai != NULL) {
455214518Srpaulo			freeaddrinfo(ai);
456214518Srpaulo			ai = NULL;
457214518Srpaulo		}
458214518Srpaulo#endif
45975110Sfenner		lex_cleanup();
46017683Spst		freechunks();
46117683Spst		return (-1);
46217683Spst	}
46317683Spst
46417683Spst	netmask = mask;
465127667Sbms
46617683Spst	snaplen = pcap_snapshot(p);
46775110Sfenner	if (snaplen == 0) {
46875110Sfenner		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
46975110Sfenner			 "snaplen of 0 rejects all packets");
47075110Sfenner		return -1;
47175110Sfenner	}
47217683Spst
473172680Smlaier	lex_init(xbuf ? xbuf : "");
474146771Ssam	init_linktype(p);
47517683Spst	(void)pcap_parse();
47617683Spst
47717683Spst	if (n_errors)
47817683Spst		syntax();
47917683Spst
48017683Spst	if (root == NULL)
48117683Spst		root = gen_retblk(snaplen);
48217683Spst
48356891Sfenner	if (optimize && !no_optimize) {
48456891Sfenner		bpf_optimize(&root);
48556891Sfenner		if (root == NULL ||
48656891Sfenner		    (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0))
48756891Sfenner			bpf_error("expression rejects all packets");
48856891Sfenner	}
48956891Sfenner	program->bf_insns = icode_to_fcode(root, &len);
49056891Sfenner	program->bf_len = len;
49156891Sfenner
49275110Sfenner	lex_cleanup();
49356891Sfenner	freechunks();
49456891Sfenner	return (0);
49556891Sfenner}
49656891Sfenner
49756891Sfenner/*
49856891Sfenner * entry point for using the compiler with no pcap open
49956891Sfenner * pass in all the stuff that is needed explicitly instead.
50056891Sfenner */
50156891Sfennerint
50256891Sfennerpcap_compile_nopcap(int snaplen_arg, int linktype_arg,
50356891Sfenner		    struct bpf_program *program,
504172680Smlaier	     const char *buf, int optimize, bpf_u_int32 mask)
50556891Sfenner{
50675110Sfenner	pcap_t *p;
50775110Sfenner	int ret;
50856891Sfenner
50975110Sfenner	p = pcap_open_dead(linktype_arg, snaplen_arg);
51075110Sfenner	if (p == NULL)
51156891Sfenner		return (-1);
51275110Sfenner	ret = pcap_compile(p, program, buf, optimize, mask);
51375110Sfenner	pcap_close(p);
51475110Sfenner	return (ret);
51575110Sfenner}
51656891Sfenner
51775110Sfenner/*
51875110Sfenner * Clean up a "struct bpf_program" by freeing all the memory allocated
51975110Sfenner * in it.
52075110Sfenner */
52175110Sfennervoid
52275110Sfennerpcap_freecode(struct bpf_program *program)
52375110Sfenner{
52475110Sfenner	program->bf_len = 0;
52575110Sfenner	if (program->bf_insns != NULL) {
52675110Sfenner		free((char *)program->bf_insns);
52775110Sfenner		program->bf_insns = NULL;
52817683Spst	}
52917683Spst}
53017683Spst
53117683Spst/*
53217683Spst * Backpatch the blocks in 'list' to 'target'.  The 'sense' field indicates
53317683Spst * which of the jt and jf fields has been resolved and which is a pointer
53417683Spst * back to another unresolved block (or nil).  At least one of the fields
53517683Spst * in each block is already resolved.
53617683Spst */
53717683Spststatic void
53817683Spstbackpatch(list, target)
53917683Spst	struct block *list, *target;
54017683Spst{
54117683Spst	struct block *next;
54217683Spst
54317683Spst	while (list) {
54417683Spst		if (!list->sense) {
54517683Spst			next = JT(list);
54617683Spst			JT(list) = target;
54717683Spst		} else {
54817683Spst			next = JF(list);
54917683Spst			JF(list) = target;
55017683Spst		}
55117683Spst		list = next;
55217683Spst	}
55317683Spst}
55417683Spst
55517683Spst/*
55617683Spst * Merge the lists in b0 and b1, using the 'sense' field to indicate
55717683Spst * which of jt and jf is the link.
55817683Spst */
55917683Spststatic void
56017683Spstmerge(b0, b1)
56117683Spst	struct block *b0, *b1;
56217683Spst{
56317683Spst	register struct block **p = &b0;
56417683Spst
56517683Spst	/* Find end of list. */
56617683Spst	while (*p)
56717683Spst		p = !((*p)->sense) ? &JT(*p) : &JF(*p);
56817683Spst
56917683Spst	/* Concatenate the lists. */
57017683Spst	*p = b1;
57117683Spst}
57217683Spst
57317683Spstvoid
57417683Spstfinish_parse(p)
57517683Spst	struct block *p;
57617683Spst{
577172680Smlaier	struct block *ppi_dlt_check;
578172680Smlaier
579147897Ssam	/*
580147897Ssam	 * Insert before the statements of the first (root) block any
581147897Ssam	 * statements needed to load the lengths of any variable-length
582147897Ssam	 * headers into registers.
583147897Ssam	 *
584147897Ssam	 * XXX - a fancier strategy would be to insert those before the
585147897Ssam	 * statements of all blocks that use those lengths and that
586147897Ssam	 * have no predecessors that use them, so that we only compute
587147897Ssam	 * the lengths if we need them.  There might be even better
588190225Srpaulo	 * approaches than that.
589190225Srpaulo	 *
590190225Srpaulo	 * However, those strategies would be more complicated, and
591190225Srpaulo	 * as we don't generate code to compute a length if the
592190225Srpaulo	 * program has no tests that use the length, and as most
593190225Srpaulo	 * tests will probably use those lengths, we would just
594190225Srpaulo	 * postpone computing the lengths so that it's not done
595190225Srpaulo	 * for tests that fail early, and it's not clear that's
596190225Srpaulo	 * worth the effort.
597147897Ssam	 */
598190225Srpaulo	insert_compute_vloffsets(p->head);
599190225Srpaulo
600190225Srpaulo	/*
601190225Srpaulo	 * For DLT_PPI captures, generate a check of the per-packet
602190225Srpaulo	 * DLT value to make sure it's DLT_IEEE802_11.
603190225Srpaulo	 */
604190225Srpaulo	ppi_dlt_check = gen_ppi_dlt_check();
605190225Srpaulo	if (ppi_dlt_check != NULL)
606190225Srpaulo		gen_and(ppi_dlt_check, p);
607172680Smlaier
608190225Srpaulo	backpatch(p, gen_retblk(snaplen));
609190225Srpaulo	p->sense = !p->sense;
610190225Srpaulo	backpatch(p, gen_retblk(0));
611190225Srpaulo	root = p->head;
61217683Spst}
61317683Spst
61417683Spstvoid
61517683Spstgen_and(b0, b1)
61617683Spst	struct block *b0, *b1;
61717683Spst{
61817683Spst	backpatch(b0, b1->head);
61917683Spst	b0->sense = !b0->sense;
62017683Spst	b1->sense = !b1->sense;
62117683Spst	merge(b1, b0);
62217683Spst	b1->sense = !b1->sense;
62317683Spst	b1->head = b0->head;
62417683Spst}
62517683Spst
62617683Spstvoid
62717683Spstgen_or(b0, b1)
62817683Spst	struct block *b0, *b1;
62917683Spst{
63017683Spst	b0->sense = !b0->sense;
63117683Spst	backpatch(b0, b1->head);
63217683Spst	b0->sense = !b0->sense;
63317683Spst	merge(b1, b0);
63417683Spst	b1->head = b0->head;
63517683Spst}
63617683Spst
63717683Spstvoid
63817683Spstgen_not(b)
63917683Spst	struct block *b;
64017683Spst{
64117683Spst	b->sense = !b->sense;
64217683Spst}
64317683Spst
64417683Spststatic struct block *
645147897Ssamgen_cmp(offrel, offset, size, v)
646147897Ssam	enum e_offrel offrel;
64717683Spst	u_int offset, size;
64817683Spst	bpf_int32 v;
64917683Spst{
650147897Ssam	return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v);
651147897Ssam}
65217683Spst
653147897Ssamstatic struct block *
654147897Ssamgen_cmp_gt(offrel, offset, size, v)
655147897Ssam	enum e_offrel offrel;
656147897Ssam	u_int offset, size;
657147897Ssam	bpf_int32 v;
658147897Ssam{
659147897Ssam	return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 0, v);
660147897Ssam}
66117683Spst
662147897Ssamstatic struct block *
663147897Ssamgen_cmp_ge(offrel, offset, size, v)
664147897Ssam	enum e_offrel offrel;
665147897Ssam	u_int offset, size;
666147897Ssam	bpf_int32 v;
667147897Ssam{
668147897Ssam	return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 0, v);
669147897Ssam}
67017683Spst
671147897Ssamstatic struct block *
672147897Ssamgen_cmp_lt(offrel, offset, size, v)
673147897Ssam	enum e_offrel offrel;
674147897Ssam	u_int offset, size;
675147897Ssam	bpf_int32 v;
676147897Ssam{
677147897Ssam	return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 1, v);
67817683Spst}
67917683Spst
68017683Spststatic struct block *
681147897Ssamgen_cmp_le(offrel, offset, size, v)
682147897Ssam	enum e_offrel offrel;
68375110Sfenner	u_int offset, size;
68475110Sfenner	bpf_int32 v;
68575110Sfenner{
686147897Ssam	return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 1, v);
68775110Sfenner}
68875110Sfenner
68975110Sfennerstatic struct block *
690147897Ssamgen_mcmp(offrel, offset, size, v, mask)
691147897Ssam	enum e_offrel offrel;
69217683Spst	u_int offset, size;
69317683Spst	bpf_int32 v;
69417683Spst	bpf_u_int32 mask;
69517683Spst{
696147897Ssam	return gen_ncmp(offrel, offset, size, mask, BPF_JEQ, 0, v);
69717683Spst}
69817683Spst
69917683Spststatic struct block *
700147897Ssamgen_bcmp(offrel, offset, size, v)
701147897Ssam	enum e_offrel offrel;
70217683Spst	register u_int offset, size;
70317683Spst	register const u_char *v;
70417683Spst{
70517683Spst	register struct block *b, *tmp;
70617683Spst
70717683Spst	b = NULL;
70817683Spst	while (size >= 4) {
70917683Spst		register const u_char *p = &v[size - 4];
71026178Sfenner		bpf_int32 w = ((bpf_int32)p[0] << 24) |
71126178Sfenner		    ((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3];
71217683Spst
713147897Ssam		tmp = gen_cmp(offrel, offset + size - 4, BPF_W, w);
71417683Spst		if (b != NULL)
71517683Spst			gen_and(b, tmp);
71617683Spst		b = tmp;
71717683Spst		size -= 4;
71817683Spst	}
71917683Spst	while (size >= 2) {
72017683Spst		register const u_char *p = &v[size - 2];
72126178Sfenner		bpf_int32 w = ((bpf_int32)p[0] << 8) | p[1];
72217683Spst
723147897Ssam		tmp = gen_cmp(offrel, offset + size - 2, BPF_H, w);
72417683Spst		if (b != NULL)
72517683Spst			gen_and(b, tmp);
72617683Spst		b = tmp;
72717683Spst		size -= 2;
72817683Spst	}
72917683Spst	if (size > 0) {
730147897Ssam		tmp = gen_cmp(offrel, offset, BPF_B, (bpf_int32)v[0]);
73117683Spst		if (b != NULL)
73217683Spst			gen_and(b, tmp);
73317683Spst		b = tmp;
73417683Spst	}
73517683Spst	return b;
73617683Spst}
73717683Spst
738147897Ssam/*
739147897Ssam * AND the field of size "size" at offset "offset" relative to the header
740147897Ssam * specified by "offrel" with "mask", and compare it with the value "v"
741147897Ssam * with the test specified by "jtype"; if "reverse" is true, the test
742147897Ssam * should test the opposite of "jtype".
743147897Ssam */
744127667Sbmsstatic struct block *
745147897Ssamgen_ncmp(offrel, offset, size, mask, jtype, reverse, v)
746147897Ssam	enum e_offrel offrel;
747147897Ssam	bpf_int32 v;
748147897Ssam	bpf_u_int32 offset, size, mask, jtype;
749127667Sbms	int reverse;
750127667Sbms{
751147897Ssam	struct slist *s, *s2;
752127667Sbms	struct block *b;
753146771Ssam
754147897Ssam	s = gen_load_a(offrel, offset, size);
755146771Ssam
756127667Sbms	if (mask != 0xffffffff) {
757147897Ssam		s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
758147897Ssam		s2->s.k = mask;
759147897Ssam		sappend(s, s2);
760127667Sbms	}
761146771Ssam
762127667Sbms	b = new_block(JMP(jtype));
763127667Sbms	b->stmts = s;
764147897Ssam	b->s.k = v;
765127667Sbms	if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE))
766127667Sbms		gen_not(b);
767127667Sbms	return b;
768127667Sbms}
769127667Sbms
77017683Spst/*
77117683Spst * Various code constructs need to know the layout of the data link
772147897Ssam * layer.  These variables give the necessary offsets from the beginning
773147897Ssam * of the packet data.
77417683Spst */
775127667Sbms
776127667Sbms/*
777172680Smlaier * This is the offset of the beginning of the link-layer header from
778172680Smlaier * the beginning of the raw packet data.
779172680Smlaier *
780147897Ssam * It's usually 0, except for 802.11 with a fixed-length radio header.
781172680Smlaier * (For 802.11 with a variable-length radio header, we have to generate
782172680Smlaier * code to compute that offset; off_ll is 0 in that case.)
783147897Ssam */
784147897Ssamstatic u_int off_ll;
785147897Ssam
786147897Ssam/*
787190225Srpaulo * If there's a variable-length header preceding the link-layer header,
788190225Srpaulo * "reg_off_ll" is the register number for a register containing the
789190225Srpaulo * length of that header, and therefore the offset of the link-layer
790190225Srpaulo * header from the beginning of the raw packet data.  Otherwise,
791190225Srpaulo * "reg_off_ll" is -1.
792190225Srpaulo */
793190225Srpaulostatic int reg_off_ll;
794190225Srpaulo
795190225Srpaulo/*
796190225Srpaulo * This is the offset of the beginning of the MAC-layer header from
797190225Srpaulo * the beginning of the link-layer header.
798172680Smlaier * It's usually 0, except for ATM LANE, where it's the offset, relative
799236167Sdelphij * to the beginning of the raw packet data, of the Ethernet header, and
800236167Sdelphij * for Ethernet with various additional information.
801127667Sbms */
802127667Sbmsstatic u_int off_mac;
803127667Sbms
804127667Sbms/*
805190225Srpaulo * This is the offset of the beginning of the MAC-layer payload,
806190225Srpaulo * from the beginning of the raw packet data.
807190225Srpaulo *
808190225Srpaulo * I.e., it's the sum of the length of the link-layer header (without,
809190225Srpaulo * for example, any 802.2 LLC header, so it's the MAC-layer
810190225Srpaulo * portion of that header), plus any prefix preceding the
811190225Srpaulo * link-layer header.
812190225Srpaulo */
813190225Srpaulostatic u_int off_macpl;
814190225Srpaulo
815190225Srpaulo/*
816190225Srpaulo * This is 1 if the offset of the beginning of the MAC-layer payload
817190225Srpaulo * from the beginning of the link-layer header is variable-length.
818190225Srpaulo */
819190225Srpaulostatic int off_macpl_is_variable;
820190225Srpaulo
821190225Srpaulo/*
822190225Srpaulo * If the link layer has variable_length headers, "reg_off_macpl"
823190225Srpaulo * is the register number for a register containing the length of the
824190225Srpaulo * link-layer header plus the length of any variable-length header
825190225Srpaulo * preceding the link-layer header.  Otherwise, "reg_off_macpl"
826190225Srpaulo * is -1.
827190225Srpaulo */
828190225Srpaulostatic int reg_off_macpl;
829190225Srpaulo
830190225Srpaulo/*
831127667Sbms * "off_linktype" is the offset to information in the link-layer header
832172680Smlaier * giving the packet type.  This offset is relative to the beginning
833172680Smlaier * of the link-layer header (i.e., it doesn't include off_ll).
834127667Sbms *
835127667Sbms * For Ethernet, it's the offset of the Ethernet type field.
836127667Sbms *
837127667Sbms * For link-layer types that always use 802.2 headers, it's the
838127667Sbms * offset of the LLC header.
839127667Sbms *
840127667Sbms * For PPP, it's the offset of the PPP type field.
841127667Sbms *
842127667Sbms * For Cisco HDLC, it's the offset of the CHDLC type field.
843127667Sbms *
844127667Sbms * For BSD loopback, it's the offset of the AF_ value.
845127667Sbms *
846127667Sbms * For Linux cooked sockets, it's the offset of the type field.
847127667Sbms *
848127667Sbms * It's set to -1 for no encapsulation, in which case, IP is assumed.
849127667Sbms */
85017683Spststatic u_int off_linktype;
851127667Sbms
852127667Sbms/*
853190225Srpaulo * TRUE if "pppoes" appeared in the filter; it causes link-layer type
854190225Srpaulo * checks to check the PPP header, assumed to follow a LAN-style link-
855190225Srpaulo * layer header and a PPPoE session header.
856190225Srpaulo */
857190225Srpaulostatic int is_pppoes = 0;
858190225Srpaulo
859190225Srpaulo/*
860127667Sbms * TRUE if the link layer includes an ATM pseudo-header.
861127667Sbms */
862127667Sbmsstatic int is_atm = 0;
863127667Sbms
864127667Sbms/*
865127667Sbms * TRUE if "lane" appeared in the filter; it causes us to generate
866127667Sbms * code that assumes LANE rather than LLC-encapsulated traffic in SunATM.
867127667Sbms */
868127667Sbmsstatic int is_lane = 0;
869127667Sbms
870127667Sbms/*
871127667Sbms * These are offsets for the ATM pseudo-header.
872127667Sbms */
873127667Sbmsstatic u_int off_vpi;
874127667Sbmsstatic u_int off_vci;
875127667Sbmsstatic u_int off_proto;
876127667Sbms
877127667Sbms/*
878172680Smlaier * These are offsets for the MTP2 fields.
879172680Smlaier */
880172680Smlaierstatic u_int off_li;
881172680Smlaier
882172680Smlaier/*
883147897Ssam * These are offsets for the MTP3 fields.
884147897Ssam */
885147897Ssamstatic u_int off_sio;
886147897Ssamstatic u_int off_opc;
887147897Ssamstatic u_int off_dpc;
888147897Ssamstatic u_int off_sls;
889147897Ssam
890147897Ssam/*
891127667Sbms * This is the offset of the first byte after the ATM pseudo_header,
892127667Sbms * or -1 if there is no ATM pseudo-header.
893127667Sbms */
894127667Sbmsstatic u_int off_payload;
895127667Sbms
896127667Sbms/*
897127667Sbms * These are offsets to the beginning of the network-layer header.
898190225Srpaulo * They are relative to the beginning of the MAC-layer payload (i.e.,
899190225Srpaulo * they don't include off_ll or off_macpl).
900127667Sbms *
901127667Sbms * If the link layer never uses 802.2 LLC:
902127667Sbms *
903127667Sbms *	"off_nl" and "off_nl_nosnap" are the same.
904127667Sbms *
905127667Sbms * If the link layer always uses 802.2 LLC:
906127667Sbms *
907127667Sbms *	"off_nl" is the offset if there's a SNAP header following
908127667Sbms *	the 802.2 header;
909127667Sbms *
910127667Sbms *	"off_nl_nosnap" is the offset if there's no SNAP header.
911127667Sbms *
912127667Sbms * If the link layer is Ethernet:
913127667Sbms *
914127667Sbms *	"off_nl" is the offset if the packet is an Ethernet II packet
915127667Sbms *	(we assume no 802.3+802.2+SNAP);
916127667Sbms *
917127667Sbms *	"off_nl_nosnap" is the offset if the packet is an 802.3 packet
918127667Sbms *	with an 802.2 header following it.
919127667Sbms */
92017683Spststatic u_int off_nl;
921127667Sbmsstatic u_int off_nl_nosnap;
922127667Sbms
92317683Spststatic int linktype;
92417683Spst
92517683Spststatic void
926146771Ssaminit_linktype(p)
927146771Ssam	pcap_t *p;
92817683Spst{
929146771Ssam	linktype = pcap_datalink(p);
930146771Ssam#ifdef PCAP_FDDIPAD
931146771Ssam	pcap_fddipad = p->fddipad;
932146771Ssam#endif
93317683Spst
934127667Sbms	/*
935127667Sbms	 * Assume it's not raw ATM with a pseudo-header, for now.
936127667Sbms	 */
937127667Sbms	off_mac = 0;
938127667Sbms	is_atm = 0;
939127667Sbms	is_lane = 0;
940127667Sbms	off_vpi = -1;
941127667Sbms	off_vci = -1;
942127667Sbms	off_proto = -1;
943127667Sbms	off_payload = -1;
944127667Sbms
945162015Ssam	/*
946190225Srpaulo	 * And that we're not doing PPPoE.
947190225Srpaulo	 */
948190225Srpaulo	is_pppoes = 0;
949190225Srpaulo
950190225Srpaulo	/*
951162015Ssam	 * And assume we're not doing SS7.
952162015Ssam	 */
953172680Smlaier	off_li = -1;
954147897Ssam	off_sio = -1;
955147897Ssam	off_opc = -1;
956147897Ssam	off_dpc = -1;
957147897Ssam	off_sls = -1;
958147897Ssam
959147897Ssam	/*
960190225Srpaulo	 * Also assume it's not 802.11.
961147897Ssam	 */
962147897Ssam	off_ll = 0;
963190225Srpaulo	off_macpl = 0;
964190225Srpaulo	off_macpl_is_variable = 0;
965147897Ssam
96698533Sfenner	orig_linktype = -1;
96798533Sfenner	orig_nl = -1;
968162015Ssam        label_stack_depth = 0;
96998533Sfenner
970190225Srpaulo	reg_off_ll = -1;
971190225Srpaulo	reg_off_macpl = -1;
972147897Ssam
973146771Ssam	switch (linktype) {
97417683Spst
97598533Sfenner	case DLT_ARCNET:
97698533Sfenner		off_linktype = 2;
977190225Srpaulo		off_macpl = 6;
978190225Srpaulo		off_nl = 0;		/* XXX in reality, variable! */
979190225Srpaulo		off_nl_nosnap = 0;	/* no 802.2 LLC */
98098533Sfenner		return;
98198533Sfenner
982127667Sbms	case DLT_ARCNET_LINUX:
983127667Sbms		off_linktype = 4;
984190225Srpaulo		off_macpl = 8;
985190225Srpaulo		off_nl = 0;		/* XXX in reality, variable! */
986190225Srpaulo		off_nl_nosnap = 0;	/* no 802.2 LLC */
987127667Sbms		return;
988127667Sbms
98917683Spst	case DLT_EN10MB:
99017683Spst		off_linktype = 12;
991190225Srpaulo		off_macpl = 14;		/* Ethernet header length */
992190225Srpaulo		off_nl = 0;		/* Ethernet II */
993190225Srpaulo		off_nl_nosnap = 3;	/* 802.3+802.2 */
99417683Spst		return;
99517683Spst
99617683Spst	case DLT_SLIP:
99717683Spst		/*
99817683Spst		 * SLIP doesn't have a link level type.  The 16 byte
99917683Spst		 * header is hacked into our SLIP driver.
100017683Spst		 */
100117683Spst		off_linktype = -1;
1002190225Srpaulo		off_macpl = 16;
1003190225Srpaulo		off_nl = 0;
1004190225Srpaulo		off_nl_nosnap = 0;	/* no 802.2 LLC */
100517683Spst		return;
100617683Spst
100739294Sfenner	case DLT_SLIP_BSDOS:
100839294Sfenner		/* XXX this may be the same as the DLT_PPP_BSDOS case */
100939294Sfenner		off_linktype = -1;
101039294Sfenner		/* XXX end */
1011190225Srpaulo		off_macpl = 24;
1012190225Srpaulo		off_nl = 0;
1013190225Srpaulo		off_nl_nosnap = 0;	/* no 802.2 LLC */
101439294Sfenner		return;
101539294Sfenner
101617683Spst	case DLT_NULL:
101775110Sfenner	case DLT_LOOP:
101817683Spst		off_linktype = 0;
1019190225Srpaulo		off_macpl = 4;
1020190225Srpaulo		off_nl = 0;
1021190225Srpaulo		off_nl_nosnap = 0;	/* no 802.2 LLC */
102217683Spst		return;
102317683Spst
1024127667Sbms	case DLT_ENC:
1025127667Sbms		off_linktype = 0;
1026190225Srpaulo		off_macpl = 12;
1027190225Srpaulo		off_nl = 0;
1028190225Srpaulo		off_nl_nosnap = 0;	/* no 802.2 LLC */
1029127667Sbms		return;
1030127667Sbms
103117683Spst	case DLT_PPP:
1032146771Ssam	case DLT_PPP_PPPD:
103398533Sfenner	case DLT_C_HDLC:		/* BSD/OS Cisco HDLC */
103498533Sfenner	case DLT_PPP_SERIAL:		/* NetBSD sync/async serial PPP */
103517683Spst		off_linktype = 2;
1036190225Srpaulo		off_macpl = 4;
1037190225Srpaulo		off_nl = 0;
1038190225Srpaulo		off_nl_nosnap = 0;	/* no 802.2 LLC */
103917683Spst		return;
104017683Spst
104198533Sfenner	case DLT_PPP_ETHER:
104298533Sfenner		/*
104398533Sfenner		 * This does no include the Ethernet header, and
104498533Sfenner		 * only covers session state.
104598533Sfenner		 */
104698533Sfenner		off_linktype = 6;
1047190225Srpaulo		off_macpl = 8;
1048190225Srpaulo		off_nl = 0;
1049190225Srpaulo		off_nl_nosnap = 0;	/* no 802.2 LLC */
105098533Sfenner		return;
105198533Sfenner
105239294Sfenner	case DLT_PPP_BSDOS:
105339294Sfenner		off_linktype = 5;
1054190225Srpaulo		off_macpl = 24;
1055190225Srpaulo		off_nl = 0;
1056190225Srpaulo		off_nl_nosnap = 0;	/* no 802.2 LLC */
105739294Sfenner		return;
105839294Sfenner
105917683Spst	case DLT_FDDI:
106017683Spst		/*
106117683Spst		 * FDDI doesn't really have a link-level type field.
106298533Sfenner		 * We set "off_linktype" to the offset of the LLC header.
106375110Sfenner		 *
106498533Sfenner		 * To check for Ethernet types, we assume that SSAP = SNAP
106598533Sfenner		 * is being used and pick out the encapsulated Ethernet type.
106675110Sfenner		 * XXX - should we generate code to check for SNAP?
106717683Spst		 */
106898533Sfenner		off_linktype = 13;
106917683Spst#ifdef PCAP_FDDIPAD
107017683Spst		off_linktype += pcap_fddipad;
107117683Spst#endif
1072190225Srpaulo		off_macpl = 13;		/* FDDI MAC header length */
107317683Spst#ifdef PCAP_FDDIPAD
1074190225Srpaulo		off_macpl += pcap_fddipad;
107517683Spst#endif
1076190225Srpaulo		off_nl = 8;		/* 802.2+SNAP */
1077190225Srpaulo		off_nl_nosnap = 3;	/* 802.2 */
107817683Spst		return;
107917683Spst
108017683Spst	case DLT_IEEE802:
108175110Sfenner		/*
108275110Sfenner		 * Token Ring doesn't really have a link-level type field.
108398533Sfenner		 * We set "off_linktype" to the offset of the LLC header.
108475110Sfenner		 *
108598533Sfenner		 * To check for Ethernet types, we assume that SSAP = SNAP
108698533Sfenner		 * is being used and pick out the encapsulated Ethernet type.
108775110Sfenner		 * XXX - should we generate code to check for SNAP?
108875110Sfenner		 *
108975110Sfenner		 * XXX - the header is actually variable-length.
109075110Sfenner		 * Some various Linux patched versions gave 38
109175110Sfenner		 * as "off_linktype" and 40 as "off_nl"; however,
109275110Sfenner		 * if a token ring packet has *no* routing
109375110Sfenner		 * information, i.e. is not source-routed, the correct
109475110Sfenner		 * values are 20 and 22, as they are in the vanilla code.
109575110Sfenner		 *
109675110Sfenner		 * A packet is source-routed iff the uppermost bit
109775110Sfenner		 * of the first byte of the source address, at an
109875110Sfenner		 * offset of 8, has the uppermost bit set.  If the
109975110Sfenner		 * packet is source-routed, the total number of bytes
110075110Sfenner		 * of routing information is 2 plus bits 0x1F00 of
110175110Sfenner		 * the 16-bit value at an offset of 14 (shifted right
110275110Sfenner		 * 8 - figure out which byte that is).
110375110Sfenner		 */
110498533Sfenner		off_linktype = 14;
1105190225Srpaulo		off_macpl = 14;		/* Token Ring MAC header length */
1106190225Srpaulo		off_nl = 8;		/* 802.2+SNAP */
1107190225Srpaulo		off_nl_nosnap = 3;	/* 802.2 */
110817683Spst		return;
110917683Spst
111098533Sfenner	case DLT_IEEE802_11:
1111190225Srpaulo	case DLT_PRISM_HEADER:
1112190225Srpaulo	case DLT_IEEE802_11_RADIO_AVS:
1113190225Srpaulo	case DLT_IEEE802_11_RADIO:
111498533Sfenner		/*
111598533Sfenner		 * 802.11 doesn't really have a link-level type field.
111698533Sfenner		 * We set "off_linktype" to the offset of the LLC header.
111798533Sfenner		 *
111898533Sfenner		 * To check for Ethernet types, we assume that SSAP = SNAP
111998533Sfenner		 * is being used and pick out the encapsulated Ethernet type.
112098533Sfenner		 * XXX - should we generate code to check for SNAP?
112198533Sfenner		 *
1122190225Srpaulo		 * We also handle variable-length radio headers here.
1123190225Srpaulo		 * The Prism header is in theory variable-length, but in
1124190225Srpaulo		 * practice it's always 144 bytes long.  However, some
1125190225Srpaulo		 * drivers on Linux use ARPHRD_IEEE80211_PRISM, but
1126190225Srpaulo		 * sometimes or always supply an AVS header, so we
1127190225Srpaulo		 * have to check whether the radio header is a Prism
1128190225Srpaulo		 * header or an AVS header, so, in practice, it's
1129190225Srpaulo		 * variable-length.
113098533Sfenner		 */
113198533Sfenner		off_linktype = 24;
1132190225Srpaulo		off_macpl = 0;		/* link-layer header is variable-length */
1133190225Srpaulo		off_macpl_is_variable = 1;
1134190225Srpaulo		off_nl = 8;		/* 802.2+SNAP */
1135190225Srpaulo		off_nl_nosnap = 3;	/* 802.2 */
113698533Sfenner		return;
113798533Sfenner
1138190225Srpaulo	case DLT_PPI:
1139172680Smlaier		/*
1140190225Srpaulo		 * At the moment we treat PPI the same way that we treat
1141190225Srpaulo		 * normal Radiotap encoded packets. The difference is in
1142190225Srpaulo		 * the function that generates the code at the beginning
1143190225Srpaulo		 * to compute the header length.  Since this code generator
1144190225Srpaulo		 * of PPI supports bare 802.11 encapsulation only (i.e.
1145190225Srpaulo		 * the encapsulated DLT should be DLT_IEEE802_11) we
1146190225Srpaulo		 * generate code to check for this too.
1147172680Smlaier		 */
1148147897Ssam		off_linktype = 24;
1149190225Srpaulo		off_macpl = 0;		/* link-layer header is variable-length */
1150190225Srpaulo		off_macpl_is_variable = 1;
1151190225Srpaulo		off_nl = 8;		/* 802.2+SNAP */
1152190225Srpaulo		off_nl_nosnap = 3;	/* 802.2 */
1153127667Sbms		return;
1154127667Sbms
115517683Spst	case DLT_ATM_RFC1483:
1156127667Sbms	case DLT_ATM_CLIP:	/* Linux ATM defines this */
115717683Spst		/*
115817683Spst		 * assume routed, non-ISO PDUs
115917683Spst		 * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00)
1160147897Ssam		 *
1161147897Ssam		 * XXX - what about ISO PDUs, e.g. CLNP, ISIS, ESIS,
1162147897Ssam		 * or PPP with the PPP NLPID (e.g., PPPoA)?  The
1163147897Ssam		 * latter would presumably be treated the way PPPoE
1164147897Ssam		 * should be, so you can do "pppoe and udp port 2049"
1165147897Ssam		 * or "pppoa and tcp port 80" and have it check for
1166147897Ssam		 * PPPo{A,E} and a PPP protocol of IP and....
116717683Spst		 */
1168127667Sbms		off_linktype = 0;
1169190225Srpaulo		off_macpl = 0;		/* packet begins with LLC header */
1170127667Sbms		off_nl = 8;		/* 802.2+SNAP */
1171127667Sbms		off_nl_nosnap = 3;	/* 802.2 */
117217683Spst		return;
117326178Sfenner
1174127667Sbms	case DLT_SUNATM:
1175127667Sbms		/*
1176127667Sbms		 * Full Frontal ATM; you get AALn PDUs with an ATM
1177127667Sbms		 * pseudo-header.
1178127667Sbms		 */
1179127667Sbms		is_atm = 1;
1180127667Sbms		off_vpi = SUNATM_VPI_POS;
1181127667Sbms		off_vci = SUNATM_VCI_POS;
1182127667Sbms		off_proto = PROTO_POS;
1183190225Srpaulo		off_mac = -1;	/* assume LLC-encapsulated, so no MAC-layer header */
1184127667Sbms		off_payload = SUNATM_PKT_BEGIN_POS;
1185127667Sbms		off_linktype = off_payload;
1186190225Srpaulo		off_macpl = off_payload;	/* if LLC-encapsulated */
1187190225Srpaulo		off_nl = 8;		/* 802.2+SNAP */
1188190225Srpaulo		off_nl_nosnap = 3;	/* 802.2 */
1189127667Sbms		return;
1190127667Sbms
119126178Sfenner	case DLT_RAW:
1192214518Srpaulo	case DLT_IPV4:
1193214518Srpaulo	case DLT_IPV6:
119426178Sfenner		off_linktype = -1;
1195190225Srpaulo		off_macpl = 0;
119626178Sfenner		off_nl = 0;
1197127667Sbms		off_nl_nosnap = 0;	/* no 802.2 LLC */
119826178Sfenner		return;
119975110Sfenner
120075110Sfenner	case DLT_LINUX_SLL:	/* fake header for Linux cooked socket */
120175110Sfenner		off_linktype = 14;
1202190225Srpaulo		off_macpl = 16;
1203190225Srpaulo		off_nl = 0;
1204190225Srpaulo		off_nl_nosnap = 0;	/* no 802.2 LLC */
120575110Sfenner		return;
120698533Sfenner
120798533Sfenner	case DLT_LTALK:
120898533Sfenner		/*
120998533Sfenner		 * LocalTalk does have a 1-byte type field in the LLAP header,
121098533Sfenner		 * but really it just indicates whether there is a "short" or
121198533Sfenner		 * "long" DDP packet following.
121298533Sfenner		 */
121398533Sfenner		off_linktype = -1;
1214190225Srpaulo		off_macpl = 0;
121598533Sfenner		off_nl = 0;
1216127667Sbms		off_nl_nosnap = 0;	/* no 802.2 LLC */
121798533Sfenner		return;
1218127667Sbms
1219127667Sbms	case DLT_IP_OVER_FC:
1220127667Sbms		/*
1221127667Sbms		 * RFC 2625 IP-over-Fibre-Channel doesn't really have a
1222127667Sbms		 * link-level type field.  We set "off_linktype" to the
1223127667Sbms		 * offset of the LLC header.
1224127667Sbms		 *
1225127667Sbms		 * To check for Ethernet types, we assume that SSAP = SNAP
1226127667Sbms		 * is being used and pick out the encapsulated Ethernet type.
1227127667Sbms		 * XXX - should we generate code to check for SNAP? RFC
1228127667Sbms		 * 2625 says SNAP should be used.
1229127667Sbms		 */
1230127667Sbms		off_linktype = 16;
1231190225Srpaulo		off_macpl = 16;
1232190225Srpaulo		off_nl = 8;		/* 802.2+SNAP */
1233190225Srpaulo		off_nl_nosnap = 3;	/* 802.2 */
1234127667Sbms		return;
1235127667Sbms
1236127667Sbms	case DLT_FRELAY:
1237127667Sbms		/*
1238127667Sbms		 * XXX - we should set this to handle SNAP-encapsulated
1239127667Sbms		 * frames (NLPID of 0x80).
1240127667Sbms		 */
1241127667Sbms		off_linktype = -1;
1242190225Srpaulo		off_macpl = 0;
1243127667Sbms		off_nl = 0;
1244127667Sbms		off_nl_nosnap = 0;	/* no 802.2 LLC */
1245127667Sbms		return;
1246127667Sbms
1247172680Smlaier                /*
1248172680Smlaier                 * the only BPF-interesting FRF.16 frames are non-control frames;
1249172680Smlaier                 * Frame Relay has a variable length link-layer
1250172680Smlaier                 * so lets start with offset 4 for now and increments later on (FIXME);
1251172680Smlaier                 */
1252172680Smlaier	case DLT_MFR:
1253172680Smlaier		off_linktype = -1;
1254190225Srpaulo		off_macpl = 0;
1255172680Smlaier		off_nl = 4;
1256172680Smlaier		off_nl_nosnap = 0;	/* XXX - for now -> no 802.2 LLC */
1257172680Smlaier		return;
1258172680Smlaier
1259127667Sbms	case DLT_APPLE_IP_OVER_IEEE1394:
1260127667Sbms		off_linktype = 16;
1261190225Srpaulo		off_macpl = 18;
1262190225Srpaulo		off_nl = 0;
1263190225Srpaulo		off_nl_nosnap = 0;	/* no 802.2 LLC */
1264127667Sbms		return;
1265127667Sbms
1266146771Ssam	case DLT_SYMANTEC_FIREWALL:
1267146771Ssam		off_linktype = 6;
1268190225Srpaulo		off_macpl = 44;
1269190225Srpaulo		off_nl = 0;		/* Ethernet II */
1270190225Srpaulo		off_nl_nosnap = 0;	/* XXX - what does it do with 802.3 packets? */
1271146771Ssam		return;
1272146771Ssam
1273172680Smlaier#ifdef HAVE_NET_PFVAR_H
1274127667Sbms	case DLT_PFLOG:
1275127667Sbms		off_linktype = 0;
1276190225Srpaulo		off_macpl = PFLOG_HDRLEN;
1277190225Srpaulo		off_nl = 0;
1278190225Srpaulo		off_nl_nosnap = 0;	/* no 802.2 LLC */
1279127667Sbms		return;
1280172680Smlaier#endif
1281127667Sbms
1282162015Ssam        case DLT_JUNIPER_MFR:
1283146771Ssam        case DLT_JUNIPER_MLFR:
1284146771Ssam        case DLT_JUNIPER_MLPPP:
1285162015Ssam        case DLT_JUNIPER_PPP:
1286162015Ssam        case DLT_JUNIPER_CHDLC:
1287162015Ssam        case DLT_JUNIPER_FRELAY:
1288146771Ssam                off_linktype = 4;
1289190225Srpaulo		off_macpl = 4;
1290190225Srpaulo		off_nl = 0;
1291147897Ssam		off_nl_nosnap = -1;	/* no 802.2 LLC */
1292146771Ssam                return;
1293146771Ssam
1294146771Ssam	case DLT_JUNIPER_ATM1:
1295190225Srpaulo		off_linktype = 4;	/* in reality variable between 4-8 */
1296190225Srpaulo		off_macpl = 4;	/* in reality variable between 4-8 */
1297190225Srpaulo		off_nl = 0;
1298190225Srpaulo		off_nl_nosnap = 10;
1299146771Ssam		return;
1300146771Ssam
1301146771Ssam	case DLT_JUNIPER_ATM2:
1302190225Srpaulo		off_linktype = 8;	/* in reality variable between 8-12 */
1303190225Srpaulo		off_macpl = 8;	/* in reality variable between 8-12 */
1304190225Srpaulo		off_nl = 0;
1305190225Srpaulo		off_nl_nosnap = 10;
1306146771Ssam		return;
1307146771Ssam
1308147897Ssam		/* frames captured on a Juniper PPPoE service PIC
1309147897Ssam		 * contain raw ethernet frames */
1310147897Ssam	case DLT_JUNIPER_PPPOE:
1311162015Ssam        case DLT_JUNIPER_ETHER:
1312190225Srpaulo        	off_macpl = 14;
1313147897Ssam		off_linktype = 16;
1314147897Ssam		off_nl = 18;		/* Ethernet II */
1315147897Ssam		off_nl_nosnap = 21;	/* 802.3+802.2 */
1316147897Ssam		return;
1317147897Ssam
1318147897Ssam	case DLT_JUNIPER_PPPOE_ATM:
1319147897Ssam		off_linktype = 4;
1320190225Srpaulo		off_macpl = 6;
1321190225Srpaulo		off_nl = 0;
1322190225Srpaulo		off_nl_nosnap = -1;	/* no 802.2 LLC */
1323147897Ssam		return;
1324147897Ssam
1325147897Ssam	case DLT_JUNIPER_GGSN:
1326147897Ssam		off_linktype = 6;
1327190225Srpaulo		off_macpl = 12;
1328190225Srpaulo		off_nl = 0;
1329190225Srpaulo		off_nl_nosnap = -1;	/* no 802.2 LLC */
1330147897Ssam		return;
1331147897Ssam
1332147897Ssam	case DLT_JUNIPER_ES:
1333147897Ssam		off_linktype = 6;
1334190225Srpaulo		off_macpl = -1;		/* not really a network layer but raw IP addresses */
1335190225Srpaulo		off_nl = -1;		/* not really a network layer but raw IP addresses */
1336147897Ssam		off_nl_nosnap = -1;	/* no 802.2 LLC */
1337147897Ssam		return;
1338147897Ssam
1339147897Ssam	case DLT_JUNIPER_MONITOR:
1340147897Ssam		off_linktype = 12;
1341190225Srpaulo		off_macpl = 12;
1342190225Srpaulo		off_nl = 0;		/* raw IP/IP6 header */
1343147897Ssam		off_nl_nosnap = -1;	/* no 802.2 LLC */
1344147897Ssam		return;
1345147897Ssam
1346147897Ssam	case DLT_JUNIPER_SERVICES:
1347147897Ssam		off_linktype = 12;
1348190225Srpaulo		off_macpl = -1;		/* L3 proto location dep. on cookie type */
1349147897Ssam		off_nl = -1;		/* L3 proto location dep. on cookie type */
1350147897Ssam		off_nl_nosnap = -1;	/* no 802.2 LLC */
1351147897Ssam		return;
1352147897Ssam
1353172680Smlaier	case DLT_JUNIPER_VP:
1354172680Smlaier		off_linktype = 18;
1355190225Srpaulo		off_macpl = -1;
1356172680Smlaier		off_nl = -1;
1357172680Smlaier		off_nl_nosnap = -1;
1358172680Smlaier		return;
1359172680Smlaier
1360190225Srpaulo	case DLT_JUNIPER_ST:
1361190225Srpaulo		off_linktype = 18;
1362190225Srpaulo		off_macpl = -1;
1363190225Srpaulo		off_nl = -1;
1364190225Srpaulo		off_nl_nosnap = -1;
1365190225Srpaulo		return;
1366190225Srpaulo
1367190225Srpaulo	case DLT_JUNIPER_ISM:
1368190225Srpaulo		off_linktype = 8;
1369190225Srpaulo		off_macpl = -1;
1370190225Srpaulo		off_nl = -1;
1371190225Srpaulo		off_nl_nosnap = -1;
1372190225Srpaulo		return;
1373190225Srpaulo
1374236167Sdelphij	case DLT_JUNIPER_VS:
1375236167Sdelphij	case DLT_JUNIPER_SRX_E2E:
1376236167Sdelphij	case DLT_JUNIPER_FIBRECHANNEL:
1377236167Sdelphij	case DLT_JUNIPER_ATM_CEMIC:
1378236167Sdelphij		off_linktype = 8;
1379236167Sdelphij		off_macpl = -1;
1380236167Sdelphij		off_nl = -1;
1381236167Sdelphij		off_nl_nosnap = -1;
1382236167Sdelphij		return;
1383236167Sdelphij
1384147897Ssam	case DLT_MTP2:
1385172680Smlaier		off_li = 2;
1386147897Ssam		off_sio = 3;
1387147897Ssam		off_opc = 4;
1388147897Ssam		off_dpc = 4;
1389147897Ssam		off_sls = 7;
1390147897Ssam		off_linktype = -1;
1391190225Srpaulo		off_macpl = -1;
1392147897Ssam		off_nl = -1;
1393147897Ssam		off_nl_nosnap = -1;
1394147897Ssam		return;
1395147897Ssam
1396172680Smlaier	case DLT_MTP2_WITH_PHDR:
1397172680Smlaier		off_li = 6;
1398172680Smlaier		off_sio = 7;
1399172680Smlaier		off_opc = 8;
1400172680Smlaier		off_dpc = 8;
1401172680Smlaier		off_sls = 11;
1402172680Smlaier		off_linktype = -1;
1403190225Srpaulo		off_macpl = -1;
1404172680Smlaier		off_nl = -1;
1405172680Smlaier		off_nl_nosnap = -1;
1406172680Smlaier		return;
1407172680Smlaier
1408190225Srpaulo	case DLT_ERF:
1409190225Srpaulo		off_li = 22;
1410190225Srpaulo		off_sio = 23;
1411190225Srpaulo		off_opc = 24;
1412190225Srpaulo		off_dpc = 24;
1413190225Srpaulo		off_sls = 27;
1414190225Srpaulo		off_linktype = -1;
1415190225Srpaulo		off_macpl = -1;
1416190225Srpaulo		off_nl = -1;
1417190225Srpaulo		off_nl_nosnap = -1;
1418190225Srpaulo		return;
1419190225Srpaulo
1420127667Sbms	case DLT_PFSYNC:
1421127667Sbms		off_linktype = -1;
1422190225Srpaulo		off_macpl = 4;
1423190225Srpaulo		off_nl = 0;
1424190225Srpaulo		off_nl_nosnap = 0;
1425127667Sbms		return;
1426147897Ssam
1427190225Srpaulo	case DLT_AX25_KISS:
1428190225Srpaulo		/*
1429190225Srpaulo		 * Currently, only raw "link[N:M]" filtering is supported.
1430190225Srpaulo		 */
1431190225Srpaulo		off_linktype = -1;	/* variable, min 15, max 71 steps of 7 */
1432190225Srpaulo		off_macpl = -1;
1433190225Srpaulo		off_nl = -1;		/* variable, min 16, max 71 steps of 7 */
1434190225Srpaulo		off_nl_nosnap = -1;	/* no 802.2 LLC */
1435190225Srpaulo		off_mac = 1;		/* step over the kiss length byte */
1436190225Srpaulo		return;
1437190225Srpaulo
1438236167Sdelphij	case DLT_IPNET:
1439236167Sdelphij		off_linktype = 1;
1440236167Sdelphij		off_macpl = 24;		/* ipnet header length */
1441236167Sdelphij		off_nl = 0;
1442190225Srpaulo		off_nl_nosnap = -1;
1443190225Srpaulo		return;
1444214518Srpaulo
1445236167Sdelphij	case DLT_NETANALYZER:
1446236167Sdelphij		off_mac = 4;		/* MAC header is past 4-byte pseudo-header */
1447236167Sdelphij		off_linktype = 16;	/* includes 4-byte pseudo-header */
1448236167Sdelphij		off_macpl = 18;		/* pseudo-header+Ethernet header length */
1449236167Sdelphij		off_nl = 0;		/* Ethernet II */
1450236167Sdelphij		off_nl_nosnap = 3;	/* 802.3+802.2 */
1451214518Srpaulo		return;
1452214518Srpaulo
1453236167Sdelphij	case DLT_NETANALYZER_TRANSPARENT:
1454236167Sdelphij		off_mac = 12;		/* MAC header is past 4-byte pseudo-header, preamble, and SFD */
1455236167Sdelphij		off_linktype = 24;	/* includes 4-byte pseudo-header+preamble+SFD */
1456236167Sdelphij		off_macpl = 26;		/* pseudo-header+preamble+SFD+Ethernet header length */
1457236167Sdelphij		off_nl = 0;		/* Ethernet II */
1458236167Sdelphij		off_nl_nosnap = 3;	/* 802.3+802.2 */
1459214518Srpaulo		return;
1460214518Srpaulo
1461236167Sdelphij	default:
1462214518Srpaulo		/*
1463236167Sdelphij		 * For values in the range in which we've assigned new
1464236167Sdelphij		 * DLT_ values, only raw "link[N:M]" filtering is supported.
1465214518Srpaulo		 */
1466236167Sdelphij		if (linktype >= DLT_MATCHING_MIN &&
1467236167Sdelphij		    linktype <= DLT_MATCHING_MAX) {
1468236167Sdelphij			off_linktype = -1;
1469236167Sdelphij			off_macpl = -1;
1470236167Sdelphij			off_nl = -1;
1471236167Sdelphij			off_nl_nosnap = -1;
1472236167Sdelphij			return;
1473236167Sdelphij		}
1474214518Srpaulo
147517683Spst	}
147675110Sfenner	bpf_error("unknown data link type %d", linktype);
147717683Spst	/* NOTREACHED */
147817683Spst}
147917683Spst
1480147897Ssam/*
1481147897Ssam * Load a value relative to the beginning of the link-layer header.
1482147897Ssam * The link-layer header doesn't necessarily begin at the beginning
1483147897Ssam * of the packet data; there might be a variable-length prefix containing
1484147897Ssam * radio information.
1485147897Ssam */
1486147897Ssamstatic struct slist *
1487147897Ssamgen_load_llrel(offset, size)
1488147897Ssam	u_int offset, size;
1489147897Ssam{
1490147897Ssam	struct slist *s, *s2;
1491147897Ssam
1492147897Ssam	s = gen_llprefixlen();
1493147897Ssam
1494147897Ssam	/*
1495147897Ssam	 * If "s" is non-null, it has code to arrange that the X register
1496147897Ssam	 * contains the length of the prefix preceding the link-layer
1497147897Ssam	 * header.
1498172680Smlaier	 *
1499172680Smlaier	 * Otherwise, the length of the prefix preceding the link-layer
1500172680Smlaier	 * header is "off_ll".
1501147897Ssam	 */
1502147897Ssam	if (s != NULL) {
1503172680Smlaier		/*
1504172680Smlaier		 * There's a variable-length prefix preceding the
1505172680Smlaier		 * link-layer header.  "s" points to a list of statements
1506172680Smlaier		 * that put the length of that prefix into the X register.
1507172680Smlaier		 * do an indirect load, to use the X register as an offset.
1508172680Smlaier		 */
1509147897Ssam		s2 = new_stmt(BPF_LD|BPF_IND|size);
1510147897Ssam		s2->s.k = offset;
1511147897Ssam		sappend(s, s2);
1512147897Ssam	} else {
1513172680Smlaier		/*
1514172680Smlaier		 * There is no variable-length header preceding the
1515172680Smlaier		 * link-layer header; add in off_ll, which, if there's
1516172680Smlaier		 * a fixed-length header preceding the link-layer header,
1517172680Smlaier		 * is the length of that header.
1518172680Smlaier		 */
1519147897Ssam		s = new_stmt(BPF_LD|BPF_ABS|size);
1520172680Smlaier		s->s.k = offset + off_ll;
1521147897Ssam	}
1522147897Ssam	return s;
1523147897Ssam}
1524147897Ssam
1525190225Srpaulo/*
1526190225Srpaulo * Load a value relative to the beginning of the MAC-layer payload.
1527190225Srpaulo */
1528190225Srpaulostatic struct slist *
1529190225Srpaulogen_load_macplrel(offset, size)
1530190225Srpaulo	u_int offset, size;
1531190225Srpaulo{
1532190225Srpaulo	struct slist *s, *s2;
1533172680Smlaier
1534190225Srpaulo	s = gen_off_macpl();
1535190225Srpaulo
1536190225Srpaulo	/*
1537190225Srpaulo	 * If s is non-null, the offset of the MAC-layer payload is
1538190225Srpaulo	 * variable, and s points to a list of instructions that
1539190225Srpaulo	 * arrange that the X register contains that offset.
1540190225Srpaulo	 *
1541190225Srpaulo	 * Otherwise, the offset of the MAC-layer payload is constant,
1542190225Srpaulo	 * and is in off_macpl.
1543190225Srpaulo	 */
1544190225Srpaulo	if (s != NULL) {
1545190225Srpaulo		/*
1546190225Srpaulo		 * The offset of the MAC-layer payload is in the X
1547190225Srpaulo		 * register.  Do an indirect load, to use the X register
1548190225Srpaulo		 * as an offset.
1549190225Srpaulo		 */
1550190225Srpaulo		s2 = new_stmt(BPF_LD|BPF_IND|size);
1551190225Srpaulo		s2->s.k = offset;
1552190225Srpaulo		sappend(s, s2);
1553190225Srpaulo	} else {
1554190225Srpaulo		/*
1555190225Srpaulo		 * The offset of the MAC-layer payload is constant,
1556190225Srpaulo		 * and is in off_macpl; load the value at that offset
1557190225Srpaulo		 * plus the specified offset.
1558190225Srpaulo		 */
1559190225Srpaulo		s = new_stmt(BPF_LD|BPF_ABS|size);
1560190225Srpaulo		s->s.k = off_macpl + offset;
1561190225Srpaulo	}
1562190225Srpaulo	return s;
1563190225Srpaulo}
1564190225Srpaulo
1565147897Ssam/*
1566147897Ssam * Load a value relative to the beginning of the specified header.
1567147897Ssam */
1568147897Ssamstatic struct slist *
1569147897Ssamgen_load_a(offrel, offset, size)
1570147897Ssam	enum e_offrel offrel;
1571147897Ssam	u_int offset, size;
1572147897Ssam{
1573147897Ssam	struct slist *s, *s2;
1574147897Ssam
1575147897Ssam	switch (offrel) {
1576147897Ssam
1577147897Ssam	case OR_PACKET:
1578172680Smlaier                s = new_stmt(BPF_LD|BPF_ABS|size);
1579172680Smlaier                s->s.k = offset;
1580147897Ssam		break;
1581147897Ssam
1582147897Ssam	case OR_LINK:
1583172680Smlaier		s = gen_load_llrel(offset, size);
1584147897Ssam		break;
1585147897Ssam
1586190225Srpaulo	case OR_MACPL:
1587190225Srpaulo		s = gen_load_macplrel(offset, size);
1588190225Srpaulo		break;
1589190225Srpaulo
1590147897Ssam	case OR_NET:
1591190225Srpaulo		s = gen_load_macplrel(off_nl + offset, size);
1592147897Ssam		break;
1593147897Ssam
1594147897Ssam	case OR_NET_NOSNAP:
1595190225Srpaulo		s = gen_load_macplrel(off_nl_nosnap + offset, size);
1596147897Ssam		break;
1597147897Ssam
1598147897Ssam	case OR_TRAN_IPV4:
1599147897Ssam		/*
1600172680Smlaier		 * Load the X register with the length of the IPv4 header
1601172680Smlaier		 * (plus the offset of the link-layer header, if it's
1602172680Smlaier		 * preceded by a variable-length header such as a radio
1603172680Smlaier		 * header), in bytes.
1604147897Ssam		 */
1605147897Ssam		s = gen_loadx_iphdrlen();
1606147897Ssam
1607147897Ssam		/*
1608190225Srpaulo		 * Load the item at {offset of the MAC-layer payload} +
1609190225Srpaulo		 * {offset, relative to the start of the MAC-layer
1610190225Srpaulo		 * paylod, of the IPv4 header} + {length of the IPv4 header} +
1611172680Smlaier		 * {specified offset}.
1612172680Smlaier		 *
1613190225Srpaulo		 * (If the offset of the MAC-layer payload is variable,
1614190225Srpaulo		 * it's included in the value in the X register, and
1615190225Srpaulo		 * off_macpl is 0.)
1616147897Ssam		 */
1617147897Ssam		s2 = new_stmt(BPF_LD|BPF_IND|size);
1618190225Srpaulo		s2->s.k = off_macpl + off_nl + offset;
1619147897Ssam		sappend(s, s2);
1620147897Ssam		break;
1621147897Ssam
1622147897Ssam	case OR_TRAN_IPV6:
1623190225Srpaulo		s = gen_load_macplrel(off_nl + 40 + offset, size);
1624147897Ssam		break;
1625147897Ssam
1626147897Ssam	default:
1627147897Ssam		abort();
1628147897Ssam		return NULL;
1629147897Ssam	}
1630147897Ssam	return s;
1631147897Ssam}
1632147897Ssam
1633147897Ssam/*
1634147897Ssam * Generate code to load into the X register the sum of the length of
1635147897Ssam * the IPv4 header and any variable-length header preceding the link-layer
1636147897Ssam * header.
1637147897Ssam */
1638147897Ssamstatic struct slist *
1639147897Ssamgen_loadx_iphdrlen()
1640147897Ssam{
1641147897Ssam	struct slist *s, *s2;
1642147897Ssam
1643190225Srpaulo	s = gen_off_macpl();
1644147897Ssam	if (s != NULL) {
1645147897Ssam		/*
1646147897Ssam		 * There's a variable-length prefix preceding the
1647190225Srpaulo		 * link-layer header, or the link-layer header is itself
1648190225Srpaulo		 * variable-length.  "s" points to a list of statements
1649190225Srpaulo		 * that put the offset of the MAC-layer payload into
1650190225Srpaulo		 * the X register.
1651190225Srpaulo		 *
1652147897Ssam		 * The 4*([k]&0xf) addressing mode can't be used, as we
1653147897Ssam		 * don't have a constant offset, so we have to load the
1654147897Ssam		 * value in question into the A register and add to it
1655147897Ssam		 * the value from the X register.
1656147897Ssam		 */
1657147897Ssam		s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
1658147897Ssam		s2->s.k = off_nl;
1659147897Ssam		sappend(s, s2);
1660147897Ssam		s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
1661147897Ssam		s2->s.k = 0xf;
1662147897Ssam		sappend(s, s2);
1663147897Ssam		s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
1664147897Ssam		s2->s.k = 2;
1665147897Ssam		sappend(s, s2);
1666147897Ssam
1667147897Ssam		/*
1668147897Ssam		 * The A register now contains the length of the
1669190225Srpaulo		 * IP header.  We need to add to it the offset of
1670190225Srpaulo		 * the MAC-layer payload, which is still in the X
1671190225Srpaulo		 * register, and move the result into the X register.
1672147897Ssam		 */
1673147897Ssam		sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
1674147897Ssam		sappend(s, new_stmt(BPF_MISC|BPF_TAX));
1675147897Ssam	} else {
1676147897Ssam		/*
1677147897Ssam		 * There is no variable-length header preceding the
1678190225Srpaulo		 * link-layer header, and the link-layer header is
1679190225Srpaulo		 * fixed-length; load the length of the IPv4 header,
1680190225Srpaulo		 * which is at an offset of off_nl from the beginning
1681190225Srpaulo		 * of the MAC-layer payload, and thus at an offset
1682190225Srpaulo		 * of off_mac_pl + off_nl from the beginning of the
1683190225Srpaulo		 * raw packet data.
1684147897Ssam		 */
1685147897Ssam		s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
1686190225Srpaulo		s->s.k = off_macpl + off_nl;
1687147897Ssam	}
1688147897Ssam	return s;
1689147897Ssam}
1690147897Ssam
169117683Spststatic struct block *
169217683Spstgen_uncond(rsense)
169317683Spst	int rsense;
169417683Spst{
169517683Spst	struct block *b;
169617683Spst	struct slist *s;
169717683Spst
169817683Spst	s = new_stmt(BPF_LD|BPF_IMM);
169917683Spst	s->s.k = !rsense;
170017683Spst	b = new_block(JMP(BPF_JEQ));
170117683Spst	b->stmts = s;
170217683Spst
170317683Spst	return b;
170417683Spst}
170517683Spst
170617683Spststatic inline struct block *
170717683Spstgen_true()
170817683Spst{
170917683Spst	return gen_uncond(1);
171017683Spst}
171117683Spst
171217683Spststatic inline struct block *
171317683Spstgen_false()
171417683Spst{
171517683Spst	return gen_uncond(0);
171617683Spst}
171717683Spst
171875110Sfenner/*
171975110Sfenner * Byte-swap a 32-bit number.
172075110Sfenner * ("htonl()" or "ntohl()" won't work - we want to byte-swap even on
172175110Sfenner * big-endian platforms.)
172275110Sfenner */
172375110Sfenner#define	SWAPLONG(y) \
172475110Sfenner((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
172575110Sfenner
1726147897Ssam/*
1727147897Ssam * Generate code to match a particular packet type.
1728147897Ssam *
1729147897Ssam * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
1730147897Ssam * value, if <= ETHERMTU.  We use that to determine whether to
1731147897Ssam * match the type/length field or to check the type/length field for
1732147897Ssam * a value <= ETHERMTU to see whether it's a type field and then do
1733147897Ssam * the appropriate test.
1734147897Ssam */
173517683Spststatic struct block *
1736127667Sbmsgen_ether_linktype(proto)
173739294Sfenner	register int proto;
173817683Spst{
173939294Sfenner	struct block *b0, *b1;
174039294Sfenner
1741127667Sbms	switch (proto) {
174226178Sfenner
1743127667Sbms	case LLCSAP_ISONS:
1744127667Sbms	case LLCSAP_IP:
1745127667Sbms	case LLCSAP_NETBEUI:
1746127667Sbms		/*
1747147897Ssam		 * OSI protocols and NetBEUI always use 802.2 encapsulation,
1748147897Ssam		 * so we check the DSAP and SSAP.
1749147897Ssam		 *
1750147897Ssam		 * LLCSAP_IP checks for IP-over-802.2, rather
1751147897Ssam		 * than IP-over-Ethernet or IP-over-SNAP.
1752147897Ssam		 *
1753127667Sbms		 * XXX - should we check both the DSAP and the
1754127667Sbms		 * SSAP, like this, or should we check just the
1755147897Ssam		 * DSAP, as we do for other types <= ETHERMTU
1756147897Ssam		 * (i.e., other SAP values)?
1757127667Sbms		 */
1758147897Ssam		b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
1759127667Sbms		gen_not(b0);
1760190225Srpaulo		b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)
1761147897Ssam			     ((proto << 8) | proto));
1762127667Sbms		gen_and(b0, b1);
1763127667Sbms		return b1;
176498533Sfenner
1765127667Sbms	case LLCSAP_IPX:
1766127667Sbms		/*
1767127667Sbms		 * Check for;
1768127667Sbms		 *
1769127667Sbms		 *	Ethernet_II frames, which are Ethernet
1770127667Sbms		 *	frames with a frame type of ETHERTYPE_IPX;
1771127667Sbms		 *
1772127667Sbms		 *	Ethernet_802.3 frames, which are 802.3
1773127667Sbms		 *	frames (i.e., the type/length field is
1774127667Sbms		 *	a length field, <= ETHERMTU, rather than
1775127667Sbms		 *	a type field) with the first two bytes
1776127667Sbms		 *	after the Ethernet/802.3 header being
1777127667Sbms		 *	0xFFFF;
1778127667Sbms		 *
1779127667Sbms		 *	Ethernet_802.2 frames, which are 802.3
1780127667Sbms		 *	frames with an 802.2 LLC header and
1781127667Sbms		 *	with the IPX LSAP as the DSAP in the LLC
1782127667Sbms		 *	header;
1783127667Sbms		 *
1784127667Sbms		 *	Ethernet_SNAP frames, which are 802.3
1785127667Sbms		 *	frames with an LLC header and a SNAP
1786127667Sbms		 *	header and with an OUI of 0x000000
1787127667Sbms		 *	(encapsulated Ethernet) and a protocol
1788127667Sbms		 *	ID of ETHERTYPE_IPX in the SNAP header.
1789127667Sbms		 *
1790127667Sbms		 * XXX - should we generate the same code both
1791127667Sbms		 * for tests for LLCSAP_IPX and for ETHERTYPE_IPX?
1792127667Sbms		 */
179398533Sfenner
1794127667Sbms		/*
1795127667Sbms		 * This generates code to check both for the
1796127667Sbms		 * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3.
1797127667Sbms		 */
1798190225Srpaulo		b0 = gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
1799190225Srpaulo		b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)0xFFFF);
1800127667Sbms		gen_or(b0, b1);
180198533Sfenner
1802127667Sbms		/*
1803127667Sbms		 * Now we add code to check for SNAP frames with
1804127667Sbms		 * ETHERTYPE_IPX, i.e. Ethernet_SNAP.
1805127667Sbms		 */
1806190225Srpaulo		b0 = gen_snap(0x000000, ETHERTYPE_IPX);
1807127667Sbms		gen_or(b0, b1);
180898533Sfenner
1809127667Sbms		/*
1810127667Sbms		 * Now we generate code to check for 802.3
1811127667Sbms		 * frames in general.
1812127667Sbms		 */
1813147897Ssam		b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
1814127667Sbms		gen_not(b0);
181598533Sfenner
1816127667Sbms		/*
1817127667Sbms		 * Now add the check for 802.3 frames before the
1818127667Sbms		 * check for Ethernet_802.2 and Ethernet_802.3,
1819127667Sbms		 * as those checks should only be done on 802.3
1820127667Sbms		 * frames, not on Ethernet frames.
1821127667Sbms		 */
1822127667Sbms		gen_and(b0, b1);
182398533Sfenner
1824127667Sbms		/*
1825127667Sbms		 * Now add the check for Ethernet_II frames, and
1826127667Sbms		 * do that before checking for the other frame
1827127667Sbms		 * types.
1828127667Sbms		 */
1829147897Ssam		b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
1830147897Ssam		    (bpf_int32)ETHERTYPE_IPX);
1831127667Sbms		gen_or(b0, b1);
1832127667Sbms		return b1;
183398533Sfenner
1834127667Sbms	case ETHERTYPE_ATALK:
1835127667Sbms	case ETHERTYPE_AARP:
1836127667Sbms		/*
1837127667Sbms		 * EtherTalk (AppleTalk protocols on Ethernet link
1838127667Sbms		 * layer) may use 802.2 encapsulation.
1839127667Sbms		 */
184075110Sfenner
1841127667Sbms		/*
1842127667Sbms		 * Check for 802.2 encapsulation (EtherTalk phase 2?);
1843127667Sbms		 * we check for an Ethernet type field less than
1844127667Sbms		 * 1500, which means it's an 802.3 length field.
1845127667Sbms		 */
1846147897Ssam		b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
1847127667Sbms		gen_not(b0);
1848127667Sbms
1849127667Sbms		/*
1850127667Sbms		 * 802.2-encapsulated ETHERTYPE_ATALK packets are
1851127667Sbms		 * SNAP packets with an organization code of
1852127667Sbms		 * 0x080007 (Apple, for Appletalk) and a protocol
1853127667Sbms		 * type of ETHERTYPE_ATALK (Appletalk).
1854127667Sbms		 *
1855127667Sbms		 * 802.2-encapsulated ETHERTYPE_AARP packets are
1856127667Sbms		 * SNAP packets with an organization code of
1857127667Sbms		 * 0x000000 (encapsulated Ethernet) and a protocol
1858127667Sbms		 * type of ETHERTYPE_AARP (Appletalk ARP).
1859127667Sbms		 */
1860127667Sbms		if (proto == ETHERTYPE_ATALK)
1861190225Srpaulo			b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
1862127667Sbms		else	/* proto == ETHERTYPE_AARP */
1863190225Srpaulo			b1 = gen_snap(0x000000, ETHERTYPE_AARP);
1864127667Sbms		gen_and(b0, b1);
1865127667Sbms
1866127667Sbms		/*
1867127667Sbms		 * Check for Ethernet encapsulation (Ethertalk
1868127667Sbms		 * phase 1?); we just check for the Ethernet
1869127667Sbms		 * protocol type.
1870127667Sbms		 */
1871147897Ssam		b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
1872127667Sbms
1873127667Sbms		gen_or(b0, b1);
1874127667Sbms		return b1;
1875127667Sbms
1876127667Sbms	default:
1877127667Sbms		if (proto <= ETHERMTU) {
187875110Sfenner			/*
1879127667Sbms			 * This is an LLC SAP value, so the frames
1880127667Sbms			 * that match would be 802.2 frames.
1881127667Sbms			 * Check that the frame is an 802.2 frame
1882127667Sbms			 * (i.e., that the length/type field is
1883127667Sbms			 * a length field, <= ETHERMTU) and
1884127667Sbms			 * then check the DSAP.
188575110Sfenner			 */
1886147897Ssam			b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
188775110Sfenner			gen_not(b0);
1888147897Ssam			b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B,
1889147897Ssam			    (bpf_int32)proto);
189075110Sfenner			gen_and(b0, b1);
1891127667Sbms			return b1;
1892127667Sbms		} else {
189375110Sfenner			/*
1894127667Sbms			 * This is an Ethernet type, so compare
1895127667Sbms			 * the length/type field with it (if
1896127667Sbms			 * the frame is an 802.2 frame, the length
1897127667Sbms			 * field will be <= ETHERMTU, and, as
1898127667Sbms			 * "proto" is > ETHERMTU, this test
1899127667Sbms			 * will fail and the frame won't match,
1900127667Sbms			 * which is what we want).
190175110Sfenner			 */
1902147897Ssam			return gen_cmp(OR_LINK, off_linktype, BPF_H,
1903147897Ssam			    (bpf_int32)proto);
1904127667Sbms		}
1905127667Sbms	}
1906127667Sbms}
190775110Sfenner
1908147897Ssam/*
1909214518Srpaulo * "proto" is an Ethernet type value and for IPNET, if it is not IPv4
1910214518Srpaulo * or IPv6 then we have an error.
1911214518Srpaulo */
1912214518Srpaulostatic struct block *
1913214518Srpaulogen_ipnet_linktype(proto)
1914214518Srpaulo	register int proto;
1915214518Srpaulo{
1916214518Srpaulo	switch (proto) {
1917214518Srpaulo
1918214518Srpaulo	case ETHERTYPE_IP:
1919214518Srpaulo		return gen_cmp(OR_LINK, off_linktype, BPF_B,
1920214518Srpaulo		    (bpf_int32)IPH_AF_INET);
1921214518Srpaulo		/* NOTREACHED */
1922214518Srpaulo
1923214518Srpaulo	case ETHERTYPE_IPV6:
1924214518Srpaulo		return gen_cmp(OR_LINK, off_linktype, BPF_B,
1925214518Srpaulo		    (bpf_int32)IPH_AF_INET6);
1926214518Srpaulo		/* NOTREACHED */
1927214518Srpaulo
1928214518Srpaulo	default:
1929214518Srpaulo		break;
1930214518Srpaulo	}
1931214518Srpaulo
1932214518Srpaulo	return gen_false();
1933214518Srpaulo}
1934214518Srpaulo
1935214518Srpaulo/*
1936147897Ssam * Generate code to match a particular packet type.
1937147897Ssam *
1938147897Ssam * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
1939147897Ssam * value, if <= ETHERMTU.  We use that to determine whether to
1940147897Ssam * match the type field or to check the type field for the special
1941147897Ssam * LINUX_SLL_P_802_2 value and then do the appropriate test.
1942147897Ssam */
1943127667Sbmsstatic struct block *
1944146771Ssamgen_linux_sll_linktype(proto)
1945146771Ssam	register int proto;
1946146771Ssam{
1947146771Ssam	struct block *b0, *b1;
1948146771Ssam
1949146771Ssam	switch (proto) {
1950146771Ssam
1951147897Ssam	case LLCSAP_ISONS:
1952146771Ssam	case LLCSAP_IP:
1953147897Ssam	case LLCSAP_NETBEUI:
1954146771Ssam		/*
1955147897Ssam		 * OSI protocols and NetBEUI always use 802.2 encapsulation,
1956147897Ssam		 * so we check the DSAP and SSAP.
1957147897Ssam		 *
1958147897Ssam		 * LLCSAP_IP checks for IP-over-802.2, rather
1959147897Ssam		 * than IP-over-Ethernet or IP-over-SNAP.
1960147897Ssam		 *
1961146771Ssam		 * XXX - should we check both the DSAP and the
1962146771Ssam		 * SSAP, like this, or should we check just the
1963147897Ssam		 * DSAP, as we do for other types <= ETHERMTU
1964147897Ssam		 * (i.e., other SAP values)?
1965146771Ssam		 */
1966147897Ssam		b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
1967190225Srpaulo		b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32)
1968147897Ssam			     ((proto << 8) | proto));
1969146771Ssam		gen_and(b0, b1);
1970146771Ssam		return b1;
1971146771Ssam
1972146771Ssam	case LLCSAP_IPX:
1973146771Ssam		/*
1974146771Ssam		 *	Ethernet_II frames, which are Ethernet
1975146771Ssam		 *	frames with a frame type of ETHERTYPE_IPX;
1976146771Ssam		 *
1977146771Ssam		 *	Ethernet_802.3 frames, which have a frame
1978146771Ssam		 *	type of LINUX_SLL_P_802_3;
1979146771Ssam		 *
1980146771Ssam		 *	Ethernet_802.2 frames, which are 802.3
1981146771Ssam		 *	frames with an 802.2 LLC header (i.e, have
1982146771Ssam		 *	a frame type of LINUX_SLL_P_802_2) and
1983146771Ssam		 *	with the IPX LSAP as the DSAP in the LLC
1984146771Ssam		 *	header;
1985146771Ssam		 *
1986146771Ssam		 *	Ethernet_SNAP frames, which are 802.3
1987146771Ssam		 *	frames with an LLC header and a SNAP
1988146771Ssam		 *	header and with an OUI of 0x000000
1989146771Ssam		 *	(encapsulated Ethernet) and a protocol
1990146771Ssam		 *	ID of ETHERTYPE_IPX in the SNAP header.
1991146771Ssam		 *
1992146771Ssam		 * First, do the checks on LINUX_SLL_P_802_2
1993146771Ssam		 * frames; generate the check for either
1994146771Ssam		 * Ethernet_802.2 or Ethernet_SNAP frames, and
1995146771Ssam		 * then put a check for LINUX_SLL_P_802_2 frames
1996146771Ssam		 * before it.
1997146771Ssam		 */
1998190225Srpaulo		b0 = gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
1999190225Srpaulo		b1 = gen_snap(0x000000, ETHERTYPE_IPX);
2000146771Ssam		gen_or(b0, b1);
2001147897Ssam		b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
2002146771Ssam		gen_and(b0, b1);
2003146771Ssam
2004146771Ssam		/*
2005146771Ssam		 * Now check for 802.3 frames and OR that with
2006146771Ssam		 * the previous test.
2007146771Ssam		 */
2008147897Ssam		b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_3);
2009146771Ssam		gen_or(b0, b1);
2010146771Ssam
2011146771Ssam		/*
2012146771Ssam		 * Now add the check for Ethernet_II frames, and
2013146771Ssam		 * do that before checking for the other frame
2014146771Ssam		 * types.
2015146771Ssam		 */
2016147897Ssam		b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
2017146771Ssam		    (bpf_int32)ETHERTYPE_IPX);
2018146771Ssam		gen_or(b0, b1);
2019146771Ssam		return b1;
2020146771Ssam
2021146771Ssam	case ETHERTYPE_ATALK:
2022146771Ssam	case ETHERTYPE_AARP:
2023146771Ssam		/*
2024146771Ssam		 * EtherTalk (AppleTalk protocols on Ethernet link
2025146771Ssam		 * layer) may use 802.2 encapsulation.
2026146771Ssam		 */
2027146771Ssam
2028146771Ssam		/*
2029146771Ssam		 * Check for 802.2 encapsulation (EtherTalk phase 2?);
2030146771Ssam		 * we check for the 802.2 protocol type in the
2031146771Ssam		 * "Ethernet type" field.
2032146771Ssam		 */
2033147897Ssam		b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
2034146771Ssam
2035146771Ssam		/*
2036146771Ssam		 * 802.2-encapsulated ETHERTYPE_ATALK packets are
2037146771Ssam		 * SNAP packets with an organization code of
2038146771Ssam		 * 0x080007 (Apple, for Appletalk) and a protocol
2039146771Ssam		 * type of ETHERTYPE_ATALK (Appletalk).
2040146771Ssam		 *
2041146771Ssam		 * 802.2-encapsulated ETHERTYPE_AARP packets are
2042146771Ssam		 * SNAP packets with an organization code of
2043146771Ssam		 * 0x000000 (encapsulated Ethernet) and a protocol
2044146771Ssam		 * type of ETHERTYPE_AARP (Appletalk ARP).
2045146771Ssam		 */
2046146771Ssam		if (proto == ETHERTYPE_ATALK)
2047190225Srpaulo			b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
2048146771Ssam		else	/* proto == ETHERTYPE_AARP */
2049190225Srpaulo			b1 = gen_snap(0x000000, ETHERTYPE_AARP);
2050146771Ssam		gen_and(b0, b1);
2051146771Ssam
2052146771Ssam		/*
2053146771Ssam		 * Check for Ethernet encapsulation (Ethertalk
2054146771Ssam		 * phase 1?); we just check for the Ethernet
2055146771Ssam		 * protocol type.
2056146771Ssam		 */
2057147897Ssam		b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
2058146771Ssam
2059146771Ssam		gen_or(b0, b1);
2060146771Ssam		return b1;
2061146771Ssam
2062146771Ssam	default:
2063146771Ssam		if (proto <= ETHERMTU) {
2064146771Ssam			/*
2065146771Ssam			 * This is an LLC SAP value, so the frames
2066146771Ssam			 * that match would be 802.2 frames.
2067146771Ssam			 * Check for the 802.2 protocol type
2068146771Ssam			 * in the "Ethernet type" field, and
2069146771Ssam			 * then check the DSAP.
2070146771Ssam			 */
2071147897Ssam			b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
2072146771Ssam			    LINUX_SLL_P_802_2);
2073190225Srpaulo			b1 = gen_cmp(OR_LINK, off_macpl, BPF_B,
2074146771Ssam			     (bpf_int32)proto);
2075146771Ssam			gen_and(b0, b1);
2076146771Ssam			return b1;
2077146771Ssam		} else {
2078146771Ssam			/*
2079146771Ssam			 * This is an Ethernet type, so compare
2080146771Ssam			 * the length/type field with it (if
2081146771Ssam			 * the frame is an 802.2 frame, the length
2082146771Ssam			 * field will be <= ETHERMTU, and, as
2083146771Ssam			 * "proto" is > ETHERMTU, this test
2084146771Ssam			 * will fail and the frame won't match,
2085146771Ssam			 * which is what we want).
2086146771Ssam			 */
2087147897Ssam			return gen_cmp(OR_LINK, off_linktype, BPF_H,
2088146771Ssam			    (bpf_int32)proto);
2089146771Ssam		}
2090146771Ssam	}
2091146771Ssam}
2092146771Ssam
2093190225Srpaulostatic struct slist *
2094190225Srpaulogen_load_prism_llprefixlen()
2095147897Ssam{
2096147897Ssam	struct slist *s1, *s2;
2097190225Srpaulo	struct slist *sjeq_avs_cookie;
2098190225Srpaulo	struct slist *sjcommon;
2099147897Ssam
2100147897Ssam	/*
2101190225Srpaulo	 * This code is not compatible with the optimizer, as
2102190225Srpaulo	 * we are generating jmp instructions within a normal
2103190225Srpaulo	 * slist of instructions
2104147897Ssam	 */
2105190225Srpaulo	no_optimize = 1;
2106190225Srpaulo
2107190225Srpaulo	/*
2108190225Srpaulo	 * Generate code to load the length of the radio header into
2109190225Srpaulo	 * the register assigned to hold that length, if one has been
2110190225Srpaulo	 * assigned.  (If one hasn't been assigned, no code we've
2111190225Srpaulo	 * generated uses that prefix, so we don't need to generate any
2112190225Srpaulo	 * code to load it.)
2113190225Srpaulo	 *
2114190225Srpaulo	 * Some Linux drivers use ARPHRD_IEEE80211_PRISM but sometimes
2115190225Srpaulo	 * or always use the AVS header rather than the Prism header.
2116190225Srpaulo	 * We load a 4-byte big-endian value at the beginning of the
2117190225Srpaulo	 * raw packet data, and see whether, when masked with 0xFFFFF000,
2118190225Srpaulo	 * it's equal to 0x80211000.  If so, that indicates that it's
2119190225Srpaulo	 * an AVS header (the masked-out bits are the version number).
2120190225Srpaulo	 * Otherwise, it's a Prism header.
2121190225Srpaulo	 *
2122190225Srpaulo	 * XXX - the Prism header is also, in theory, variable-length,
2123190225Srpaulo	 * but no known software generates headers that aren't 144
2124190225Srpaulo	 * bytes long.
2125190225Srpaulo	 */
2126190225Srpaulo	if (reg_off_ll != -1) {
2127147897Ssam		/*
2128190225Srpaulo		 * Load the cookie.
2129190225Srpaulo		 */
2130190225Srpaulo		s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
2131190225Srpaulo		s1->s.k = 0;
2132190225Srpaulo
2133190225Srpaulo		/*
2134190225Srpaulo		 * AND it with 0xFFFFF000.
2135190225Srpaulo		 */
2136190225Srpaulo		s2 = new_stmt(BPF_ALU|BPF_AND|BPF_K);
2137190225Srpaulo		s2->s.k = 0xFFFFF000;
2138190225Srpaulo		sappend(s1, s2);
2139190225Srpaulo
2140190225Srpaulo		/*
2141190225Srpaulo		 * Compare with 0x80211000.
2142190225Srpaulo		 */
2143190225Srpaulo		sjeq_avs_cookie = new_stmt(JMP(BPF_JEQ));
2144190225Srpaulo		sjeq_avs_cookie->s.k = 0x80211000;
2145190225Srpaulo		sappend(s1, sjeq_avs_cookie);
2146190225Srpaulo
2147190225Srpaulo		/*
2148190225Srpaulo		 * If it's AVS:
2149190225Srpaulo		 *
2150190225Srpaulo		 * The 4 bytes at an offset of 4 from the beginning of
2151190225Srpaulo		 * the AVS header are the length of the AVS header.
2152190225Srpaulo		 * That field is big-endian.
2153190225Srpaulo		 */
2154190225Srpaulo		s2 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
2155190225Srpaulo		s2->s.k = 4;
2156190225Srpaulo		sappend(s1, s2);
2157190225Srpaulo		sjeq_avs_cookie->s.jt = s2;
2158190225Srpaulo
2159190225Srpaulo		/*
2160190225Srpaulo		 * Now jump to the code to allocate a register
2161190225Srpaulo		 * into which to save the header length and
2162190225Srpaulo		 * store the length there.  (The "jump always"
2163190225Srpaulo		 * instruction needs to have the k field set;
2164190225Srpaulo		 * it's added to the PC, so, as we're jumping
2165190225Srpaulo		 * over a single instruction, it should be 1.)
2166190225Srpaulo		 */
2167190225Srpaulo		sjcommon = new_stmt(JMP(BPF_JA));
2168190225Srpaulo		sjcommon->s.k = 1;
2169190225Srpaulo		sappend(s1, sjcommon);
2170190225Srpaulo
2171190225Srpaulo		/*
2172190225Srpaulo		 * Now for the code that handles the Prism header.
2173190225Srpaulo		 * Just load the length of the Prism header (144)
2174190225Srpaulo		 * into the A register.  Have the test for an AVS
2175190225Srpaulo		 * header branch here if we don't have an AVS header.
2176190225Srpaulo		 */
2177190225Srpaulo		s2 = new_stmt(BPF_LD|BPF_W|BPF_IMM);
2178190225Srpaulo		s2->s.k = 144;
2179190225Srpaulo		sappend(s1, s2);
2180190225Srpaulo		sjeq_avs_cookie->s.jf = s2;
2181190225Srpaulo
2182190225Srpaulo		/*
2183190225Srpaulo		 * Now allocate a register to hold that value and store
2184190225Srpaulo		 * it.  The code for the AVS header will jump here after
2185190225Srpaulo		 * loading the length of the AVS header.
2186190225Srpaulo		 */
2187190225Srpaulo		s2 = new_stmt(BPF_ST);
2188190225Srpaulo		s2->s.k = reg_off_ll;
2189190225Srpaulo		sappend(s1, s2);
2190190225Srpaulo		sjcommon->s.jf = s2;
2191190225Srpaulo
2192190225Srpaulo		/*
2193190225Srpaulo		 * Now move it into the X register.
2194190225Srpaulo		 */
2195190225Srpaulo		s2 = new_stmt(BPF_MISC|BPF_TAX);
2196190225Srpaulo		sappend(s1, s2);
2197190225Srpaulo
2198190225Srpaulo		return (s1);
2199190225Srpaulo	} else
2200190225Srpaulo		return (NULL);
2201190225Srpaulo}
2202190225Srpaulo
2203190225Srpaulostatic struct slist *
2204190225Srpaulogen_load_avs_llprefixlen()
2205190225Srpaulo{
2206190225Srpaulo	struct slist *s1, *s2;
2207190225Srpaulo
2208190225Srpaulo	/*
2209190225Srpaulo	 * Generate code to load the length of the AVS header into
2210190225Srpaulo	 * the register assigned to hold that length, if one has been
2211190225Srpaulo	 * assigned.  (If one hasn't been assigned, no code we've
2212190225Srpaulo	 * generated uses that prefix, so we don't need to generate any
2213190225Srpaulo	 * code to load it.)
2214190225Srpaulo	 */
2215190225Srpaulo	if (reg_off_ll != -1) {
2216190225Srpaulo		/*
2217190225Srpaulo		 * The 4 bytes at an offset of 4 from the beginning of
2218190225Srpaulo		 * the AVS header are the length of the AVS header.
2219190225Srpaulo		 * That field is big-endian.
2220190225Srpaulo		 */
2221190225Srpaulo		s1 = new_stmt(BPF_LD|BPF_W|BPF_ABS);
2222190225Srpaulo		s1->s.k = 4;
2223190225Srpaulo
2224190225Srpaulo		/*
2225190225Srpaulo		 * Now allocate a register to hold that value and store
2226190225Srpaulo		 * it.
2227190225Srpaulo		 */
2228190225Srpaulo		s2 = new_stmt(BPF_ST);
2229190225Srpaulo		s2->s.k = reg_off_ll;
2230190225Srpaulo		sappend(s1, s2);
2231190225Srpaulo
2232190225Srpaulo		/*
2233190225Srpaulo		 * Now move it into the X register.
2234190225Srpaulo		 */
2235190225Srpaulo		s2 = new_stmt(BPF_MISC|BPF_TAX);
2236190225Srpaulo		sappend(s1, s2);
2237190225Srpaulo
2238190225Srpaulo		return (s1);
2239190225Srpaulo	} else
2240190225Srpaulo		return (NULL);
2241190225Srpaulo}
2242190225Srpaulo
2243190225Srpaulostatic struct slist *
2244190225Srpaulogen_load_radiotap_llprefixlen()
2245190225Srpaulo{
2246190225Srpaulo	struct slist *s1, *s2;
2247190225Srpaulo
2248190225Srpaulo	/*
2249190225Srpaulo	 * Generate code to load the length of the radiotap header into
2250190225Srpaulo	 * the register assigned to hold that length, if one has been
2251190225Srpaulo	 * assigned.  (If one hasn't been assigned, no code we've
2252190225Srpaulo	 * generated uses that prefix, so we don't need to generate any
2253190225Srpaulo	 * code to load it.)
2254190225Srpaulo	 */
2255190225Srpaulo	if (reg_off_ll != -1) {
2256190225Srpaulo		/*
2257147897Ssam		 * The 2 bytes at offsets of 2 and 3 from the beginning
2258147897Ssam		 * of the radiotap header are the length of the radiotap
2259147897Ssam		 * header; unfortunately, it's little-endian, so we have
2260147897Ssam		 * to load it a byte at a time and construct the value.
2261147897Ssam		 */
2262147897Ssam
2263147897Ssam		/*
2264147897Ssam		 * Load the high-order byte, at an offset of 3, shift it
2265147897Ssam		 * left a byte, and put the result in the X register.
2266147897Ssam		 */
2267147897Ssam		s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
2268147897Ssam		s1->s.k = 3;
2269147897Ssam		s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
2270147897Ssam		sappend(s1, s2);
2271147897Ssam		s2->s.k = 8;
2272147897Ssam		s2 = new_stmt(BPF_MISC|BPF_TAX);
2273147897Ssam		sappend(s1, s2);
2274147897Ssam
2275147897Ssam		/*
2276147897Ssam		 * Load the next byte, at an offset of 2, and OR the
2277147897Ssam		 * value from the X register into it.
2278147897Ssam		 */
2279147897Ssam		s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
2280147897Ssam		sappend(s1, s2);
2281147897Ssam		s2->s.k = 2;
2282147897Ssam		s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X);
2283147897Ssam		sappend(s1, s2);
2284147897Ssam
2285147897Ssam		/*
2286147897Ssam		 * Now allocate a register to hold that value and store
2287147897Ssam		 * it.
2288147897Ssam		 */
2289147897Ssam		s2 = new_stmt(BPF_ST);
2290190225Srpaulo		s2->s.k = reg_off_ll;
2291147897Ssam		sappend(s1, s2);
2292147897Ssam
2293147897Ssam		/*
2294147897Ssam		 * Now move it into the X register.
2295147897Ssam		 */
2296147897Ssam		s2 = new_stmt(BPF_MISC|BPF_TAX);
2297147897Ssam		sappend(s1, s2);
2298147897Ssam
2299190225Srpaulo		return (s1);
2300190225Srpaulo	} else
2301190225Srpaulo		return (NULL);
2302147897Ssam}
2303147897Ssam
2304172680Smlaier/*
2305172680Smlaier * At the moment we treat PPI as normal Radiotap encoded
2306172680Smlaier * packets. The difference is in the function that generates
2307172680Smlaier * the code at the beginning to compute the header length.
2308172680Smlaier * Since this code generator of PPI supports bare 802.11
2309172680Smlaier * encapsulation only (i.e. the encapsulated DLT should be
2310190225Srpaulo * DLT_IEEE802_11) we generate code to check for this too;
2311190225Srpaulo * that's done in finish_parse().
2312172680Smlaier */
2313190225Srpaulostatic struct slist *
2314190225Srpaulogen_load_ppi_llprefixlen()
2315172680Smlaier{
2316172680Smlaier	struct slist *s1, *s2;
2317172680Smlaier
2318172680Smlaier	/*
2319190225Srpaulo	 * Generate code to load the length of the radiotap header
2320190225Srpaulo	 * into the register assigned to hold that length, if one has
2321190225Srpaulo	 * been assigned.
2322172680Smlaier	 */
2323190225Srpaulo	if (reg_off_ll != -1) {
2324190225Srpaulo		/*
2325172680Smlaier		 * The 2 bytes at offsets of 2 and 3 from the beginning
2326172680Smlaier		 * of the radiotap header are the length of the radiotap
2327172680Smlaier		 * header; unfortunately, it's little-endian, so we have
2328172680Smlaier		 * to load it a byte at a time and construct the value.
2329172680Smlaier		 */
2330147897Ssam
2331172680Smlaier		/*
2332172680Smlaier		 * Load the high-order byte, at an offset of 3, shift it
2333172680Smlaier		 * left a byte, and put the result in the X register.
2334172680Smlaier		 */
2335172680Smlaier		s1 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
2336172680Smlaier		s1->s.k = 3;
2337172680Smlaier		s2 = new_stmt(BPF_ALU|BPF_LSH|BPF_K);
2338172680Smlaier		sappend(s1, s2);
2339172680Smlaier		s2->s.k = 8;
2340172680Smlaier		s2 = new_stmt(BPF_MISC|BPF_TAX);
2341172680Smlaier		sappend(s1, s2);
2342172680Smlaier
2343172680Smlaier		/*
2344172680Smlaier		 * Load the next byte, at an offset of 2, and OR the
2345172680Smlaier		 * value from the X register into it.
2346172680Smlaier		 */
2347172680Smlaier		s2 = new_stmt(BPF_LD|BPF_B|BPF_ABS);
2348172680Smlaier		sappend(s1, s2);
2349172680Smlaier		s2->s.k = 2;
2350172680Smlaier		s2 = new_stmt(BPF_ALU|BPF_OR|BPF_X);
2351172680Smlaier		sappend(s1, s2);
2352172680Smlaier
2353172680Smlaier		/*
2354172680Smlaier		 * Now allocate a register to hold that value and store
2355172680Smlaier		 * it.
2356172680Smlaier		 */
2357172680Smlaier		s2 = new_stmt(BPF_ST);
2358190225Srpaulo		s2->s.k = reg_off_ll;
2359172680Smlaier		sappend(s1, s2);
2360172680Smlaier
2361172680Smlaier		/*
2362172680Smlaier		 * Now move it into the X register.
2363172680Smlaier		 */
2364172680Smlaier		s2 = new_stmt(BPF_MISC|BPF_TAX);
2365172680Smlaier		sappend(s1, s2);
2366172680Smlaier
2367190225Srpaulo		return (s1);
2368190225Srpaulo	} else
2369190225Srpaulo		return (NULL);
2370190225Srpaulo}
2371190225Srpaulo
2372190225Srpaulo/*
2373190225Srpaulo * Load a value relative to the beginning of the link-layer header after the 802.11
2374190225Srpaulo * header, i.e. LLC_SNAP.
2375190225Srpaulo * The link-layer header doesn't necessarily begin at the beginning
2376190225Srpaulo * of the packet data; there might be a variable-length prefix containing
2377190225Srpaulo * radio information.
2378190225Srpaulo */
2379190225Srpaulostatic struct slist *
2380190225Srpaulogen_load_802_11_header_len(struct slist *s, struct slist *snext)
2381190225Srpaulo{
2382190225Srpaulo	struct slist *s2;
2383190225Srpaulo	struct slist *sjset_data_frame_1;
2384190225Srpaulo	struct slist *sjset_data_frame_2;
2385190225Srpaulo	struct slist *sjset_qos;
2386190225Srpaulo	struct slist *sjset_radiotap_flags;
2387190225Srpaulo	struct slist *sjset_radiotap_tsft;
2388190225Srpaulo	struct slist *sjset_tsft_datapad, *sjset_notsft_datapad;
2389190225Srpaulo	struct slist *s_roundup;
2390190225Srpaulo
2391190225Srpaulo	if (reg_off_macpl == -1) {
2392172680Smlaier		/*
2393190225Srpaulo		 * No register has been assigned to the offset of
2394190225Srpaulo		 * the MAC-layer payload, which means nobody needs
2395190225Srpaulo		 * it; don't bother computing it - just return
2396190225Srpaulo		 * what we already have.
2397172680Smlaier		 */
2398190225Srpaulo		return (s);
2399190225Srpaulo	}
2400172680Smlaier
2401190225Srpaulo	/*
2402190225Srpaulo	 * This code is not compatible with the optimizer, as
2403190225Srpaulo	 * we are generating jmp instructions within a normal
2404190225Srpaulo	 * slist of instructions
2405190225Srpaulo	 */
2406190225Srpaulo	no_optimize = 1;
2407190225Srpaulo
2408190225Srpaulo	/*
2409190225Srpaulo	 * If "s" is non-null, it has code to arrange that the X register
2410190225Srpaulo	 * contains the length of the prefix preceding the link-layer
2411190225Srpaulo	 * header.
2412190225Srpaulo	 *
2413190225Srpaulo	 * Otherwise, the length of the prefix preceding the link-layer
2414190225Srpaulo	 * header is "off_ll".
2415190225Srpaulo	 */
2416190225Srpaulo	if (s == NULL) {
2417190225Srpaulo		/*
2418190225Srpaulo		 * There is no variable-length header preceding the
2419190225Srpaulo		 * link-layer header.
2420190225Srpaulo		 *
2421190225Srpaulo		 * Load the length of the fixed-length prefix preceding
2422190225Srpaulo		 * the link-layer header (if any) into the X register,
2423190225Srpaulo		 * and store it in the reg_off_macpl register.
2424190225Srpaulo		 * That length is off_ll.
2425190225Srpaulo		 */
2426190225Srpaulo		s = new_stmt(BPF_LDX|BPF_IMM);
2427190225Srpaulo		s->s.k = off_ll;
2428172680Smlaier	}
2429190225Srpaulo
2430190225Srpaulo	/*
2431190225Srpaulo	 * The X register contains the offset of the beginning of the
2432190225Srpaulo	 * link-layer header; add 24, which is the minimum length
2433190225Srpaulo	 * of the MAC header for a data frame, to that, and store it
2434190225Srpaulo	 * in reg_off_macpl, and then load the Frame Control field,
2435190225Srpaulo	 * which is at the offset in the X register, with an indexed load.
2436190225Srpaulo	 */
2437190225Srpaulo	s2 = new_stmt(BPF_MISC|BPF_TXA);
2438190225Srpaulo	sappend(s, s2);
2439190225Srpaulo	s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
2440190225Srpaulo	s2->s.k = 24;
2441190225Srpaulo	sappend(s, s2);
2442190225Srpaulo	s2 = new_stmt(BPF_ST);
2443190225Srpaulo	s2->s.k = reg_off_macpl;
2444190225Srpaulo	sappend(s, s2);
2445190225Srpaulo
2446190225Srpaulo	s2 = new_stmt(BPF_LD|BPF_IND|BPF_B);
2447190225Srpaulo	s2->s.k = 0;
2448190225Srpaulo	sappend(s, s2);
2449190225Srpaulo
2450190225Srpaulo	/*
2451190225Srpaulo	 * Check the Frame Control field to see if this is a data frame;
2452190225Srpaulo	 * a data frame has the 0x08 bit (b3) in that field set and the
2453190225Srpaulo	 * 0x04 bit (b2) clear.
2454190225Srpaulo	 */
2455190225Srpaulo	sjset_data_frame_1 = new_stmt(JMP(BPF_JSET));
2456190225Srpaulo	sjset_data_frame_1->s.k = 0x08;
2457190225Srpaulo	sappend(s, sjset_data_frame_1);
2458190225Srpaulo
2459190225Srpaulo	/*
2460190225Srpaulo	 * If b3 is set, test b2, otherwise go to the first statement of
2461190225Srpaulo	 * the rest of the program.
2462190225Srpaulo	 */
2463190225Srpaulo	sjset_data_frame_1->s.jt = sjset_data_frame_2 = new_stmt(JMP(BPF_JSET));
2464190225Srpaulo	sjset_data_frame_2->s.k = 0x04;
2465190225Srpaulo	sappend(s, sjset_data_frame_2);
2466190225Srpaulo	sjset_data_frame_1->s.jf = snext;
2467190225Srpaulo
2468190225Srpaulo	/*
2469190225Srpaulo	 * If b2 is not set, this is a data frame; test the QoS bit.
2470190225Srpaulo	 * Otherwise, go to the first statement of the rest of the
2471190225Srpaulo	 * program.
2472190225Srpaulo	 */
2473190225Srpaulo	sjset_data_frame_2->s.jt = snext;
2474190225Srpaulo	sjset_data_frame_2->s.jf = sjset_qos = new_stmt(JMP(BPF_JSET));
2475190225Srpaulo	sjset_qos->s.k = 0x80;	/* QoS bit */
2476190225Srpaulo	sappend(s, sjset_qos);
2477190225Srpaulo
2478190225Srpaulo	/*
2479190225Srpaulo	 * If it's set, add 2 to reg_off_macpl, to skip the QoS
2480190225Srpaulo	 * field.
2481190225Srpaulo	 * Otherwise, go to the first statement of the rest of the
2482190225Srpaulo	 * program.
2483190225Srpaulo	 */
2484190225Srpaulo	sjset_qos->s.jt = s2 = new_stmt(BPF_LD|BPF_MEM);
2485190225Srpaulo	s2->s.k = reg_off_macpl;
2486190225Srpaulo	sappend(s, s2);
2487190225Srpaulo	s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
2488190225Srpaulo	s2->s.k = 2;
2489190225Srpaulo	sappend(s, s2);
2490190225Srpaulo	s2 = new_stmt(BPF_ST);
2491190225Srpaulo	s2->s.k = reg_off_macpl;
2492190225Srpaulo	sappend(s, s2);
2493190225Srpaulo
2494190225Srpaulo	/*
2495190225Srpaulo	 * If we have a radiotap header, look at it to see whether
2496190225Srpaulo	 * there's Atheros padding between the MAC-layer header
2497190225Srpaulo	 * and the payload.
2498190225Srpaulo	 *
2499190225Srpaulo	 * Note: all of the fields in the radiotap header are
2500190225Srpaulo	 * little-endian, so we byte-swap all of the values
2501190225Srpaulo	 * we test against, as they will be loaded as big-endian
2502190225Srpaulo	 * values.
2503190225Srpaulo	 */
2504190225Srpaulo	if (linktype == DLT_IEEE802_11_RADIO) {
2505190225Srpaulo		/*
2506190225Srpaulo		 * Is the IEEE80211_RADIOTAP_FLAGS bit (0x0000002) set
2507190225Srpaulo		 * in the presence flag?
2508190225Srpaulo		 */
2509190225Srpaulo		sjset_qos->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_W);
2510190225Srpaulo		s2->s.k = 4;
2511190225Srpaulo		sappend(s, s2);
2512190225Srpaulo
2513190225Srpaulo		sjset_radiotap_flags = new_stmt(JMP(BPF_JSET));
2514190225Srpaulo		sjset_radiotap_flags->s.k = SWAPLONG(0x00000002);
2515190225Srpaulo		sappend(s, sjset_radiotap_flags);
2516190225Srpaulo
2517190225Srpaulo		/*
2518190225Srpaulo		 * If not, skip all of this.
2519190225Srpaulo		 */
2520190225Srpaulo		sjset_radiotap_flags->s.jf = snext;
2521190225Srpaulo
2522190225Srpaulo		/*
2523190225Srpaulo		 * Otherwise, is the IEEE80211_RADIOTAP_TSFT bit set?
2524190225Srpaulo		 */
2525190225Srpaulo		sjset_radiotap_tsft = sjset_radiotap_flags->s.jt =
2526190225Srpaulo		    new_stmt(JMP(BPF_JSET));
2527190225Srpaulo		sjset_radiotap_tsft->s.k = SWAPLONG(0x00000001);
2528190225Srpaulo		sappend(s, sjset_radiotap_tsft);
2529190225Srpaulo
2530190225Srpaulo		/*
2531190225Srpaulo		 * If IEEE80211_RADIOTAP_TSFT is set, the flags field is
2532190225Srpaulo		 * at an offset of 16 from the beginning of the raw packet
2533190225Srpaulo		 * data (8 bytes for the radiotap header and 8 bytes for
2534190225Srpaulo		 * the TSFT field).
2535190225Srpaulo		 *
2536190225Srpaulo		 * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
2537190225Srpaulo		 * is set.
2538190225Srpaulo		 */
2539190225Srpaulo		sjset_radiotap_tsft->s.jt = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
2540190225Srpaulo		s2->s.k = 16;
2541190225Srpaulo		sappend(s, s2);
2542190225Srpaulo
2543190225Srpaulo		sjset_tsft_datapad = new_stmt(JMP(BPF_JSET));
2544190225Srpaulo		sjset_tsft_datapad->s.k = 0x20;
2545190225Srpaulo		sappend(s, sjset_tsft_datapad);
2546190225Srpaulo
2547190225Srpaulo		/*
2548190225Srpaulo		 * If IEEE80211_RADIOTAP_TSFT is not set, the flags field is
2549190225Srpaulo		 * at an offset of 8 from the beginning of the raw packet
2550190225Srpaulo		 * data (8 bytes for the radiotap header).
2551190225Srpaulo		 *
2552190225Srpaulo		 * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
2553190225Srpaulo		 * is set.
2554190225Srpaulo		 */
2555190225Srpaulo		sjset_radiotap_tsft->s.jf = s2 = new_stmt(BPF_LD|BPF_ABS|BPF_B);
2556190225Srpaulo		s2->s.k = 8;
2557190225Srpaulo		sappend(s, s2);
2558190225Srpaulo
2559190225Srpaulo		sjset_notsft_datapad = new_stmt(JMP(BPF_JSET));
2560190225Srpaulo		sjset_notsft_datapad->s.k = 0x20;
2561190225Srpaulo		sappend(s, sjset_notsft_datapad);
2562190225Srpaulo
2563190225Srpaulo		/*
2564190225Srpaulo		 * In either case, if IEEE80211_RADIOTAP_F_DATAPAD is
2565190225Srpaulo		 * set, round the length of the 802.11 header to
2566190225Srpaulo		 * a multiple of 4.  Do that by adding 3 and then
2567190225Srpaulo		 * dividing by and multiplying by 4, which we do by
2568190225Srpaulo		 * ANDing with ~3.
2569190225Srpaulo		 */
2570190225Srpaulo		s_roundup = new_stmt(BPF_LD|BPF_MEM);
2571190225Srpaulo		s_roundup->s.k = reg_off_macpl;
2572190225Srpaulo		sappend(s, s_roundup);
2573190225Srpaulo		s2 = new_stmt(BPF_ALU|BPF_ADD|BPF_IMM);
2574190225Srpaulo		s2->s.k = 3;
2575190225Srpaulo		sappend(s, s2);
2576190225Srpaulo		s2 = new_stmt(BPF_ALU|BPF_AND|BPF_IMM);
2577190225Srpaulo		s2->s.k = ~3;
2578190225Srpaulo		sappend(s, s2);
2579190225Srpaulo		s2 = new_stmt(BPF_ST);
2580190225Srpaulo		s2->s.k = reg_off_macpl;
2581190225Srpaulo		sappend(s, s2);
2582190225Srpaulo
2583190225Srpaulo		sjset_tsft_datapad->s.jt = s_roundup;
2584190225Srpaulo		sjset_tsft_datapad->s.jf = snext;
2585190225Srpaulo		sjset_notsft_datapad->s.jt = s_roundup;
2586190225Srpaulo		sjset_notsft_datapad->s.jf = snext;
2587190225Srpaulo	} else
2588190225Srpaulo		sjset_qos->s.jf = snext;
2589190225Srpaulo
2590190225Srpaulo	return s;
2591172680Smlaier}
2592190225Srpaulo
2593190225Srpaulostatic void
2594190225Srpauloinsert_compute_vloffsets(b)
2595190225Srpaulo	struct block *b;
2596190225Srpaulo{
2597190225Srpaulo	struct slist *s;
2598190225Srpaulo
2599190225Srpaulo	/*
2600190225Srpaulo	 * For link-layer types that have a variable-length header
2601190225Srpaulo	 * preceding the link-layer header, generate code to load
2602190225Srpaulo	 * the offset of the link-layer header into the register
2603190225Srpaulo	 * assigned to that offset, if any.
2604190225Srpaulo	 */
2605190225Srpaulo	switch (linktype) {
2606190225Srpaulo
2607190225Srpaulo	case DLT_PRISM_HEADER:
2608190225Srpaulo		s = gen_load_prism_llprefixlen();
2609190225Srpaulo		break;
2610190225Srpaulo
2611190225Srpaulo	case DLT_IEEE802_11_RADIO_AVS:
2612190225Srpaulo		s = gen_load_avs_llprefixlen();
2613190225Srpaulo		break;
2614190225Srpaulo
2615190225Srpaulo	case DLT_IEEE802_11_RADIO:
2616190225Srpaulo		s = gen_load_radiotap_llprefixlen();
2617190225Srpaulo		break;
2618190225Srpaulo
2619190225Srpaulo	case DLT_PPI:
2620190225Srpaulo		s = gen_load_ppi_llprefixlen();
2621190225Srpaulo		break;
2622190225Srpaulo
2623190225Srpaulo	default:
2624190225Srpaulo		s = NULL;
2625190225Srpaulo		break;
2626190225Srpaulo	}
2627190225Srpaulo
2628190225Srpaulo	/*
2629190225Srpaulo	 * For link-layer types that have a variable-length link-layer
2630190225Srpaulo	 * header, generate code to load the offset of the MAC-layer
2631190225Srpaulo	 * payload into the register assigned to that offset, if any.
2632190225Srpaulo	 */
2633190225Srpaulo	switch (linktype) {
2634190225Srpaulo
2635190225Srpaulo	case DLT_IEEE802_11:
2636190225Srpaulo	case DLT_PRISM_HEADER:
2637190225Srpaulo	case DLT_IEEE802_11_RADIO_AVS:
2638190225Srpaulo	case DLT_IEEE802_11_RADIO:
2639190225Srpaulo	case DLT_PPI:
2640190225Srpaulo		s = gen_load_802_11_header_len(s, b->stmts);
2641190225Srpaulo		break;
2642190225Srpaulo	}
2643190225Srpaulo
2644190225Srpaulo	/*
2645190225Srpaulo	 * If we have any offset-loading code, append all the
2646190225Srpaulo	 * existing statements in the block to those statements,
2647190225Srpaulo	 * and make the resulting list the list of statements
2648190225Srpaulo	 * for the block.
2649190225Srpaulo	 */
2650190225Srpaulo	if (s != NULL) {
2651190225Srpaulo		sappend(s, b->stmts);
2652190225Srpaulo		b->stmts = s;
2653190225Srpaulo	}
2654190225Srpaulo}
2655190225Srpaulo
2656172680Smlaierstatic struct block *
2657172680Smlaiergen_ppi_dlt_check(void)
2658172680Smlaier{
2659172680Smlaier	struct slist *s_load_dlt;
2660172680Smlaier	struct block *b;
2661172680Smlaier
2662172680Smlaier	if (linktype == DLT_PPI)
2663172680Smlaier	{
2664172680Smlaier		/* Create the statements that check for the DLT
2665172680Smlaier		 */
2666172680Smlaier		s_load_dlt = new_stmt(BPF_LD|BPF_W|BPF_ABS);
2667172680Smlaier		s_load_dlt->s.k = 4;
2668172680Smlaier
2669172680Smlaier		b = new_block(JMP(BPF_JEQ));
2670172680Smlaier
2671172680Smlaier		b->stmts = s_load_dlt;
2672172680Smlaier		b->s.k = SWAPLONG(DLT_IEEE802_11);
2673172680Smlaier	}
2674172680Smlaier	else
2675172680Smlaier	{
2676172680Smlaier		b = NULL;
2677172680Smlaier	}
2678172680Smlaier
2679172680Smlaier	return b;
2680172680Smlaier}
2681172680Smlaier
2682190225Srpaulostatic struct slist *
2683190225Srpaulogen_prism_llprefixlen(void)
2684147897Ssam{
2685190225Srpaulo	struct slist *s;
2686147897Ssam
2687190225Srpaulo	if (reg_off_ll == -1) {
2688190225Srpaulo		/*
2689190225Srpaulo		 * We haven't yet assigned a register for the length
2690190225Srpaulo		 * of the radio header; allocate one.
2691190225Srpaulo		 */
2692190225Srpaulo		reg_off_ll = alloc_reg();
2693190225Srpaulo	}
2694190225Srpaulo
2695190225Srpaulo	/*
2696190225Srpaulo	 * Load the register containing the radio length
2697190225Srpaulo	 * into the X register.
2698172680Smlaier	 */
2699190225Srpaulo	s = new_stmt(BPF_LDX|BPF_MEM);
2700190225Srpaulo	s->s.k = reg_off_ll;
2701190225Srpaulo	return s;
2702190225Srpaulo}
2703172680Smlaier
2704190225Srpaulostatic struct slist *
2705190225Srpaulogen_avs_llprefixlen(void)
2706190225Srpaulo{
2707190225Srpaulo	struct slist *s;
2708190225Srpaulo
2709190225Srpaulo	if (reg_off_ll == -1) {
2710190225Srpaulo		/*
2711190225Srpaulo		 * We haven't yet assigned a register for the length
2712190225Srpaulo		 * of the AVS header; allocate one.
2713190225Srpaulo		 */
2714190225Srpaulo		reg_off_ll = alloc_reg();
2715147897Ssam	}
2716190225Srpaulo
2717190225Srpaulo	/*
2718190225Srpaulo	 * Load the register containing the AVS length
2719190225Srpaulo	 * into the X register.
2720190225Srpaulo	 */
2721190225Srpaulo	s = new_stmt(BPF_LDX|BPF_MEM);
2722190225Srpaulo	s->s.k = reg_off_ll;
2723190225Srpaulo	return s;
2724147897Ssam}
2725147897Ssam
2726147897Ssamstatic struct slist *
2727147897Ssamgen_radiotap_llprefixlen(void)
2728147897Ssam{
2729147897Ssam	struct slist *s;
2730147897Ssam
2731190225Srpaulo	if (reg_off_ll == -1) {
2732147897Ssam		/*
2733147897Ssam		 * We haven't yet assigned a register for the length
2734147897Ssam		 * of the radiotap header; allocate one.
2735147897Ssam		 */
2736190225Srpaulo		reg_off_ll = alloc_reg();
2737147897Ssam	}
2738147897Ssam
2739147897Ssam	/*
2740147897Ssam	 * Load the register containing the radiotap length
2741147897Ssam	 * into the X register.
2742147897Ssam	 */
2743147897Ssam	s = new_stmt(BPF_LDX|BPF_MEM);
2744190225Srpaulo	s->s.k = reg_off_ll;
2745147897Ssam	return s;
2746147897Ssam}
2747147897Ssam
2748172680Smlaier/*
2749172680Smlaier * At the moment we treat PPI as normal Radiotap encoded
2750172680Smlaier * packets. The difference is in the function that generates
2751172680Smlaier * the code at the beginning to compute the header length.
2752172680Smlaier * Since this code generator of PPI supports bare 802.11
2753172680Smlaier * encapsulation only (i.e. the encapsulated DLT should be
2754172680Smlaier * DLT_IEEE802_11) we generate code to check for this too.
2755172680Smlaier */
2756172680Smlaierstatic struct slist *
2757172680Smlaiergen_ppi_llprefixlen(void)
2758172680Smlaier{
2759172680Smlaier	struct slist *s;
2760172680Smlaier
2761190225Srpaulo	if (reg_off_ll == -1) {
2762172680Smlaier		/*
2763172680Smlaier		 * We haven't yet assigned a register for the length
2764172680Smlaier		 * of the radiotap header; allocate one.
2765172680Smlaier		 */
2766190225Srpaulo		reg_off_ll = alloc_reg();
2767172680Smlaier	}
2768172680Smlaier
2769172680Smlaier	/*
2770190225Srpaulo	 * Load the register containing the PPI length
2771172680Smlaier	 * into the X register.
2772172680Smlaier	 */
2773172680Smlaier	s = new_stmt(BPF_LDX|BPF_MEM);
2774190225Srpaulo	s->s.k = reg_off_ll;
2775172680Smlaier	return s;
2776172680Smlaier}
2777172680Smlaier
2778147897Ssam/*
2779147897Ssam * Generate code to compute the link-layer header length, if necessary,
2780147897Ssam * putting it into the X register, and to return either a pointer to a
2781147897Ssam * "struct slist" for the list of statements in that code, or NULL if
2782147897Ssam * no code is necessary.
2783147897Ssam */
2784147897Ssamstatic struct slist *
2785147897Ssamgen_llprefixlen(void)
2786147897Ssam{
2787147897Ssam	switch (linktype) {
2788147897Ssam
2789190225Srpaulo	case DLT_PRISM_HEADER:
2790190225Srpaulo		return gen_prism_llprefixlen();
2791172680Smlaier
2792190225Srpaulo	case DLT_IEEE802_11_RADIO_AVS:
2793190225Srpaulo		return gen_avs_llprefixlen();
2794190225Srpaulo
2795147897Ssam	case DLT_IEEE802_11_RADIO:
2796147897Ssam		return gen_radiotap_llprefixlen();
2797147897Ssam
2798190225Srpaulo	case DLT_PPI:
2799190225Srpaulo		return gen_ppi_llprefixlen();
2800190225Srpaulo
2801147897Ssam	default:
2802147897Ssam		return NULL;
2803147897Ssam	}
2804147897Ssam}
2805147897Ssam
2806147897Ssam/*
2807190225Srpaulo * Generate code to load the register containing the offset of the
2808190225Srpaulo * MAC-layer payload into the X register; if no register for that offset
2809190225Srpaulo * has been allocated, allocate it first.
2810190225Srpaulo */
2811190225Srpaulostatic struct slist *
2812190225Srpaulogen_off_macpl(void)
2813190225Srpaulo{
2814190225Srpaulo	struct slist *s;
2815190225Srpaulo
2816190225Srpaulo	if (off_macpl_is_variable) {
2817190225Srpaulo		if (reg_off_macpl == -1) {
2818190225Srpaulo			/*
2819190225Srpaulo			 * We haven't yet assigned a register for the offset
2820190225Srpaulo			 * of the MAC-layer payload; allocate one.
2821190225Srpaulo			 */
2822190225Srpaulo			reg_off_macpl = alloc_reg();
2823190225Srpaulo		}
2824190225Srpaulo
2825190225Srpaulo		/*
2826190225Srpaulo		 * Load the register containing the offset of the MAC-layer
2827190225Srpaulo		 * payload into the X register.
2828190225Srpaulo		 */
2829190225Srpaulo		s = new_stmt(BPF_LDX|BPF_MEM);
2830190225Srpaulo		s->s.k = reg_off_macpl;
2831190225Srpaulo		return s;
2832190225Srpaulo	} else {
2833190225Srpaulo		/*
2834190225Srpaulo		 * That offset isn't variable, so we don't need to
2835190225Srpaulo		 * generate any code.
2836190225Srpaulo		 */
2837190225Srpaulo		return NULL;
2838190225Srpaulo	}
2839190225Srpaulo}
2840190225Srpaulo
2841190225Srpaulo/*
2842190225Srpaulo * Map an Ethernet type to the equivalent PPP type.
2843190225Srpaulo */
2844190225Srpaulostatic int
2845190225Srpauloethertype_to_ppptype(proto)
2846190225Srpaulo	int proto;
2847190225Srpaulo{
2848190225Srpaulo	switch (proto) {
2849190225Srpaulo
2850190225Srpaulo	case ETHERTYPE_IP:
2851190225Srpaulo		proto = PPP_IP;
2852190225Srpaulo		break;
2853190225Srpaulo
2854190225Srpaulo	case ETHERTYPE_IPV6:
2855190225Srpaulo		proto = PPP_IPV6;
2856190225Srpaulo		break;
2857190225Srpaulo
2858190225Srpaulo	case ETHERTYPE_DN:
2859190225Srpaulo		proto = PPP_DECNET;
2860190225Srpaulo		break;
2861190225Srpaulo
2862190225Srpaulo	case ETHERTYPE_ATALK:
2863190225Srpaulo		proto = PPP_APPLE;
2864190225Srpaulo		break;
2865190225Srpaulo
2866190225Srpaulo	case ETHERTYPE_NS:
2867190225Srpaulo		proto = PPP_NS;
2868190225Srpaulo		break;
2869190225Srpaulo
2870190225Srpaulo	case LLCSAP_ISONS:
2871190225Srpaulo		proto = PPP_OSI;
2872190225Srpaulo		break;
2873190225Srpaulo
2874190225Srpaulo	case LLCSAP_8021D:
2875190225Srpaulo		/*
2876190225Srpaulo		 * I'm assuming the "Bridging PDU"s that go
2877190225Srpaulo		 * over PPP are Spanning Tree Protocol
2878190225Srpaulo		 * Bridging PDUs.
2879190225Srpaulo		 */
2880190225Srpaulo		proto = PPP_BRPDU;
2881190225Srpaulo		break;
2882190225Srpaulo
2883190225Srpaulo	case LLCSAP_IPX:
2884190225Srpaulo		proto = PPP_IPX;
2885190225Srpaulo		break;
2886190225Srpaulo	}
2887190225Srpaulo	return (proto);
2888190225Srpaulo}
2889190225Srpaulo
2890190225Srpaulo/*
2891147897Ssam * Generate code to match a particular packet type by matching the
2892147897Ssam * link-layer type field or fields in the 802.2 LLC header.
2893147897Ssam *
2894147897Ssam * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
2895147897Ssam * value, if <= ETHERMTU.
2896147897Ssam */
2897146771Ssamstatic struct block *
2898127667Sbmsgen_linktype(proto)
2899127667Sbms	register int proto;
2900127667Sbms{
2901127667Sbms	struct block *b0, *b1, *b2;
290298533Sfenner
2903162015Ssam	/* are we checking MPLS-encapsulated packets? */
2904162015Ssam	if (label_stack_depth > 0) {
2905162015Ssam		switch (proto) {
2906162015Ssam		case ETHERTYPE_IP:
2907162015Ssam		case PPP_IP:
2908190225Srpaulo			/* FIXME add other L3 proto IDs */
2909162015Ssam			return gen_mpls_linktype(Q_IP);
2910162015Ssam
2911162015Ssam		case ETHERTYPE_IPV6:
2912162015Ssam		case PPP_IPV6:
2913190225Srpaulo			/* FIXME add other L3 proto IDs */
2914162015Ssam			return gen_mpls_linktype(Q_IPV6);
2915162015Ssam
2916162015Ssam		default:
2917162015Ssam			bpf_error("unsupported protocol over mpls");
2918162015Ssam			/* NOTREACHED */
2919162015Ssam		}
2920162015Ssam	}
2921162015Ssam
2922190225Srpaulo	/*
2923190225Srpaulo	 * Are we testing PPPoE packets?
2924190225Srpaulo	 */
2925190225Srpaulo	if (is_pppoes) {
2926190225Srpaulo		/*
2927190225Srpaulo		 * The PPPoE session header is part of the
2928190225Srpaulo		 * MAC-layer payload, so all references
2929190225Srpaulo		 * should be relative to the beginning of
2930190225Srpaulo		 * that payload.
2931190225Srpaulo		 */
2932190225Srpaulo
2933190225Srpaulo		/*
2934190225Srpaulo		 * We use Ethernet protocol types inside libpcap;
2935190225Srpaulo		 * map them to the corresponding PPP protocol types.
2936190225Srpaulo		 */
2937190225Srpaulo		proto = ethertype_to_ppptype(proto);
2938190225Srpaulo		return gen_cmp(OR_MACPL, off_linktype, BPF_H, (bpf_int32)proto);
2939190225Srpaulo	}
2940190225Srpaulo
2941127667Sbms	switch (linktype) {
2942127667Sbms
2943127667Sbms	case DLT_EN10MB:
2944236167Sdelphij	case DLT_NETANALYZER:
2945236167Sdelphij	case DLT_NETANALYZER_TRANSPARENT:
2946127667Sbms		return gen_ether_linktype(proto);
2947146771Ssam		/*NOTREACHED*/
2948127667Sbms		break;
2949127667Sbms
2950127667Sbms	case DLT_C_HDLC:
2951127667Sbms		switch (proto) {
2952127667Sbms
2953127667Sbms		case LLCSAP_ISONS:
2954127667Sbms			proto = (proto << 8 | LLCSAP_ISONS);
2955127667Sbms			/* fall through */
2956127667Sbms
295798533Sfenner		default:
2958147897Ssam			return gen_cmp(OR_LINK, off_linktype, BPF_H,
2959147897Ssam			    (bpf_int32)proto);
2960146771Ssam			/*NOTREACHED*/
2961127667Sbms			break;
296275110Sfenner		}
296375110Sfenner		break;
296475110Sfenner
2965190225Srpaulo	case DLT_IEEE802_11:
2966190225Srpaulo	case DLT_PRISM_HEADER:
2967190225Srpaulo	case DLT_IEEE802_11_RADIO_AVS:
2968190225Srpaulo	case DLT_IEEE802_11_RADIO:
2969172680Smlaier	case DLT_PPI:
2970190225Srpaulo		/*
2971190225Srpaulo		 * Check that we have a data frame.
2972190225Srpaulo		 */
2973190225Srpaulo		b0 = gen_check_802_11_data_frame();
2974190225Srpaulo
2975190225Srpaulo		/*
2976190225Srpaulo		 * Now check for the specified link-layer type.
2977190225Srpaulo		 */
2978190225Srpaulo		b1 = gen_llc_linktype(proto);
2979190225Srpaulo		gen_and(b0, b1);
2980190225Srpaulo		return b1;
2981190225Srpaulo		/*NOTREACHED*/
2982190225Srpaulo		break;
2983190225Srpaulo
2984147897Ssam	case DLT_FDDI:
2985190225Srpaulo		/*
2986190225Srpaulo		 * XXX - check for asynchronous frames, as per RFC 1103.
2987190225Srpaulo		 */
2988190225Srpaulo		return gen_llc_linktype(proto);
2989190225Srpaulo		/*NOTREACHED*/
2990190225Srpaulo		break;
2991190225Srpaulo
2992147897Ssam	case DLT_IEEE802:
2993190225Srpaulo		/*
2994190225Srpaulo		 * XXX - check for LLC PDUs, as per IEEE 802.5.
2995190225Srpaulo		 */
2996190225Srpaulo		return gen_llc_linktype(proto);
2997190225Srpaulo		/*NOTREACHED*/
2998190225Srpaulo		break;
2999190225Srpaulo
300098533Sfenner	case DLT_ATM_RFC1483:
300198533Sfenner	case DLT_ATM_CLIP:
3002127667Sbms	case DLT_IP_OVER_FC:
3003147897Ssam		return gen_llc_linktype(proto);
3004146771Ssam		/*NOTREACHED*/
3005127667Sbms		break;
3006127667Sbms
3007127667Sbms	case DLT_SUNATM:
300898533Sfenner		/*
3009127667Sbms		 * If "is_lane" is set, check for a LANE-encapsulated
3010127667Sbms		 * version of this protocol, otherwise check for an
3011127667Sbms		 * LLC-encapsulated version of this protocol.
3012127667Sbms		 *
3013127667Sbms		 * We assume LANE means Ethernet, not Token Ring.
301498533Sfenner		 */
3015127667Sbms		if (is_lane) {
301698533Sfenner			/*
3017127667Sbms			 * Check that the packet doesn't begin with an
3018127667Sbms			 * LE Control marker.  (We've already generated
3019127667Sbms			 * a test for LANE.)
302098533Sfenner			 */
3021147897Ssam			b0 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
3022147897Ssam			    0xFF00);
3023127667Sbms			gen_not(b0);
302498533Sfenner
302598533Sfenner			/*
3026127667Sbms			 * Now generate an Ethernet test.
302798533Sfenner			 */
3028127667Sbms			b1 = gen_ether_linktype(proto);
3029127667Sbms			gen_and(b0, b1);
3030127667Sbms			return b1;
3031127667Sbms		} else {
303298533Sfenner			/*
3033127667Sbms			 * Check for LLC encapsulation and then check the
3034127667Sbms			 * protocol.
303598533Sfenner			 */
3036127667Sbms			b0 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
3037147897Ssam			b1 = gen_llc_linktype(proto);
3038127667Sbms			gen_and(b0, b1);
3039127667Sbms			return b1;
304098533Sfenner		}
3041147897Ssam		/*NOTREACHED*/
3042147897Ssam		break;
304398533Sfenner
304498533Sfenner	case DLT_LINUX_SLL:
3045146771Ssam		return gen_linux_sll_linktype(proto);
3046146771Ssam		/*NOTREACHED*/
304798533Sfenner		break;
304898533Sfenner
304917683Spst	case DLT_SLIP:
305098533Sfenner	case DLT_SLIP_BSDOS:
305198533Sfenner	case DLT_RAW:
305298533Sfenner		/*
305398533Sfenner		 * These types don't provide any type field; packets
3054172680Smlaier		 * are always IPv4 or IPv6.
305598533Sfenner		 *
305698533Sfenner		 * XXX - for IPv4, check for a version number of 4, and,
305798533Sfenner		 * for IPv6, check for a version number of 6?
305898533Sfenner		 */
305998533Sfenner		switch (proto) {
306017683Spst
306198533Sfenner		case ETHERTYPE_IP:
3062172680Smlaier			/* Check for a version number of 4. */
3063172680Smlaier			return gen_mcmp(OR_LINK, 0, BPF_B, 0x40, 0xF0);
3064252281Sdelphij
306598533Sfenner		case ETHERTYPE_IPV6:
3066172680Smlaier			/* Check for a version number of 6. */
3067172680Smlaier			return gen_mcmp(OR_LINK, 0, BPF_B, 0x60, 0xF0);
306898533Sfenner
306998533Sfenner		default:
307098533Sfenner			return gen_false();		/* always false */
307198533Sfenner		}
3072146771Ssam		/*NOTREACHED*/
307398533Sfenner		break;
307498533Sfenner
3075214518Srpaulo	case DLT_IPV4:
3076214518Srpaulo		/*
3077214518Srpaulo		 * Raw IPv4, so no type field.
3078214518Srpaulo		 */
3079214518Srpaulo		if (proto == ETHERTYPE_IP)
3080214518Srpaulo			return gen_true();		/* always true */
3081214518Srpaulo
3082214518Srpaulo		/* Checking for something other than IPv4; always false */
3083214518Srpaulo		return gen_false();
3084214518Srpaulo		/*NOTREACHED*/
3085214518Srpaulo		break;
3086214518Srpaulo
3087214518Srpaulo	case DLT_IPV6:
3088214518Srpaulo		/*
3089214518Srpaulo		 * Raw IPv6, so no type field.
3090214518Srpaulo		 */
3091214518Srpaulo		if (proto == ETHERTYPE_IPV6)
3092214518Srpaulo			return gen_true();		/* always true */
3093214518Srpaulo
3094214518Srpaulo		/* Checking for something other than IPv6; always false */
3095214518Srpaulo		return gen_false();
3096214518Srpaulo		/*NOTREACHED*/
3097214518Srpaulo		break;
3098214518Srpaulo
309917683Spst	case DLT_PPP:
3100146771Ssam	case DLT_PPP_PPPD:
310175110Sfenner	case DLT_PPP_SERIAL:
310298533Sfenner	case DLT_PPP_ETHER:
310375110Sfenner		/*
310475110Sfenner		 * We use Ethernet protocol types inside libpcap;
310575110Sfenner		 * map them to the corresponding PPP protocol types.
310675110Sfenner		 */
3107190225Srpaulo		proto = ethertype_to_ppptype(proto);
3108190225Srpaulo		return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
3109190225Srpaulo		/*NOTREACHED*/
311017683Spst		break;
311117683Spst
311239294Sfenner	case DLT_PPP_BSDOS:
311375110Sfenner		/*
311475110Sfenner		 * We use Ethernet protocol types inside libpcap;
311575110Sfenner		 * map them to the corresponding PPP protocol types.
311675110Sfenner		 */
311739294Sfenner		switch (proto) {
311839294Sfenner
311939294Sfenner		case ETHERTYPE_IP:
3120190225Srpaulo			/*
3121190225Srpaulo			 * Also check for Van Jacobson-compressed IP.
3122190225Srpaulo			 * XXX - do this for other forms of PPP?
3123190225Srpaulo			 */
3124147897Ssam			b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_IP);
3125147897Ssam			b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJC);
312639294Sfenner			gen_or(b0, b1);
3127147897Ssam			b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJNC);
312839294Sfenner			gen_or(b1, b0);
312939294Sfenner			return b0;
313039294Sfenner
3131190225Srpaulo		default:
3132190225Srpaulo			proto = ethertype_to_ppptype(proto);
3133190225Srpaulo			return gen_cmp(OR_LINK, off_linktype, BPF_H,
3134190225Srpaulo				(bpf_int32)proto);
313539294Sfenner		}
3136190225Srpaulo		/*NOTREACHED*/
313739294Sfenner		break;
313839294Sfenner
313917683Spst	case DLT_NULL:
314075110Sfenner	case DLT_LOOP:
3141127667Sbms	case DLT_ENC:
314275110Sfenner		/*
314375110Sfenner		 * For DLT_NULL, the link-layer header is a 32-bit
3144127667Sbms		 * word containing an AF_ value in *host* byte order,
3145127667Sbms		 * and for DLT_ENC, the link-layer header begins
3146127667Sbms		 * with a 32-bit work containing an AF_ value in
3147127667Sbms		 * host byte order.
314875110Sfenner		 *
314975110Sfenner		 * In addition, if we're reading a saved capture file,
315075110Sfenner		 * the host byte order in the capture may not be the
315175110Sfenner		 * same as the host byte order on this machine.
315275110Sfenner		 *
315375110Sfenner		 * For DLT_LOOP, the link-layer header is a 32-bit
315475110Sfenner		 * word containing an AF_ value in *network* byte order.
315575110Sfenner		 *
315675110Sfenner		 * XXX - AF_ values may, unfortunately, be platform-
315775110Sfenner		 * dependent; for example, FreeBSD's AF_INET6 is 24
315875110Sfenner		 * whilst NetBSD's and OpenBSD's is 26.
315975110Sfenner		 *
316075110Sfenner		 * This means that, when reading a capture file, just
316175110Sfenner		 * checking for our AF_INET6 value won't work if the
316275110Sfenner		 * capture file came from another OS.
316375110Sfenner		 */
316475110Sfenner		switch (proto) {
316575110Sfenner
316675110Sfenner		case ETHERTYPE_IP:
316775110Sfenner			proto = AF_INET;
316875110Sfenner			break;
316975110Sfenner
317056891Sfenner#ifdef INET6
317175110Sfenner		case ETHERTYPE_IPV6:
317275110Sfenner			proto = AF_INET6;
317375110Sfenner			break;
317456891Sfenner#endif
317575110Sfenner
317675110Sfenner		default:
317775110Sfenner			/*
317875110Sfenner			 * Not a type on which we support filtering.
317975110Sfenner			 * XXX - support those that have AF_ values
318075110Sfenner			 * #defined on this platform, at least?
318175110Sfenner			 */
318217683Spst			return gen_false();
318375110Sfenner		}
318417749Spst
3185127667Sbms		if (linktype == DLT_NULL || linktype == DLT_ENC) {
318675110Sfenner			/*
318775110Sfenner			 * The AF_ value is in host byte order, but
318875110Sfenner			 * the BPF interpreter will convert it to
318975110Sfenner			 * network byte order.
319075110Sfenner			 *
319175110Sfenner			 * If this is a save file, and it's from a
319275110Sfenner			 * machine with the opposite byte order to
319375110Sfenner			 * ours, we byte-swap the AF_ value.
319475110Sfenner			 *
319575110Sfenner			 * Then we run it through "htonl()", and
319675110Sfenner			 * generate code to compare against the result.
319775110Sfenner			 */
319875110Sfenner			if (bpf_pcap->sf.rfile != NULL &&
319975110Sfenner			    bpf_pcap->sf.swapped)
320075110Sfenner				proto = SWAPLONG(proto);
320175110Sfenner			proto = htonl(proto);
320217749Spst		}
3203147897Ssam		return (gen_cmp(OR_LINK, 0, BPF_W, (bpf_int32)proto));
320498533Sfenner
3205172680Smlaier#ifdef HAVE_NET_PFVAR_H
3206127667Sbms	case DLT_PFLOG:
3207127667Sbms		/*
3208127667Sbms		 * af field is host byte order in contrast to the rest of
3209127667Sbms		 * the packet.
3210127667Sbms		 */
3211127667Sbms		if (proto == ETHERTYPE_IP)
3212147897Ssam			return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
3213147897Ssam			    BPF_B, (bpf_int32)AF_INET));
3214127667Sbms		else if (proto == ETHERTYPE_IPV6)
3215147897Ssam			return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af),
3216147897Ssam			    BPF_B, (bpf_int32)AF_INET6));
3217127667Sbms		else
3218127667Sbms			return gen_false();
3219146771Ssam		/*NOTREACHED*/
3220127667Sbms		break;
3221172680Smlaier#endif /* HAVE_NET_PFVAR_H */
3222127667Sbms
322398533Sfenner	case DLT_ARCNET:
3224127667Sbms	case DLT_ARCNET_LINUX:
322598533Sfenner		/*
322698533Sfenner		 * XXX should we check for first fragment if the protocol
322798533Sfenner		 * uses PHDS?
322898533Sfenner		 */
3229127667Sbms		switch (proto) {
3230127667Sbms
323198533Sfenner		default:
323298533Sfenner			return gen_false();
3233127667Sbms
323498533Sfenner		case ETHERTYPE_IPV6:
3235147897Ssam			return (gen_cmp(OR_LINK, off_linktype, BPF_B,
3236127667Sbms				(bpf_int32)ARCTYPE_INET6));
3237127667Sbms
323898533Sfenner		case ETHERTYPE_IP:
3239147897Ssam			b0 = gen_cmp(OR_LINK, off_linktype, BPF_B,
3240127667Sbms				     (bpf_int32)ARCTYPE_IP);
3241147897Ssam			b1 = gen_cmp(OR_LINK, off_linktype, BPF_B,
3242127667Sbms				     (bpf_int32)ARCTYPE_IP_OLD);
324398533Sfenner			gen_or(b0, b1);
3244127667Sbms			return (b1);
3245127667Sbms
324698533Sfenner		case ETHERTYPE_ARP:
3247147897Ssam			b0 = gen_cmp(OR_LINK, off_linktype, BPF_B,
3248127667Sbms				     (bpf_int32)ARCTYPE_ARP);
3249147897Ssam			b1 = gen_cmp(OR_LINK, off_linktype, BPF_B,
3250127667Sbms				     (bpf_int32)ARCTYPE_ARP_OLD);
325198533Sfenner			gen_or(b0, b1);
3252127667Sbms			return (b1);
3253127667Sbms
325498533Sfenner		case ETHERTYPE_REVARP:
3255147897Ssam			return (gen_cmp(OR_LINK, off_linktype, BPF_B,
3256127667Sbms					(bpf_int32)ARCTYPE_REVARP));
3257127667Sbms
325898533Sfenner		case ETHERTYPE_ATALK:
3259147897Ssam			return (gen_cmp(OR_LINK, off_linktype, BPF_B,
3260127667Sbms					(bpf_int32)ARCTYPE_ATALK));
326198533Sfenner		}
3262146771Ssam		/*NOTREACHED*/
326398533Sfenner		break;
326498533Sfenner
326598533Sfenner	case DLT_LTALK:
326698533Sfenner		switch (proto) {
326798533Sfenner		case ETHERTYPE_ATALK:
326898533Sfenner			return gen_true();
326998533Sfenner		default:
327098533Sfenner			return gen_false();
327198533Sfenner		}
3272146771Ssam		/*NOTREACHED*/
327398533Sfenner		break;
3274127667Sbms
3275127667Sbms	case DLT_FRELAY:
3276127667Sbms		/*
3277127667Sbms		 * XXX - assumes a 2-byte Frame Relay header with
3278127667Sbms		 * DLCI and flags.  What if the address is longer?
3279127667Sbms		 */
3280127667Sbms		switch (proto) {
3281127667Sbms
3282127667Sbms		case ETHERTYPE_IP:
3283127667Sbms			/*
3284127667Sbms			 * Check for the special NLPID for IP.
3285127667Sbms			 */
3286147897Ssam			return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0xcc);
3287127667Sbms
3288127667Sbms		case ETHERTYPE_IPV6:
3289127667Sbms			/*
3290127667Sbms			 * Check for the special NLPID for IPv6.
3291127667Sbms			 */
3292147897Ssam			return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | 0x8e);
3293127667Sbms
3294127667Sbms		case LLCSAP_ISONS:
3295127667Sbms			/*
3296127667Sbms			 * Check for several OSI protocols.
3297127667Sbms			 *
3298127667Sbms			 * Frame Relay packets typically have an OSI
3299127667Sbms			 * NLPID at the beginning; we check for each
3300127667Sbms			 * of them.
3301127667Sbms			 *
3302127667Sbms			 * What we check for is the NLPID and a frame
3303127667Sbms			 * control field of UI, i.e. 0x03 followed
3304127667Sbms			 * by the NLPID.
3305127667Sbms			 */
3306147897Ssam			b0 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO8473_CLNP);
3307147897Ssam			b1 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO9542_ESIS);
3308147897Ssam			b2 = gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | ISO10589_ISIS);
3309127667Sbms			gen_or(b1, b2);
3310127667Sbms			gen_or(b0, b2);
3311127667Sbms			return b2;
3312127667Sbms
3313127667Sbms		default:
3314127667Sbms			return gen_false();
3315127667Sbms		}
3316146771Ssam		/*NOTREACHED*/
3317127667Sbms		break;
3318127667Sbms
3319190225Srpaulo	case DLT_MFR:
3320190225Srpaulo		bpf_error("Multi-link Frame Relay link-layer type filtering not implemented");
3321190225Srpaulo
3322162015Ssam        case DLT_JUNIPER_MFR:
3323146771Ssam        case DLT_JUNIPER_MLFR:
3324146771Ssam        case DLT_JUNIPER_MLPPP:
3325146771Ssam	case DLT_JUNIPER_ATM1:
3326146771Ssam	case DLT_JUNIPER_ATM2:
3327147897Ssam	case DLT_JUNIPER_PPPOE:
3328147897Ssam	case DLT_JUNIPER_PPPOE_ATM:
3329147897Ssam        case DLT_JUNIPER_GGSN:
3330147897Ssam        case DLT_JUNIPER_ES:
3331147897Ssam        case DLT_JUNIPER_MONITOR:
3332147897Ssam        case DLT_JUNIPER_SERVICES:
3333162015Ssam        case DLT_JUNIPER_ETHER:
3334162015Ssam        case DLT_JUNIPER_PPP:
3335162015Ssam        case DLT_JUNIPER_FRELAY:
3336162015Ssam        case DLT_JUNIPER_CHDLC:
3337172680Smlaier        case DLT_JUNIPER_VP:
3338190225Srpaulo        case DLT_JUNIPER_ST:
3339190225Srpaulo        case DLT_JUNIPER_ISM:
3340236167Sdelphij        case DLT_JUNIPER_VS:
3341236167Sdelphij        case DLT_JUNIPER_SRX_E2E:
3342236167Sdelphij        case DLT_JUNIPER_FIBRECHANNEL:
3343236167Sdelphij	case DLT_JUNIPER_ATM_CEMIC:
3344236167Sdelphij
3345146771Ssam		/* just lets verify the magic number for now -
3346146771Ssam		 * on ATM we may have up to 6 different encapsulations on the wire
3347146771Ssam		 * and need a lot of heuristics to figure out that the payload
3348146771Ssam		 * might be;
3349146771Ssam		 *
3350146771Ssam		 * FIXME encapsulation specific BPF_ filters
3351146771Ssam		 */
3352147897Ssam		return gen_mcmp(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
3353146771Ssam
3354214518Srpaulo	case DLT_IPNET:
3355214518Srpaulo		return gen_ipnet_linktype(proto);
3356214518Srpaulo
3357127667Sbms	case DLT_LINUX_IRDA:
3358146771Ssam		bpf_error("IrDA link-layer type filtering not implemented");
3359146771Ssam
3360146771Ssam	case DLT_DOCSIS:
3361146771Ssam		bpf_error("DOCSIS link-layer type filtering not implemented");
3362147897Ssam
3363190225Srpaulo	case DLT_MTP2:
3364190225Srpaulo	case DLT_MTP2_WITH_PHDR:
3365190225Srpaulo		bpf_error("MTP2 link-layer type filtering not implemented");
3366190225Srpaulo
3367190225Srpaulo	case DLT_ERF:
3368190225Srpaulo		bpf_error("ERF link-layer type filtering not implemented");
3369190225Srpaulo
3370190225Srpaulo	case DLT_PFSYNC:
3371190225Srpaulo		bpf_error("PFSYNC link-layer type filtering not implemented");
3372190225Srpaulo
3373147897Ssam	case DLT_LINUX_LAPD:
3374147897Ssam		bpf_error("LAPD link-layer type filtering not implemented");
3375190225Srpaulo
3376190225Srpaulo	case DLT_USB:
3377190225Srpaulo	case DLT_USB_LINUX:
3378214518Srpaulo	case DLT_USB_LINUX_MMAPPED:
3379190225Srpaulo		bpf_error("USB link-layer type filtering not implemented");
3380190225Srpaulo
3381190225Srpaulo	case DLT_BLUETOOTH_HCI_H4:
3382190225Srpaulo	case DLT_BLUETOOTH_HCI_H4_WITH_PHDR:
3383190225Srpaulo		bpf_error("Bluetooth link-layer type filtering not implemented");
3384190225Srpaulo
3385190225Srpaulo	case DLT_CAN20B:
3386214518Srpaulo	case DLT_CAN_SOCKETCAN:
3387214518Srpaulo		bpf_error("CAN link-layer type filtering not implemented");
3388190225Srpaulo
3389190225Srpaulo	case DLT_IEEE802_15_4:
3390190225Srpaulo	case DLT_IEEE802_15_4_LINUX:
3391190225Srpaulo	case DLT_IEEE802_15_4_NONASK_PHY:
3392236167Sdelphij	case DLT_IEEE802_15_4_NOFCS:
3393190225Srpaulo		bpf_error("IEEE 802.15.4 link-layer type filtering not implemented");
3394190225Srpaulo
3395190225Srpaulo	case DLT_IEEE802_16_MAC_CPS_RADIO:
3396190225Srpaulo		bpf_error("IEEE 802.16 link-layer type filtering not implemented");
3397190225Srpaulo
3398190225Srpaulo	case DLT_SITA:
3399190225Srpaulo		bpf_error("SITA link-layer type filtering not implemented");
3400190225Srpaulo
3401190225Srpaulo	case DLT_RAIF1:
3402190225Srpaulo		bpf_error("RAIF1 link-layer type filtering not implemented");
3403190225Srpaulo
3404190225Srpaulo	case DLT_IPMB:
3405190225Srpaulo		bpf_error("IPMB link-layer type filtering not implemented");
3406190225Srpaulo
3407190225Srpaulo	case DLT_AX25_KISS:
3408190225Srpaulo		bpf_error("AX.25 link-layer type filtering not implemented");
340917683Spst	}
341098533Sfenner
341198533Sfenner	/*
341298533Sfenner	 * All the types that have no encapsulation should either be
341398533Sfenner	 * handled as DLT_SLIP, DLT_SLIP_BSDOS, and DLT_RAW are, if
341498533Sfenner	 * all packets are IP packets, or should be handled in some
341598533Sfenner	 * special case, if none of them are (if some are and some
341698533Sfenner	 * aren't, the lack of encapsulation is a problem, as we'd
341798533Sfenner	 * have to find some other way of determining the packet type).
341898533Sfenner	 *
341998533Sfenner	 * Therefore, if "off_linktype" is -1, there's an error.
342098533Sfenner	 */
3421127667Sbms	if (off_linktype == (u_int)-1)
342298533Sfenner		abort();
342398533Sfenner
342498533Sfenner	/*
342598533Sfenner	 * Any type not handled above should always have an Ethernet
3426190225Srpaulo	 * type at an offset of "off_linktype".
342798533Sfenner	 */
3428147897Ssam	return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32)proto);
342917683Spst}
343017683Spst
343175110Sfenner/*
343275110Sfenner * Check for an LLC SNAP packet with a given organization code and
343375110Sfenner * protocol type; we check the entire contents of the 802.2 LLC and
343475110Sfenner * snap headers, checking for DSAP and SSAP of SNAP and a control
343575110Sfenner * field of 0x03 in the LLC header, and for the specified organization
343675110Sfenner * code and protocol type in the SNAP header.
343775110Sfenner */
343817683Spststatic struct block *
3439190225Srpaulogen_snap(orgcode, ptype)
344075110Sfenner	bpf_u_int32 orgcode;
344175110Sfenner	bpf_u_int32 ptype;
344275110Sfenner{
344375110Sfenner	u_char snapblock[8];
344475110Sfenner
344598533Sfenner	snapblock[0] = LLCSAP_SNAP;	/* DSAP = SNAP */
344698533Sfenner	snapblock[1] = LLCSAP_SNAP;	/* SSAP = SNAP */
3447127667Sbms	snapblock[2] = 0x03;		/* control = UI */
344875110Sfenner	snapblock[3] = (orgcode >> 16);	/* upper 8 bits of organization code */
344975110Sfenner	snapblock[4] = (orgcode >> 8);	/* middle 8 bits of organization code */
345075110Sfenner	snapblock[5] = (orgcode >> 0);	/* lower 8 bits of organization code */
345175110Sfenner	snapblock[6] = (ptype >> 8);	/* upper 8 bits of protocol type */
345275110Sfenner	snapblock[7] = (ptype >> 0);	/* lower 8 bits of protocol type */
3453190225Srpaulo	return gen_bcmp(OR_MACPL, 0, 8, snapblock);
345475110Sfenner}
345575110Sfenner
3456127667Sbms/*
3457147897Ssam * Generate code to match a particular packet type, for link-layer types
3458147897Ssam * using 802.2 LLC headers.
3459147897Ssam *
3460147897Ssam * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used
3461147897Ssam * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues.
3462147897Ssam *
3463147897Ssam * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
3464147897Ssam * value, if <= ETHERMTU.  We use that to determine whether to
3465147897Ssam * match the DSAP or both DSAP and LSAP or to check the OUI and
3466147897Ssam * protocol ID in a SNAP header.
3467127667Sbms */
346875110Sfennerstatic struct block *
3469147897Ssamgen_llc_linktype(proto)
3470127667Sbms	int proto;
3471127667Sbms{
3472127667Sbms	/*
3473127667Sbms	 * XXX - handle token-ring variable-length header.
3474127667Sbms	 */
3475127667Sbms	switch (proto) {
3476127667Sbms
3477127667Sbms	case LLCSAP_IP:
3478127667Sbms	case LLCSAP_ISONS:
3479127667Sbms	case LLCSAP_NETBEUI:
3480147897Ssam		/*
3481147897Ssam		 * XXX - should we check both the DSAP and the
3482147897Ssam		 * SSAP, like this, or should we check just the
3483147897Ssam		 * DSAP, as we do for other types <= ETHERMTU
3484147897Ssam		 * (i.e., other SAP values)?
3485147897Ssam		 */
3486190225Srpaulo		return gen_cmp(OR_MACPL, 0, BPF_H, (bpf_u_int32)
3487147897Ssam			     ((proto << 8) | proto));
3488127667Sbms
3489127667Sbms	case LLCSAP_IPX:
3490127667Sbms		/*
3491127667Sbms		 * XXX - are there ever SNAP frames for IPX on
3492127667Sbms		 * non-Ethernet 802.x networks?
3493127667Sbms		 */
3494190225Srpaulo		return gen_cmp(OR_MACPL, 0, BPF_B,
3495147897Ssam		    (bpf_int32)LLCSAP_IPX);
3496127667Sbms
3497127667Sbms	case ETHERTYPE_ATALK:
3498127667Sbms		/*
3499127667Sbms		 * 802.2-encapsulated ETHERTYPE_ATALK packets are
3500127667Sbms		 * SNAP packets with an organization code of
3501127667Sbms		 * 0x080007 (Apple, for Appletalk) and a protocol
3502127667Sbms		 * type of ETHERTYPE_ATALK (Appletalk).
3503127667Sbms		 *
3504127667Sbms		 * XXX - check for an organization code of
3505127667Sbms		 * encapsulated Ethernet as well?
3506127667Sbms		 */
3507190225Srpaulo		return gen_snap(0x080007, ETHERTYPE_ATALK);
3508127667Sbms
3509127667Sbms	default:
3510127667Sbms		/*
3511127667Sbms		 * XXX - we don't have to check for IPX 802.3
3512127667Sbms		 * here, but should we check for the IPX Ethertype?
3513127667Sbms		 */
3514127667Sbms		if (proto <= ETHERMTU) {
3515127667Sbms			/*
3516127667Sbms			 * This is an LLC SAP value, so check
3517127667Sbms			 * the DSAP.
3518127667Sbms			 */
3519190225Srpaulo			return gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32)proto);
3520127667Sbms		} else {
3521127667Sbms			/*
3522127667Sbms			 * This is an Ethernet type; we assume that it's
3523127667Sbms			 * unlikely that it'll appear in the right place
3524127667Sbms			 * at random, and therefore check only the
3525127667Sbms			 * location that would hold the Ethernet type
3526127667Sbms			 * in a SNAP frame with an organization code of
3527127667Sbms			 * 0x000000 (encapsulated Ethernet).
3528127667Sbms			 *
3529127667Sbms			 * XXX - if we were to check for the SNAP DSAP and
3530127667Sbms			 * LSAP, as per XXX, and were also to check for an
3531127667Sbms			 * organization code of 0x000000 (encapsulated
3532127667Sbms			 * Ethernet), we'd do
3533127667Sbms			 *
3534190225Srpaulo			 *	return gen_snap(0x000000, proto);
3535127667Sbms			 *
3536127667Sbms			 * here; for now, we don't, as per the above.
3537127667Sbms			 * I don't know whether it's worth the extra CPU
3538127667Sbms			 * time to do the right check or not.
3539127667Sbms			 */
3540190225Srpaulo			return gen_cmp(OR_MACPL, 6, BPF_H, (bpf_int32)proto);
3541127667Sbms		}
3542127667Sbms	}
3543127667Sbms}
3544127667Sbms
3545127667Sbmsstatic struct block *
354617683Spstgen_hostop(addr, mask, dir, proto, src_off, dst_off)
354717683Spst	bpf_u_int32 addr;
354817683Spst	bpf_u_int32 mask;
354917683Spst	int dir, proto;
355017683Spst	u_int src_off, dst_off;
355117683Spst{
355217683Spst	struct block *b0, *b1;
355317683Spst	u_int offset;
355417683Spst
355517683Spst	switch (dir) {
355617683Spst
355717683Spst	case Q_SRC:
355817683Spst		offset = src_off;
355917683Spst		break;
356017683Spst
356117683Spst	case Q_DST:
356217683Spst		offset = dst_off;
356317683Spst		break;
356417683Spst
356517683Spst	case Q_AND:
356617683Spst		b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
356717683Spst		b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
356817683Spst		gen_and(b0, b1);
356917683Spst		return b1;
357017683Spst
357117683Spst	case Q_OR:
357217683Spst	case Q_DEFAULT:
357317683Spst		b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
357417683Spst		b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
357517683Spst		gen_or(b0, b1);
357617683Spst		return b1;
357717683Spst
357817683Spst	default:
357917683Spst		abort();
358017683Spst	}
358117683Spst	b0 = gen_linktype(proto);
3582147897Ssam	b1 = gen_mcmp(OR_NET, offset, BPF_W, (bpf_int32)addr, mask);
358317683Spst	gen_and(b0, b1);
358417683Spst	return b1;
358517683Spst}
358617683Spst
358756891Sfenner#ifdef INET6
358817683Spststatic struct block *
358956891Sfennergen_hostop6(addr, mask, dir, proto, src_off, dst_off)
359056891Sfenner	struct in6_addr *addr;
359156891Sfenner	struct in6_addr *mask;
359256891Sfenner	int dir, proto;
359356891Sfenner	u_int src_off, dst_off;
359456891Sfenner{
359556891Sfenner	struct block *b0, *b1;
359656891Sfenner	u_int offset;
359756891Sfenner	u_int32_t *a, *m;
359856891Sfenner
359956891Sfenner	switch (dir) {
360056891Sfenner
360156891Sfenner	case Q_SRC:
360256891Sfenner		offset = src_off;
360356891Sfenner		break;
360456891Sfenner
360556891Sfenner	case Q_DST:
360656891Sfenner		offset = dst_off;
360756891Sfenner		break;
360856891Sfenner
360956891Sfenner	case Q_AND:
361056891Sfenner		b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
361156891Sfenner		b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
361256891Sfenner		gen_and(b0, b1);
361356891Sfenner		return b1;
361456891Sfenner
361556891Sfenner	case Q_OR:
361656891Sfenner	case Q_DEFAULT:
361756891Sfenner		b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
361856891Sfenner		b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
361956891Sfenner		gen_or(b0, b1);
362056891Sfenner		return b1;
362156891Sfenner
362256891Sfenner	default:
362356891Sfenner		abort();
362456891Sfenner	}
362556891Sfenner	/* this order is important */
362656891Sfenner	a = (u_int32_t *)addr;
362756891Sfenner	m = (u_int32_t *)mask;
3628147897Ssam	b1 = gen_mcmp(OR_NET, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
3629147897Ssam	b0 = gen_mcmp(OR_NET, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
363056891Sfenner	gen_and(b0, b1);
3631147897Ssam	b0 = gen_mcmp(OR_NET, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
363256891Sfenner	gen_and(b0, b1);
3633147897Ssam	b0 = gen_mcmp(OR_NET, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
363456891Sfenner	gen_and(b0, b1);
363556891Sfenner	b0 = gen_linktype(proto);
363656891Sfenner	gen_and(b0, b1);
363756891Sfenner	return b1;
363856891Sfenner}
3639252281Sdelphij#endif
364056891Sfenner
364156891Sfennerstatic struct block *
364217683Spstgen_ehostop(eaddr, dir)
364317683Spst	register const u_char *eaddr;
364417683Spst	register int dir;
364517683Spst{
364617683Spst	register struct block *b0, *b1;
364717683Spst
364817683Spst	switch (dir) {
364917683Spst	case Q_SRC:
3650147897Ssam		return gen_bcmp(OR_LINK, off_mac + 6, 6, eaddr);
365117683Spst
365217683Spst	case Q_DST:
3653147897Ssam		return gen_bcmp(OR_LINK, off_mac + 0, 6, eaddr);
365417683Spst
365517683Spst	case Q_AND:
365617683Spst		b0 = gen_ehostop(eaddr, Q_SRC);
365717683Spst		b1 = gen_ehostop(eaddr, Q_DST);
365817683Spst		gen_and(b0, b1);
365917683Spst		return b1;
366017683Spst
366117683Spst	case Q_DEFAULT:
366217683Spst	case Q_OR:
366317683Spst		b0 = gen_ehostop(eaddr, Q_SRC);
366417683Spst		b1 = gen_ehostop(eaddr, Q_DST);
366517683Spst		gen_or(b0, b1);
366617683Spst		return b1;
3667236167Sdelphij
3668236167Sdelphij	case Q_ADDR1:
3669236167Sdelphij		bpf_error("'addr1' is only supported on 802.11 with 802.11 headers");
3670236167Sdelphij		break;
3671236167Sdelphij
3672236167Sdelphij	case Q_ADDR2:
3673236167Sdelphij		bpf_error("'addr2' is only supported on 802.11 with 802.11 headers");
3674236167Sdelphij		break;
3675236167Sdelphij
3676236167Sdelphij	case Q_ADDR3:
3677236167Sdelphij		bpf_error("'addr3' is only supported on 802.11 with 802.11 headers");
3678236167Sdelphij		break;
3679236167Sdelphij
3680236167Sdelphij	case Q_ADDR4:
3681236167Sdelphij		bpf_error("'addr4' is only supported on 802.11 with 802.11 headers");
3682236167Sdelphij		break;
3683236167Sdelphij
3684236167Sdelphij	case Q_RA:
3685236167Sdelphij		bpf_error("'ra' is only supported on 802.11 with 802.11 headers");
3686236167Sdelphij		break;
3687236167Sdelphij
3688236167Sdelphij	case Q_TA:
3689236167Sdelphij		bpf_error("'ta' is only supported on 802.11 with 802.11 headers");
3690236167Sdelphij		break;
369117683Spst	}
369217683Spst	abort();
369317683Spst	/* NOTREACHED */
369417683Spst}
369517683Spst
369617683Spst/*
369717683Spst * Like gen_ehostop, but for DLT_FDDI
369817683Spst */
369917683Spststatic struct block *
370017683Spstgen_fhostop(eaddr, dir)
370117683Spst	register const u_char *eaddr;
370217683Spst	register int dir;
370317683Spst{
370417683Spst	struct block *b0, *b1;
370517683Spst
370617683Spst	switch (dir) {
370717683Spst	case Q_SRC:
370817683Spst#ifdef PCAP_FDDIPAD
3709147897Ssam		return gen_bcmp(OR_LINK, 6 + 1 + pcap_fddipad, 6, eaddr);
371017683Spst#else
3711147897Ssam		return gen_bcmp(OR_LINK, 6 + 1, 6, eaddr);
371217683Spst#endif
371317683Spst
371417683Spst	case Q_DST:
371517683Spst#ifdef PCAP_FDDIPAD
3716147897Ssam		return gen_bcmp(OR_LINK, 0 + 1 + pcap_fddipad, 6, eaddr);
371717683Spst#else
3718147897Ssam		return gen_bcmp(OR_LINK, 0 + 1, 6, eaddr);
371917683Spst#endif
372017683Spst
372117683Spst	case Q_AND:
372217683Spst		b0 = gen_fhostop(eaddr, Q_SRC);
372317683Spst		b1 = gen_fhostop(eaddr, Q_DST);
372417683Spst		gen_and(b0, b1);
372517683Spst		return b1;
372617683Spst
372717683Spst	case Q_DEFAULT:
372817683Spst	case Q_OR:
372917683Spst		b0 = gen_fhostop(eaddr, Q_SRC);
373017683Spst		b1 = gen_fhostop(eaddr, Q_DST);
373117683Spst		gen_or(b0, b1);
373217683Spst		return b1;
3733236167Sdelphij
3734236167Sdelphij	case Q_ADDR1:
3735236167Sdelphij		bpf_error("'addr1' is only supported on 802.11");
3736236167Sdelphij		break;
3737236167Sdelphij
3738236167Sdelphij	case Q_ADDR2:
3739236167Sdelphij		bpf_error("'addr2' is only supported on 802.11");
3740236167Sdelphij		break;
3741236167Sdelphij
3742236167Sdelphij	case Q_ADDR3:
3743236167Sdelphij		bpf_error("'addr3' is only supported on 802.11");
3744236167Sdelphij		break;
3745236167Sdelphij
3746236167Sdelphij	case Q_ADDR4:
3747236167Sdelphij		bpf_error("'addr4' is only supported on 802.11");
3748236167Sdelphij		break;
3749236167Sdelphij
3750236167Sdelphij	case Q_RA:
3751236167Sdelphij		bpf_error("'ra' is only supported on 802.11");
3752236167Sdelphij		break;
3753236167Sdelphij
3754236167Sdelphij	case Q_TA:
3755236167Sdelphij		bpf_error("'ta' is only supported on 802.11");
3756236167Sdelphij		break;
375717683Spst	}
375817683Spst	abort();
375917683Spst	/* NOTREACHED */
376017683Spst}
376117683Spst
376217683Spst/*
376375110Sfenner * Like gen_ehostop, but for DLT_IEEE802 (Token Ring)
376475110Sfenner */
376575110Sfennerstatic struct block *
376675110Sfennergen_thostop(eaddr, dir)
376775110Sfenner	register const u_char *eaddr;
376875110Sfenner	register int dir;
376975110Sfenner{
377075110Sfenner	register struct block *b0, *b1;
377175110Sfenner
377275110Sfenner	switch (dir) {
377375110Sfenner	case Q_SRC:
3774147897Ssam		return gen_bcmp(OR_LINK, 8, 6, eaddr);
377575110Sfenner
377675110Sfenner	case Q_DST:
3777147897Ssam		return gen_bcmp(OR_LINK, 2, 6, eaddr);
377875110Sfenner
377975110Sfenner	case Q_AND:
378075110Sfenner		b0 = gen_thostop(eaddr, Q_SRC);
378175110Sfenner		b1 = gen_thostop(eaddr, Q_DST);
378275110Sfenner		gen_and(b0, b1);
378375110Sfenner		return b1;
378475110Sfenner
378575110Sfenner	case Q_DEFAULT:
378675110Sfenner	case Q_OR:
378775110Sfenner		b0 = gen_thostop(eaddr, Q_SRC);
378875110Sfenner		b1 = gen_thostop(eaddr, Q_DST);
378975110Sfenner		gen_or(b0, b1);
379075110Sfenner		return b1;
3791236167Sdelphij
3792236167Sdelphij	case Q_ADDR1:
3793236167Sdelphij		bpf_error("'addr1' is only supported on 802.11");
3794236167Sdelphij		break;
3795236167Sdelphij
3796236167Sdelphij	case Q_ADDR2:
3797236167Sdelphij		bpf_error("'addr2' is only supported on 802.11");
3798236167Sdelphij		break;
3799236167Sdelphij
3800236167Sdelphij	case Q_ADDR3:
3801236167Sdelphij		bpf_error("'addr3' is only supported on 802.11");
3802236167Sdelphij		break;
3803236167Sdelphij
3804236167Sdelphij	case Q_ADDR4:
3805236167Sdelphij		bpf_error("'addr4' is only supported on 802.11");
3806236167Sdelphij		break;
3807236167Sdelphij
3808236167Sdelphij	case Q_RA:
3809236167Sdelphij		bpf_error("'ra' is only supported on 802.11");
3810236167Sdelphij		break;
3811236167Sdelphij
3812236167Sdelphij	case Q_TA:
3813236167Sdelphij		bpf_error("'ta' is only supported on 802.11");
3814236167Sdelphij		break;
381575110Sfenner	}
381675110Sfenner	abort();
381775110Sfenner	/* NOTREACHED */
381875110Sfenner}
381975110Sfenner
382075110Sfenner/*
3821190225Srpaulo * Like gen_ehostop, but for DLT_IEEE802_11 (802.11 wireless LAN) and
3822190225Srpaulo * various 802.11 + radio headers.
3823122029Sgreen */
3824122029Sgreenstatic struct block *
3825127667Sbmsgen_wlanhostop(eaddr, dir)
3826122029Sgreen	register const u_char *eaddr;
3827122029Sgreen	register int dir;
3828122029Sgreen{
3829127667Sbms	register struct block *b0, *b1, *b2;
3830127667Sbms	register struct slist *s;
3831127667Sbms
3832190225Srpaulo#ifdef ENABLE_WLAN_FILTERING_PATCH
3833190225Srpaulo	/*
3834190225Srpaulo	 * TODO GV 20070613
3835190225Srpaulo	 * We need to disable the optimizer because the optimizer is buggy
3836190225Srpaulo	 * and wipes out some LD instructions generated by the below
3837190225Srpaulo	 * code to validate the Frame Control bits
3838190225Srpaulo	 */
3839190225Srpaulo	no_optimize = 1;
3840190225Srpaulo#endif /* ENABLE_WLAN_FILTERING_PATCH */
3841190225Srpaulo
3842127667Sbms	switch (dir) {
3843127667Sbms	case Q_SRC:
3844127667Sbms		/*
3845127667Sbms		 * Oh, yuk.
3846127667Sbms		 *
3847127667Sbms		 *	For control frames, there is no SA.
3848127667Sbms		 *
3849127667Sbms		 *	For management frames, SA is at an
3850127667Sbms		 *	offset of 10 from the beginning of
3851127667Sbms		 *	the packet.
3852127667Sbms		 *
3853127667Sbms		 *	For data frames, SA is at an offset
3854127667Sbms		 *	of 10 from the beginning of the packet
3855127667Sbms		 *	if From DS is clear, at an offset of
3856127667Sbms		 *	16 from the beginning of the packet
3857127667Sbms		 *	if From DS is set and To DS is clear,
3858127667Sbms		 *	and an offset of 24 from the beginning
3859127667Sbms		 *	of the packet if From DS is set and To DS
3860127667Sbms		 *	is set.
3861127667Sbms		 */
3862127667Sbms
3863127667Sbms		/*
3864127667Sbms		 * Generate the tests to be done for data frames
3865127667Sbms		 * with From DS set.
3866127667Sbms		 *
3867127667Sbms		 * First, check for To DS set, i.e. check "link[1] & 0x01".
3868127667Sbms		 */
3869147897Ssam		s = gen_load_a(OR_LINK, 1, BPF_B);
3870127667Sbms		b1 = new_block(JMP(BPF_JSET));
3871127667Sbms		b1->s.k = 0x01;	/* To DS */
3872127667Sbms		b1->stmts = s;
3873127667Sbms
3874127667Sbms		/*
3875127667Sbms		 * If To DS is set, the SA is at 24.
3876127667Sbms		 */
3877147897Ssam		b0 = gen_bcmp(OR_LINK, 24, 6, eaddr);
3878127667Sbms		gen_and(b1, b0);
3879127667Sbms
3880127667Sbms		/*
3881127667Sbms		 * Now, check for To DS not set, i.e. check
3882127667Sbms		 * "!(link[1] & 0x01)".
3883127667Sbms		 */
3884147897Ssam		s = gen_load_a(OR_LINK, 1, BPF_B);
3885127667Sbms		b2 = new_block(JMP(BPF_JSET));
3886127667Sbms		b2->s.k = 0x01;	/* To DS */
3887127667Sbms		b2->stmts = s;
3888127667Sbms		gen_not(b2);
3889127667Sbms
3890127667Sbms		/*
3891127667Sbms		 * If To DS is not set, the SA is at 16.
3892127667Sbms		 */
3893147897Ssam		b1 = gen_bcmp(OR_LINK, 16, 6, eaddr);
3894127667Sbms		gen_and(b2, b1);
3895127667Sbms
3896127667Sbms		/*
3897127667Sbms		 * Now OR together the last two checks.  That gives
3898127667Sbms		 * the complete set of checks for data frames with
3899127667Sbms		 * From DS set.
3900127667Sbms		 */
3901127667Sbms		gen_or(b1, b0);
3902127667Sbms
3903127667Sbms		/*
3904127667Sbms		 * Now check for From DS being set, and AND that with
3905127667Sbms		 * the ORed-together checks.
3906127667Sbms		 */
3907147897Ssam		s = gen_load_a(OR_LINK, 1, BPF_B);
3908127667Sbms		b1 = new_block(JMP(BPF_JSET));
3909127667Sbms		b1->s.k = 0x02;	/* From DS */
3910127667Sbms		b1->stmts = s;
3911127667Sbms		gen_and(b1, b0);
3912127667Sbms
3913127667Sbms		/*
3914127667Sbms		 * Now check for data frames with From DS not set.
3915127667Sbms		 */
3916147897Ssam		s = gen_load_a(OR_LINK, 1, BPF_B);
3917127667Sbms		b2 = new_block(JMP(BPF_JSET));
3918127667Sbms		b2->s.k = 0x02;	/* From DS */
3919127667Sbms		b2->stmts = s;
3920127667Sbms		gen_not(b2);
3921127667Sbms
3922127667Sbms		/*
3923127667Sbms		 * If From DS isn't set, the SA is at 10.
3924127667Sbms		 */
3925147897Ssam		b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
3926127667Sbms		gen_and(b2, b1);
3927127667Sbms
3928127667Sbms		/*
3929127667Sbms		 * Now OR together the checks for data frames with
3930127667Sbms		 * From DS not set and for data frames with From DS
3931127667Sbms		 * set; that gives the checks done for data frames.
3932127667Sbms		 */
3933127667Sbms		gen_or(b1, b0);
3934127667Sbms
3935127667Sbms		/*
3936127667Sbms		 * Now check for a data frame.
3937127667Sbms		 * I.e, check "link[0] & 0x08".
3938127667Sbms		 */
3939190225Srpaulo		s = gen_load_a(OR_LINK, 0, BPF_B);
3940127667Sbms		b1 = new_block(JMP(BPF_JSET));
3941127667Sbms		b1->s.k = 0x08;
3942127667Sbms		b1->stmts = s;
3943127667Sbms
3944127667Sbms		/*
3945127667Sbms		 * AND that with the checks done for data frames.
3946127667Sbms		 */
3947127667Sbms		gen_and(b1, b0);
3948127667Sbms
3949127667Sbms		/*
3950127667Sbms		 * If the high-order bit of the type value is 0, this
3951127667Sbms		 * is a management frame.
3952127667Sbms		 * I.e, check "!(link[0] & 0x08)".
3953127667Sbms		 */
3954147897Ssam		s = gen_load_a(OR_LINK, 0, BPF_B);
3955127667Sbms		b2 = new_block(JMP(BPF_JSET));
3956127667Sbms		b2->s.k = 0x08;
3957127667Sbms		b2->stmts = s;
3958127667Sbms		gen_not(b2);
3959127667Sbms
3960127667Sbms		/*
3961127667Sbms		 * For management frames, the SA is at 10.
3962127667Sbms		 */
3963147897Ssam		b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
3964127667Sbms		gen_and(b2, b1);
3965127667Sbms
3966127667Sbms		/*
3967127667Sbms		 * OR that with the checks done for data frames.
3968127667Sbms		 * That gives the checks done for management and
3969127667Sbms		 * data frames.
3970127667Sbms		 */
3971127667Sbms		gen_or(b1, b0);
3972127667Sbms
3973127667Sbms		/*
3974127667Sbms		 * If the low-order bit of the type value is 1,
3975127667Sbms		 * this is either a control frame or a frame
3976127667Sbms		 * with a reserved type, and thus not a
3977127667Sbms		 * frame with an SA.
3978127667Sbms		 *
3979127667Sbms		 * I.e., check "!(link[0] & 0x04)".
3980127667Sbms		 */
3981147897Ssam		s = gen_load_a(OR_LINK, 0, BPF_B);
3982127667Sbms		b1 = new_block(JMP(BPF_JSET));
3983127667Sbms		b1->s.k = 0x04;
3984127667Sbms		b1->stmts = s;
3985127667Sbms		gen_not(b1);
3986127667Sbms
3987127667Sbms		/*
3988127667Sbms		 * AND that with the checks for data and management
3989127667Sbms		 * frames.
3990127667Sbms		 */
3991127667Sbms		gen_and(b1, b0);
3992127667Sbms		return b0;
3993127667Sbms
3994127667Sbms	case Q_DST:
3995127667Sbms		/*
3996127667Sbms		 * Oh, yuk.
3997127667Sbms		 *
3998127667Sbms		 *	For control frames, there is no DA.
3999127667Sbms		 *
4000127667Sbms		 *	For management frames, DA is at an
4001127667Sbms		 *	offset of 4 from the beginning of
4002127667Sbms		 *	the packet.
4003127667Sbms		 *
4004127667Sbms		 *	For data frames, DA is at an offset
4005127667Sbms		 *	of 4 from the beginning of the packet
4006127667Sbms		 *	if To DS is clear and at an offset of
4007127667Sbms		 *	16 from the beginning of the packet
4008127667Sbms		 *	if To DS is set.
4009127667Sbms		 */
4010127667Sbms
4011127667Sbms		/*
4012127667Sbms		 * Generate the tests to be done for data frames.
4013127667Sbms		 *
4014127667Sbms		 * First, check for To DS set, i.e. "link[1] & 0x01".
4015127667Sbms		 */
4016147897Ssam		s = gen_load_a(OR_LINK, 1, BPF_B);
4017127667Sbms		b1 = new_block(JMP(BPF_JSET));
4018127667Sbms		b1->s.k = 0x01;	/* To DS */
4019127667Sbms		b1->stmts = s;
4020127667Sbms
4021127667Sbms		/*
4022127667Sbms		 * If To DS is set, the DA is at 16.
4023127667Sbms		 */
4024147897Ssam		b0 = gen_bcmp(OR_LINK, 16, 6, eaddr);
4025127667Sbms		gen_and(b1, b0);
4026127667Sbms
4027127667Sbms		/*
4028127667Sbms		 * Now, check for To DS not set, i.e. check
4029127667Sbms		 * "!(link[1] & 0x01)".
4030127667Sbms		 */
4031147897Ssam		s = gen_load_a(OR_LINK, 1, BPF_B);
4032127667Sbms		b2 = new_block(JMP(BPF_JSET));
4033127667Sbms		b2->s.k = 0x01;	/* To DS */
4034127667Sbms		b2->stmts = s;
4035127667Sbms		gen_not(b2);
4036127667Sbms
4037127667Sbms		/*
4038127667Sbms		 * If To DS is not set, the DA is at 4.
4039127667Sbms		 */
4040147897Ssam		b1 = gen_bcmp(OR_LINK, 4, 6, eaddr);
4041127667Sbms		gen_and(b2, b1);
4042127667Sbms
4043127667Sbms		/*
4044127667Sbms		 * Now OR together the last two checks.  That gives
4045127667Sbms		 * the complete set of checks for data frames.
4046127667Sbms		 */
4047127667Sbms		gen_or(b1, b0);
4048127667Sbms
4049127667Sbms		/*
4050127667Sbms		 * Now check for a data frame.
4051127667Sbms		 * I.e, check "link[0] & 0x08".
4052127667Sbms		 */
4053147897Ssam		s = gen_load_a(OR_LINK, 0, BPF_B);
4054127667Sbms		b1 = new_block(JMP(BPF_JSET));
4055127667Sbms		b1->s.k = 0x08;
4056127667Sbms		b1->stmts = s;
4057127667Sbms
4058127667Sbms		/*
4059127667Sbms		 * AND that with the checks done for data frames.
4060127667Sbms		 */
4061127667Sbms		gen_and(b1, b0);
4062127667Sbms
4063127667Sbms		/*
4064127667Sbms		 * If the high-order bit of the type value is 0, this
4065127667Sbms		 * is a management frame.
4066127667Sbms		 * I.e, check "!(link[0] & 0x08)".
4067127667Sbms		 */
4068147897Ssam		s = gen_load_a(OR_LINK, 0, BPF_B);
4069127667Sbms		b2 = new_block(JMP(BPF_JSET));
4070127667Sbms		b2->s.k = 0x08;
4071127667Sbms		b2->stmts = s;
4072127667Sbms		gen_not(b2);
4073127667Sbms
4074127667Sbms		/*
4075127667Sbms		 * For management frames, the DA is at 4.
4076127667Sbms		 */
4077147897Ssam		b1 = gen_bcmp(OR_LINK, 4, 6, eaddr);
4078127667Sbms		gen_and(b2, b1);
4079127667Sbms
4080127667Sbms		/*
4081127667Sbms		 * OR that with the checks done for data frames.
4082127667Sbms		 * That gives the checks done for management and
4083127667Sbms		 * data frames.
4084127667Sbms		 */
4085127667Sbms		gen_or(b1, b0);
4086127667Sbms
4087127667Sbms		/*
4088127667Sbms		 * If the low-order bit of the type value is 1,
4089127667Sbms		 * this is either a control frame or a frame
4090127667Sbms		 * with a reserved type, and thus not a
4091127667Sbms		 * frame with an SA.
4092127667Sbms		 *
4093127667Sbms		 * I.e., check "!(link[0] & 0x04)".
4094127667Sbms		 */
4095147897Ssam		s = gen_load_a(OR_LINK, 0, BPF_B);
4096127667Sbms		b1 = new_block(JMP(BPF_JSET));
4097127667Sbms		b1->s.k = 0x04;
4098127667Sbms		b1->stmts = s;
4099127667Sbms		gen_not(b1);
4100127667Sbms
4101127667Sbms		/*
4102127667Sbms		 * AND that with the checks for data and management
4103127667Sbms		 * frames.
4104127667Sbms		 */
4105127667Sbms		gen_and(b1, b0);
4106127667Sbms		return b0;
4107127667Sbms
4108236167Sdelphij	case Q_RA:
4109236167Sdelphij		/*
4110236167Sdelphij		 * Not present in management frames; addr1 in other
4111236167Sdelphij		 * frames.
4112236167Sdelphij		 */
4113236167Sdelphij
4114236167Sdelphij		/*
4115236167Sdelphij		 * If the high-order bit of the type value is 0, this
4116236167Sdelphij		 * is a management frame.
4117236167Sdelphij		 * I.e, check "(link[0] & 0x08)".
4118236167Sdelphij		 */
4119236167Sdelphij		s = gen_load_a(OR_LINK, 0, BPF_B);
4120236167Sdelphij		b1 = new_block(JMP(BPF_JSET));
4121236167Sdelphij		b1->s.k = 0x08;
4122236167Sdelphij		b1->stmts = s;
4123236167Sdelphij
4124236167Sdelphij		/*
4125236167Sdelphij		 * Check addr1.
4126236167Sdelphij		 */
4127236167Sdelphij		b0 = gen_bcmp(OR_LINK, 4, 6, eaddr);
4128236167Sdelphij
4129236167Sdelphij		/*
4130236167Sdelphij		 * AND that with the check of addr1.
4131236167Sdelphij		 */
4132236167Sdelphij		gen_and(b1, b0);
4133236167Sdelphij		return (b0);
4134236167Sdelphij
4135236167Sdelphij	case Q_TA:
4136236167Sdelphij		/*
4137236167Sdelphij		 * Not present in management frames; addr2, if present,
4138236167Sdelphij		 * in other frames.
4139236167Sdelphij		 */
4140236167Sdelphij
4141236167Sdelphij		/*
4142236167Sdelphij		 * Not present in CTS or ACK control frames.
4143236167Sdelphij		 */
4144236167Sdelphij		b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
4145236167Sdelphij			IEEE80211_FC0_TYPE_MASK);
4146236167Sdelphij		gen_not(b0);
4147236167Sdelphij		b1 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
4148236167Sdelphij			IEEE80211_FC0_SUBTYPE_MASK);
4149236167Sdelphij		gen_not(b1);
4150236167Sdelphij		b2 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
4151236167Sdelphij			IEEE80211_FC0_SUBTYPE_MASK);
4152236167Sdelphij		gen_not(b2);
4153236167Sdelphij		gen_and(b1, b2);
4154236167Sdelphij		gen_or(b0, b2);
4155236167Sdelphij
4156236167Sdelphij		/*
4157236167Sdelphij		 * If the high-order bit of the type value is 0, this
4158236167Sdelphij		 * is a management frame.
4159236167Sdelphij		 * I.e, check "(link[0] & 0x08)".
4160236167Sdelphij		 */
4161236167Sdelphij		s = gen_load_a(OR_LINK, 0, BPF_B);
4162236167Sdelphij		b1 = new_block(JMP(BPF_JSET));
4163236167Sdelphij		b1->s.k = 0x08;
4164236167Sdelphij		b1->stmts = s;
4165236167Sdelphij
4166236167Sdelphij		/*
4167236167Sdelphij		 * AND that with the check for frames other than
4168236167Sdelphij		 * CTS and ACK frames.
4169236167Sdelphij		 */
4170236167Sdelphij		gen_and(b1, b2);
4171236167Sdelphij
4172236167Sdelphij		/*
4173236167Sdelphij		 * Check addr2.
4174236167Sdelphij		 */
4175236167Sdelphij		b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
4176236167Sdelphij		gen_and(b2, b1);
4177236167Sdelphij		return b1;
4178236167Sdelphij
4179190225Srpaulo	/*
4180236167Sdelphij	 * XXX - add BSSID keyword?
4181190225Srpaulo	 */
4182190225Srpaulo	case Q_ADDR1:
4183190225Srpaulo		return (gen_bcmp(OR_LINK, 4, 6, eaddr));
4184190225Srpaulo
4185190225Srpaulo	case Q_ADDR2:
4186190225Srpaulo		/*
4187190225Srpaulo		 * Not present in CTS or ACK control frames.
4188190225Srpaulo		 */
4189190225Srpaulo		b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
4190190225Srpaulo			IEEE80211_FC0_TYPE_MASK);
4191190225Srpaulo		gen_not(b0);
4192190225Srpaulo		b1 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
4193190225Srpaulo			IEEE80211_FC0_SUBTYPE_MASK);
4194190225Srpaulo		gen_not(b1);
4195190225Srpaulo		b2 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
4196190225Srpaulo			IEEE80211_FC0_SUBTYPE_MASK);
4197190225Srpaulo		gen_not(b2);
4198190225Srpaulo		gen_and(b1, b2);
4199190225Srpaulo		gen_or(b0, b2);
4200190225Srpaulo		b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
4201190225Srpaulo		gen_and(b2, b1);
4202190225Srpaulo		return b1;
4203190225Srpaulo
4204190225Srpaulo	case Q_ADDR3:
4205190225Srpaulo		/*
4206190225Srpaulo		 * Not present in control frames.
4207190225Srpaulo		 */
4208190225Srpaulo		b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
4209190225Srpaulo			IEEE80211_FC0_TYPE_MASK);
4210190225Srpaulo		gen_not(b0);
4211190225Srpaulo		b1 = gen_bcmp(OR_LINK, 16, 6, eaddr);
4212190225Srpaulo		gen_and(b0, b1);
4213190225Srpaulo		return b1;
4214190225Srpaulo
4215190225Srpaulo	case Q_ADDR4:
4216190225Srpaulo		/*
4217190225Srpaulo		 * Present only if the direction mask has both "From DS"
4218190225Srpaulo		 * and "To DS" set.  Neither control frames nor management
4219190225Srpaulo		 * frames should have both of those set, so we don't
4220190225Srpaulo		 * check the frame type.
4221190225Srpaulo		 */
4222190225Srpaulo		b0 = gen_mcmp(OR_LINK, 1, BPF_B,
4223190225Srpaulo			IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
4224190225Srpaulo		b1 = gen_bcmp(OR_LINK, 24, 6, eaddr);
4225190225Srpaulo		gen_and(b0, b1);
4226190225Srpaulo		return b1;
4227190225Srpaulo
4228127667Sbms	case Q_AND:
4229127667Sbms		b0 = gen_wlanhostop(eaddr, Q_SRC);
4230127667Sbms		b1 = gen_wlanhostop(eaddr, Q_DST);
4231127667Sbms		gen_and(b0, b1);
4232127667Sbms		return b1;
4233127667Sbms
4234127667Sbms	case Q_DEFAULT:
4235127667Sbms	case Q_OR:
4236127667Sbms		b0 = gen_wlanhostop(eaddr, Q_SRC);
4237127667Sbms		b1 = gen_wlanhostop(eaddr, Q_DST);
4238127667Sbms		gen_or(b0, b1);
4239127667Sbms		return b1;
4240127667Sbms	}
4241127667Sbms	abort();
4242127667Sbms	/* NOTREACHED */
4243127667Sbms}
4244127667Sbms
4245127667Sbms/*
4246127667Sbms * Like gen_ehostop, but for RFC 2625 IP-over-Fibre-Channel.
4247127667Sbms * (We assume that the addresses are IEEE 48-bit MAC addresses,
4248127667Sbms * as the RFC states.)
4249127667Sbms */
4250127667Sbmsstatic struct block *
4251127667Sbmsgen_ipfchostop(eaddr, dir)
4252127667Sbms	register const u_char *eaddr;
4253127667Sbms	register int dir;
4254127667Sbms{
4255122029Sgreen	register struct block *b0, *b1;
4256122029Sgreen
4257122029Sgreen	switch (dir) {
4258122029Sgreen	case Q_SRC:
4259147897Ssam		return gen_bcmp(OR_LINK, 10, 6, eaddr);
4260122029Sgreen
4261122029Sgreen	case Q_DST:
4262147897Ssam		return gen_bcmp(OR_LINK, 2, 6, eaddr);
4263122029Sgreen
4264122029Sgreen	case Q_AND:
4265127667Sbms		b0 = gen_ipfchostop(eaddr, Q_SRC);
4266127667Sbms		b1 = gen_ipfchostop(eaddr, Q_DST);
4267122029Sgreen		gen_and(b0, b1);
4268122029Sgreen		return b1;
4269122029Sgreen
4270122029Sgreen	case Q_DEFAULT:
4271122029Sgreen	case Q_OR:
4272127667Sbms		b0 = gen_ipfchostop(eaddr, Q_SRC);
4273127667Sbms		b1 = gen_ipfchostop(eaddr, Q_DST);
4274122029Sgreen		gen_or(b0, b1);
4275122029Sgreen		return b1;
4276236167Sdelphij
4277236167Sdelphij	case Q_ADDR1:
4278236167Sdelphij		bpf_error("'addr1' is only supported on 802.11");
4279236167Sdelphij		break;
4280236167Sdelphij
4281236167Sdelphij	case Q_ADDR2:
4282236167Sdelphij		bpf_error("'addr2' is only supported on 802.11");
4283236167Sdelphij		break;
4284236167Sdelphij
4285236167Sdelphij	case Q_ADDR3:
4286236167Sdelphij		bpf_error("'addr3' is only supported on 802.11");
4287236167Sdelphij		break;
4288236167Sdelphij
4289236167Sdelphij	case Q_ADDR4:
4290236167Sdelphij		bpf_error("'addr4' is only supported on 802.11");
4291236167Sdelphij		break;
4292236167Sdelphij
4293236167Sdelphij	case Q_RA:
4294236167Sdelphij		bpf_error("'ra' is only supported on 802.11");
4295236167Sdelphij		break;
4296236167Sdelphij
4297236167Sdelphij	case Q_TA:
4298236167Sdelphij		bpf_error("'ta' is only supported on 802.11");
4299236167Sdelphij		break;
4300122029Sgreen	}
4301122029Sgreen	abort();
4302122029Sgreen	/* NOTREACHED */
4303122029Sgreen}
4304122029Sgreen
4305122029Sgreen/*
430617683Spst * This is quite tricky because there may be pad bytes in front of the
430717683Spst * DECNET header, and then there are two possible data packet formats that
430817683Spst * carry both src and dst addresses, plus 5 packet types in a format that
430917683Spst * carries only the src node, plus 2 types that use a different format and
431017683Spst * also carry just the src node.
431117683Spst *
431217683Spst * Yuck.
431317683Spst *
431417683Spst * Instead of doing those all right, we just look for data packets with
431517683Spst * 0 or 1 bytes of padding.  If you want to look at other packets, that
431617683Spst * will require a lot more hacking.
431717683Spst *
431817683Spst * To add support for filtering on DECNET "areas" (network numbers)
431917683Spst * one would want to add a "mask" argument to this routine.  That would
432017683Spst * make the filter even more inefficient, although one could be clever
432117683Spst * and not generate masking instructions if the mask is 0xFFFF.
432217683Spst */
432317683Spststatic struct block *
4324147897Ssamgen_dnhostop(addr, dir)
432517683Spst	bpf_u_int32 addr;
432617683Spst	int dir;
432717683Spst{
432817683Spst	struct block *b0, *b1, *b2, *tmp;
432917683Spst	u_int offset_lh;	/* offset if long header is received */
433017683Spst	u_int offset_sh;	/* offset if short header is received */
433117683Spst
433217683Spst	switch (dir) {
433317683Spst
433417683Spst	case Q_DST:
433517683Spst		offset_sh = 1;	/* follows flags */
433617683Spst		offset_lh = 7;	/* flgs,darea,dsubarea,HIORD */
433717683Spst		break;
433817683Spst
433917683Spst	case Q_SRC:
434017683Spst		offset_sh = 3;	/* follows flags, dstnode */
434117683Spst		offset_lh = 15;	/* flgs,darea,dsubarea,did,sarea,ssub,HIORD */
434217683Spst		break;
434317683Spst
434417683Spst	case Q_AND:
434517683Spst		/* Inefficient because we do our Calvinball dance twice */
4346147897Ssam		b0 = gen_dnhostop(addr, Q_SRC);
4347147897Ssam		b1 = gen_dnhostop(addr, Q_DST);
434817683Spst		gen_and(b0, b1);
434917683Spst		return b1;
435017683Spst
435117683Spst	case Q_OR:
435217683Spst	case Q_DEFAULT:
435317683Spst		/* Inefficient because we do our Calvinball dance twice */
4354147897Ssam		b0 = gen_dnhostop(addr, Q_SRC);
4355147897Ssam		b1 = gen_dnhostop(addr, Q_DST);
435617683Spst		gen_or(b0, b1);
435717683Spst		return b1;
435817683Spst
435975110Sfenner	case Q_ISO:
4360146771Ssam		bpf_error("ISO host filtering not implemented");
4361127667Sbms
436217683Spst	default:
436317683Spst		abort();
436417683Spst	}
436517683Spst	b0 = gen_linktype(ETHERTYPE_DN);
436617683Spst	/* Check for pad = 1, long header case */
4367147897Ssam	tmp = gen_mcmp(OR_NET, 2, BPF_H,
436817683Spst	    (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF));
4369147897Ssam	b1 = gen_cmp(OR_NET, 2 + 1 + offset_lh,
4370172680Smlaier	    BPF_H, (bpf_int32)ntohs((u_short)addr));
437117683Spst	gen_and(tmp, b1);
437217683Spst	/* Check for pad = 0, long header case */
4373147897Ssam	tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
4374172680Smlaier	b2 = gen_cmp(OR_NET, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr));
437517683Spst	gen_and(tmp, b2);
437617683Spst	gen_or(b2, b1);
437717683Spst	/* Check for pad = 1, short header case */
4378147897Ssam	tmp = gen_mcmp(OR_NET, 2, BPF_H,
437917683Spst	    (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF));
4380172680Smlaier	b2 = gen_cmp(OR_NET, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
438117683Spst	gen_and(tmp, b2);
438217683Spst	gen_or(b2, b1);
438317683Spst	/* Check for pad = 0, short header case */
4384147897Ssam	tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
4385172680Smlaier	b2 = gen_cmp(OR_NET, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
438617683Spst	gen_and(tmp, b2);
438717683Spst	gen_or(b2, b1);
438817683Spst
438917683Spst	/* Combine with test for linktype */
439017683Spst	gen_and(b0, b1);
439117683Spst	return b1;
439217683Spst}
439317683Spst
4394162015Ssam/*
4395162015Ssam * Generate a check for IPv4 or IPv6 for MPLS-encapsulated packets;
4396162015Ssam * test the bottom-of-stack bit, and then check the version number
4397162015Ssam * field in the IP header.
4398162015Ssam */
439917683Spststatic struct block *
4400162015Ssamgen_mpls_linktype(proto)
4401162015Ssam	int proto;
4402162015Ssam{
4403162015Ssam	struct block *b0, *b1;
4404162015Ssam
4405162015Ssam        switch (proto) {
4406162015Ssam
4407162015Ssam        case Q_IP:
4408162015Ssam                /* match the bottom-of-stack bit */
4409162015Ssam                b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01);
4410162015Ssam                /* match the IPv4 version number */
4411162015Ssam                b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x40, 0xf0);
4412162015Ssam                gen_and(b0, b1);
4413162015Ssam                return b1;
4414162015Ssam
4415162015Ssam       case Q_IPV6:
4416162015Ssam                /* match the bottom-of-stack bit */
4417162015Ssam                b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01);
4418162015Ssam                /* match the IPv4 version number */
4419162015Ssam                b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x60, 0xf0);
4420162015Ssam                gen_and(b0, b1);
4421162015Ssam                return b1;
4422162015Ssam
4423162015Ssam       default:
4424162015Ssam                abort();
4425162015Ssam        }
4426162015Ssam}
4427162015Ssam
4428162015Ssamstatic struct block *
4429172680Smlaiergen_host(addr, mask, proto, dir, type)
443017683Spst	bpf_u_int32 addr;
443117683Spst	bpf_u_int32 mask;
443217683Spst	int proto;
443317683Spst	int dir;
4434172680Smlaier	int type;
443517683Spst{
443617683Spst	struct block *b0, *b1;
4437172680Smlaier	const char *typestr;
443817683Spst
4439172680Smlaier	if (type == Q_NET)
4440172680Smlaier		typestr = "net";
4441172680Smlaier	else
4442172680Smlaier		typestr = "host";
4443172680Smlaier
444417683Spst	switch (proto) {
444517683Spst
444617683Spst	case Q_DEFAULT:
4447172680Smlaier		b0 = gen_host(addr, mask, Q_IP, dir, type);
4448162015Ssam		/*
4449162015Ssam		 * Only check for non-IPv4 addresses if we're not
4450162015Ssam		 * checking MPLS-encapsulated packets.
4451162015Ssam		 */
4452162015Ssam		if (label_stack_depth == 0) {
4453172680Smlaier			b1 = gen_host(addr, mask, Q_ARP, dir, type);
4454162015Ssam			gen_or(b0, b1);
4455172680Smlaier			b0 = gen_host(addr, mask, Q_RARP, dir, type);
4456162015Ssam			gen_or(b1, b0);
445775110Sfenner		}
445817683Spst		return b0;
445917683Spst
446017683Spst	case Q_IP:
4461147897Ssam		return gen_hostop(addr, mask, dir, ETHERTYPE_IP, 12, 16);
446217683Spst
446317683Spst	case Q_RARP:
4464147897Ssam		return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, 14, 24);
446517683Spst
446617683Spst	case Q_ARP:
4467147897Ssam		return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, 14, 24);
446817683Spst
446917683Spst	case Q_TCP:
4470172680Smlaier		bpf_error("'tcp' modifier applied to %s", typestr);
447117683Spst
447298533Sfenner	case Q_SCTP:
4473172680Smlaier		bpf_error("'sctp' modifier applied to %s", typestr);
447498533Sfenner
447517683Spst	case Q_UDP:
4476172680Smlaier		bpf_error("'udp' modifier applied to %s", typestr);
447717683Spst
447817683Spst	case Q_ICMP:
4479172680Smlaier		bpf_error("'icmp' modifier applied to %s", typestr);
448017683Spst
448117683Spst	case Q_IGMP:
4482172680Smlaier		bpf_error("'igmp' modifier applied to %s", typestr);
448317683Spst
448417683Spst	case Q_IGRP:
4485172680Smlaier		bpf_error("'igrp' modifier applied to %s", typestr);
448617683Spst
448756891Sfenner	case Q_PIM:
4488172680Smlaier		bpf_error("'pim' modifier applied to %s", typestr);
448956891Sfenner
449098533Sfenner	case Q_VRRP:
4491172680Smlaier		bpf_error("'vrrp' modifier applied to %s", typestr);
449298533Sfenner
4493236167Sdelphij	case Q_CARP:
4494236167Sdelphij		bpf_error("'carp' modifier applied to %s", typestr);
4495236167Sdelphij
449617683Spst	case Q_ATALK:
449717683Spst		bpf_error("ATALK host filtering not implemented");
449817683Spst
449975110Sfenner	case Q_AARP:
450075110Sfenner		bpf_error("AARP host filtering not implemented");
450175110Sfenner
450217683Spst	case Q_DECNET:
4503147897Ssam		return gen_dnhostop(addr, dir);
450417683Spst
450517683Spst	case Q_SCA:
450617683Spst		bpf_error("SCA host filtering not implemented");
450717683Spst
450817683Spst	case Q_LAT:
450917683Spst		bpf_error("LAT host filtering not implemented");
451017683Spst
451117683Spst	case Q_MOPDL:
451217683Spst		bpf_error("MOPDL host filtering not implemented");
451317683Spst
451417683Spst	case Q_MOPRC:
451517683Spst		bpf_error("MOPRC host filtering not implemented");
451617683Spst
451756891Sfenner	case Q_IPV6:
451856891Sfenner		bpf_error("'ip6' modifier applied to ip host");
451956891Sfenner
452056891Sfenner	case Q_ICMPV6:
4521172680Smlaier		bpf_error("'icmp6' modifier applied to %s", typestr);
452256891Sfenner
452356891Sfenner	case Q_AH:
4524172680Smlaier		bpf_error("'ah' modifier applied to %s", typestr);
452556891Sfenner
452656891Sfenner	case Q_ESP:
4527172680Smlaier		bpf_error("'esp' modifier applied to %s", typestr);
452856891Sfenner
452975110Sfenner	case Q_ISO:
453075110Sfenner		bpf_error("ISO host filtering not implemented");
453175110Sfenner
453275110Sfenner	case Q_ESIS:
4533172680Smlaier		bpf_error("'esis' modifier applied to %s", typestr);
453475110Sfenner
453575110Sfenner	case Q_ISIS:
4536172680Smlaier		bpf_error("'isis' modifier applied to %s", typestr);
453775110Sfenner
453875110Sfenner	case Q_CLNP:
4539172680Smlaier		bpf_error("'clnp' modifier applied to %s", typestr);
454075110Sfenner
454198533Sfenner	case Q_STP:
4542172680Smlaier		bpf_error("'stp' modifier applied to %s", typestr);
454398533Sfenner
454498533Sfenner	case Q_IPX:
454598533Sfenner		bpf_error("IPX host filtering not implemented");
454698533Sfenner
454798533Sfenner	case Q_NETBEUI:
4548172680Smlaier		bpf_error("'netbeui' modifier applied to %s", typestr);
454998533Sfenner
4550147897Ssam	case Q_RADIO:
4551172680Smlaier		bpf_error("'radio' modifier applied to %s", typestr);
4552147897Ssam
455317683Spst	default:
455417683Spst		abort();
455517683Spst	}
455617683Spst	/* NOTREACHED */
455717683Spst}
455817683Spst
455956891Sfenner#ifdef INET6
456017683Spststatic struct block *
4561172680Smlaiergen_host6(addr, mask, proto, dir, type)
456256891Sfenner	struct in6_addr *addr;
456356891Sfenner	struct in6_addr *mask;
456456891Sfenner	int proto;
456556891Sfenner	int dir;
4566172680Smlaier	int type;
456756891Sfenner{
4568172680Smlaier	const char *typestr;
4569172680Smlaier
4570172680Smlaier	if (type == Q_NET)
4571172680Smlaier		typestr = "net";
4572172680Smlaier	else
4573172680Smlaier		typestr = "host";
4574172680Smlaier
457556891Sfenner	switch (proto) {
457656891Sfenner
457756891Sfenner	case Q_DEFAULT:
4578172680Smlaier		return gen_host6(addr, mask, Q_IPV6, dir, type);
457956891Sfenner
458056891Sfenner	case Q_IP:
4581172680Smlaier		bpf_error("'ip' modifier applied to ip6 %s", typestr);
458256891Sfenner
458356891Sfenner	case Q_RARP:
4584172680Smlaier		bpf_error("'rarp' modifier applied to ip6 %s", typestr);
458556891Sfenner
458656891Sfenner	case Q_ARP:
4587172680Smlaier		bpf_error("'arp' modifier applied to ip6 %s", typestr);
458856891Sfenner
458998533Sfenner	case Q_SCTP:
4590172680Smlaier		bpf_error("'sctp' modifier applied to %s", typestr);
459198533Sfenner
459256891Sfenner	case Q_TCP:
4593172680Smlaier		bpf_error("'tcp' modifier applied to %s", typestr);
459456891Sfenner
459556891Sfenner	case Q_UDP:
4596172680Smlaier		bpf_error("'udp' modifier applied to %s", typestr);
459756891Sfenner
459856891Sfenner	case Q_ICMP:
4599172680Smlaier		bpf_error("'icmp' modifier applied to %s", typestr);
460056891Sfenner
460156891Sfenner	case Q_IGMP:
4602172680Smlaier		bpf_error("'igmp' modifier applied to %s", typestr);
460356891Sfenner
460456891Sfenner	case Q_IGRP:
4605172680Smlaier		bpf_error("'igrp' modifier applied to %s", typestr);
460656891Sfenner
460756891Sfenner	case Q_PIM:
4608172680Smlaier		bpf_error("'pim' modifier applied to %s", typestr);
460956891Sfenner
461098533Sfenner	case Q_VRRP:
4611172680Smlaier		bpf_error("'vrrp' modifier applied to %s", typestr);
461298533Sfenner
4613236167Sdelphij	case Q_CARP:
4614236167Sdelphij		bpf_error("'carp' modifier applied to %s", typestr);
4615236167Sdelphij
461656891Sfenner	case Q_ATALK:
461756891Sfenner		bpf_error("ATALK host filtering not implemented");
461856891Sfenner
461975110Sfenner	case Q_AARP:
462075110Sfenner		bpf_error("AARP host filtering not implemented");
462175110Sfenner
462256891Sfenner	case Q_DECNET:
4623172680Smlaier		bpf_error("'decnet' modifier applied to ip6 %s", typestr);
462456891Sfenner
462556891Sfenner	case Q_SCA:
462656891Sfenner		bpf_error("SCA host filtering not implemented");
462756891Sfenner
462856891Sfenner	case Q_LAT:
462956891Sfenner		bpf_error("LAT host filtering not implemented");
463056891Sfenner
463156891Sfenner	case Q_MOPDL:
463256891Sfenner		bpf_error("MOPDL host filtering not implemented");
463356891Sfenner
463456891Sfenner	case Q_MOPRC:
463556891Sfenner		bpf_error("MOPRC host filtering not implemented");
463656891Sfenner
463756891Sfenner	case Q_IPV6:
4638147897Ssam		return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6, 8, 24);
463956891Sfenner
464056891Sfenner	case Q_ICMPV6:
4641172680Smlaier		bpf_error("'icmp6' modifier applied to %s", typestr);
464256891Sfenner
464356891Sfenner	case Q_AH:
4644172680Smlaier		bpf_error("'ah' modifier applied to %s", typestr);
464556891Sfenner
464656891Sfenner	case Q_ESP:
4647172680Smlaier		bpf_error("'esp' modifier applied to %s", typestr);
464856891Sfenner
464975110Sfenner	case Q_ISO:
465075110Sfenner		bpf_error("ISO host filtering not implemented");
465175110Sfenner
465275110Sfenner	case Q_ESIS:
4653172680Smlaier		bpf_error("'esis' modifier applied to %s", typestr);
465475110Sfenner
465575110Sfenner	case Q_ISIS:
4656172680Smlaier		bpf_error("'isis' modifier applied to %s", typestr);
465775110Sfenner
465875110Sfenner	case Q_CLNP:
4659172680Smlaier		bpf_error("'clnp' modifier applied to %s", typestr);
466075110Sfenner
466198533Sfenner	case Q_STP:
4662172680Smlaier		bpf_error("'stp' modifier applied to %s", typestr);
466398533Sfenner
466498533Sfenner	case Q_IPX:
466598533Sfenner		bpf_error("IPX host filtering not implemented");
466698533Sfenner
466798533Sfenner	case Q_NETBEUI:
4668172680Smlaier		bpf_error("'netbeui' modifier applied to %s", typestr);
466998533Sfenner
4670147897Ssam	case Q_RADIO:
4671172680Smlaier		bpf_error("'radio' modifier applied to %s", typestr);
4672147897Ssam
467356891Sfenner	default:
467456891Sfenner		abort();
467556891Sfenner	}
467656891Sfenner	/* NOTREACHED */
467756891Sfenner}
4678252281Sdelphij#endif
467956891Sfenner
468075110Sfenner#ifndef INET6
468156891Sfennerstatic struct block *
468217683Spstgen_gateway(eaddr, alist, proto, dir)
468317683Spst	const u_char *eaddr;
468417683Spst	bpf_u_int32 **alist;
468517683Spst	int proto;
468617683Spst	int dir;
468717683Spst{
468817683Spst	struct block *b0, *b1, *tmp;
468917683Spst
469017683Spst	if (dir != 0)
469117683Spst		bpf_error("direction applied to 'gateway'");
469217683Spst
469317683Spst	switch (proto) {
469417683Spst	case Q_DEFAULT:
469517683Spst	case Q_IP:
469617683Spst	case Q_ARP:
469717683Spst	case Q_RARP:
4698190225Srpaulo		switch (linktype) {
4699190225Srpaulo		case DLT_EN10MB:
4700236167Sdelphij		case DLT_NETANALYZER:
4701236167Sdelphij		case DLT_NETANALYZER_TRANSPARENT:
4702190225Srpaulo			b0 = gen_ehostop(eaddr, Q_OR);
4703190225Srpaulo			break;
4704190225Srpaulo		case DLT_FDDI:
4705190225Srpaulo			b0 = gen_fhostop(eaddr, Q_OR);
4706190225Srpaulo			break;
4707172680Smlaier		case DLT_IEEE802:
4708190225Srpaulo			b0 = gen_thostop(eaddr, Q_OR);
4709190225Srpaulo			break;
4710172680Smlaier		case DLT_IEEE802_11:
4711190225Srpaulo		case DLT_PRISM_HEADER:
4712172680Smlaier		case DLT_IEEE802_11_RADIO_AVS:
4713190225Srpaulo		case DLT_IEEE802_11_RADIO:
4714172680Smlaier		case DLT_PPI:
4715190225Srpaulo			b0 = gen_wlanhostop(eaddr, Q_OR);
4716190225Srpaulo			break;
4717190225Srpaulo		case DLT_SUNATM:
4718214518Srpaulo			if (!is_lane)
4719214518Srpaulo				bpf_error(
4720214518Srpaulo				    "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
4721214518Srpaulo			/*
4722214518Srpaulo			 * Check that the packet doesn't begin with an
4723214518Srpaulo			 * LE Control marker.  (We've already generated
4724214518Srpaulo			 * a test for LANE.)
4725214518Srpaulo			 */
4726214518Srpaulo			b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
4727214518Srpaulo			    BPF_H, 0xFF00);
4728214518Srpaulo			gen_not(b1);
4729127667Sbms
4730214518Srpaulo			/*
4731214518Srpaulo			 * Now check the MAC address.
4732214518Srpaulo			 */
4733214518Srpaulo			b0 = gen_ehostop(eaddr, Q_OR);
4734214518Srpaulo			gen_and(b1, b0);
4735190225Srpaulo			break;
4736172680Smlaier		case DLT_IP_OVER_FC:
4737190225Srpaulo			b0 = gen_ipfchostop(eaddr, Q_OR);
4738190225Srpaulo			break;
4739190225Srpaulo		default:
4740190225Srpaulo			bpf_error(
4741214518Srpaulo			    "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
4742190225Srpaulo		}
4743172680Smlaier		b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST);
474417683Spst		while (*alist) {
4745172680Smlaier			tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR,
4746172680Smlaier			    Q_HOST);
474717683Spst			gen_or(b1, tmp);
474817683Spst			b1 = tmp;
474917683Spst		}
475017683Spst		gen_not(b1);
475117683Spst		gen_and(b0, b1);
475217683Spst		return b1;
475317683Spst	}
475417683Spst	bpf_error("illegal modifier of 'gateway'");
475517683Spst	/* NOTREACHED */
475617683Spst}
475775110Sfenner#endif
475817683Spst
475917683Spststruct block *
476017683Spstgen_proto_abbrev(proto)
476117683Spst	int proto;
476217683Spst{
476375110Sfenner	struct block *b0;
476475110Sfenner	struct block *b1;
476517683Spst
476617683Spst	switch (proto) {
476717683Spst
476898533Sfenner	case Q_SCTP:
476998533Sfenner		b1 = gen_proto(IPPROTO_SCTP, Q_IP, Q_DEFAULT);
477098533Sfenner		b0 = gen_proto(IPPROTO_SCTP, Q_IPV6, Q_DEFAULT);
477198533Sfenner		gen_or(b0, b1);
477298533Sfenner		break;
477398533Sfenner
477417683Spst	case Q_TCP:
477556891Sfenner		b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT);
477656891Sfenner		b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
477756891Sfenner		gen_or(b0, b1);
477817683Spst		break;
477917683Spst
478017683Spst	case Q_UDP:
478156891Sfenner		b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT);
478256891Sfenner		b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
478356891Sfenner		gen_or(b0, b1);
478417683Spst		break;
478517683Spst
478617683Spst	case Q_ICMP:
478756891Sfenner		b1 = gen_proto(IPPROTO_ICMP, Q_IP, Q_DEFAULT);
478817683Spst		break;
478917683Spst
479075110Sfenner#ifndef	IPPROTO_IGMP
479175110Sfenner#define	IPPROTO_IGMP	2
479275110Sfenner#endif
479375110Sfenner
479417683Spst	case Q_IGMP:
479575110Sfenner		b1 = gen_proto(IPPROTO_IGMP, Q_IP, Q_DEFAULT);
479617683Spst		break;
479717683Spst
479817683Spst#ifndef	IPPROTO_IGRP
479917683Spst#define	IPPROTO_IGRP	9
480017683Spst#endif
480117683Spst	case Q_IGRP:
480256891Sfenner		b1 = gen_proto(IPPROTO_IGRP, Q_IP, Q_DEFAULT);
480317683Spst		break;
480417683Spst
480556891Sfenner#ifndef IPPROTO_PIM
480656891Sfenner#define IPPROTO_PIM	103
480756891Sfenner#endif
480856891Sfenner
480956891Sfenner	case Q_PIM:
481056891Sfenner		b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT);
481156891Sfenner		b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
481256891Sfenner		gen_or(b0, b1);
481356891Sfenner		break;
481456891Sfenner
481598533Sfenner#ifndef IPPROTO_VRRP
481698533Sfenner#define IPPROTO_VRRP	112
481798533Sfenner#endif
481898533Sfenner
481998533Sfenner	case Q_VRRP:
482098533Sfenner		b1 = gen_proto(IPPROTO_VRRP, Q_IP, Q_DEFAULT);
482198533Sfenner		break;
482298533Sfenner
4823236167Sdelphij#ifndef IPPROTO_CARP
4824236167Sdelphij#define IPPROTO_CARP	112
4825236167Sdelphij#endif
4826236167Sdelphij
4827236167Sdelphij	case Q_CARP:
4828236167Sdelphij		b1 = gen_proto(IPPROTO_CARP, Q_IP, Q_DEFAULT);
4829236167Sdelphij		break;
4830236167Sdelphij
483117683Spst	case Q_IP:
483217683Spst		b1 =  gen_linktype(ETHERTYPE_IP);
483317683Spst		break;
483417683Spst
483517683Spst	case Q_ARP:
483617683Spst		b1 =  gen_linktype(ETHERTYPE_ARP);
483717683Spst		break;
483817683Spst
483917683Spst	case Q_RARP:
484017683Spst		b1 =  gen_linktype(ETHERTYPE_REVARP);
484117683Spst		break;
484217683Spst
484317683Spst	case Q_LINK:
484417683Spst		bpf_error("link layer applied in wrong context");
484517683Spst
484617683Spst	case Q_ATALK:
484717683Spst		b1 =  gen_linktype(ETHERTYPE_ATALK);
484817683Spst		break;
484917683Spst
485075110Sfenner	case Q_AARP:
485175110Sfenner		b1 =  gen_linktype(ETHERTYPE_AARP);
485275110Sfenner		break;
485375110Sfenner
485417683Spst	case Q_DECNET:
485517683Spst		b1 =  gen_linktype(ETHERTYPE_DN);
485617683Spst		break;
485717683Spst
485817683Spst	case Q_SCA:
485917683Spst		b1 =  gen_linktype(ETHERTYPE_SCA);
486017683Spst		break;
486117683Spst
486217683Spst	case Q_LAT:
486317683Spst		b1 =  gen_linktype(ETHERTYPE_LAT);
486417683Spst		break;
486517683Spst
486617683Spst	case Q_MOPDL:
486717683Spst		b1 =  gen_linktype(ETHERTYPE_MOPDL);
486817683Spst		break;
486917683Spst
487017683Spst	case Q_MOPRC:
487117683Spst		b1 =  gen_linktype(ETHERTYPE_MOPRC);
487217683Spst		break;
487317683Spst
487456891Sfenner	case Q_IPV6:
487556891Sfenner		b1 = gen_linktype(ETHERTYPE_IPV6);
487656891Sfenner		break;
487756891Sfenner
487856891Sfenner#ifndef IPPROTO_ICMPV6
487956891Sfenner#define IPPROTO_ICMPV6	58
488056891Sfenner#endif
488156891Sfenner	case Q_ICMPV6:
488256891Sfenner		b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT);
488356891Sfenner		break;
488456891Sfenner
488556891Sfenner#ifndef IPPROTO_AH
488656891Sfenner#define IPPROTO_AH	51
488756891Sfenner#endif
488856891Sfenner	case Q_AH:
488956891Sfenner		b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT);
489056891Sfenner		b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT);
489156891Sfenner		gen_or(b0, b1);
489256891Sfenner		break;
489356891Sfenner
489456891Sfenner#ifndef IPPROTO_ESP
489556891Sfenner#define IPPROTO_ESP	50
489656891Sfenner#endif
489756891Sfenner	case Q_ESP:
489856891Sfenner		b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT);
489956891Sfenner		b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
490056891Sfenner		gen_or(b0, b1);
490156891Sfenner		break;
490256891Sfenner
490317749Spst	case Q_ISO:
4904146771Ssam		b1 = gen_linktype(LLCSAP_ISONS);
490517749Spst		break;
490617749Spst
490717749Spst	case Q_ESIS:
4908146771Ssam		b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT);
490917749Spst		break;
491017749Spst
491117749Spst	case Q_ISIS:
4912146771Ssam		b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
491317749Spst		break;
491417749Spst
4915127667Sbms	case Q_ISIS_L1: /* all IS-IS Level1 PDU-Types */
4916146771Ssam		b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
4917146771Ssam		b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
4918127667Sbms		gen_or(b0, b1);
4919146771Ssam		b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
4920127667Sbms		gen_or(b0, b1);
4921146771Ssam		b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
4922127667Sbms		gen_or(b0, b1);
4923146771Ssam		b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
4924127667Sbms		gen_or(b0, b1);
4925127667Sbms		break;
4926127667Sbms
4927127667Sbms	case Q_ISIS_L2: /* all IS-IS Level2 PDU-Types */
4928146771Ssam		b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
4929146771Ssam		b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
4930127667Sbms		gen_or(b0, b1);
4931146771Ssam		b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
4932127667Sbms		gen_or(b0, b1);
4933146771Ssam		b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
4934127667Sbms		gen_or(b0, b1);
4935146771Ssam		b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
4936127667Sbms		gen_or(b0, b1);
4937127667Sbms		break;
4938127667Sbms
4939127667Sbms	case Q_ISIS_IIH: /* all IS-IS Hello PDU-Types */
4940146771Ssam		b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
4941146771Ssam		b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
4942127667Sbms		gen_or(b0, b1);
4943146771Ssam		b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);
4944127667Sbms		gen_or(b0, b1);
4945127667Sbms		break;
4946127667Sbms
4947146771Ssam	case Q_ISIS_LSP:
4948146771Ssam		b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
4949146771Ssam		b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
4950127667Sbms		gen_or(b0, b1);
4951127667Sbms		break;
4952127667Sbms
4953127667Sbms	case Q_ISIS_SNP:
4954146771Ssam		b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
4955146771Ssam		b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
4956127667Sbms		gen_or(b0, b1);
4957146771Ssam		b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
4958127667Sbms		gen_or(b0, b1);
4959146771Ssam		b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
4960127667Sbms		gen_or(b0, b1);
4961127667Sbms		break;
4962127667Sbms
4963127667Sbms	case Q_ISIS_CSNP:
4964146771Ssam		b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
4965146771Ssam		b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
4966127667Sbms		gen_or(b0, b1);
4967127667Sbms		break;
4968127667Sbms
4969127667Sbms	case Q_ISIS_PSNP:
4970146771Ssam		b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
4971146771Ssam		b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
4972127667Sbms		gen_or(b0, b1);
4973127667Sbms		break;
4974127667Sbms
497575110Sfenner	case Q_CLNP:
4976146771Ssam		b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT);
497775110Sfenner		break;
497875110Sfenner
497998533Sfenner	case Q_STP:
4980146771Ssam		b1 = gen_linktype(LLCSAP_8021D);
498198533Sfenner		break;
498298533Sfenner
498398533Sfenner	case Q_IPX:
4984146771Ssam		b1 = gen_linktype(LLCSAP_IPX);
498598533Sfenner		break;
498698533Sfenner
498798533Sfenner	case Q_NETBEUI:
4988146771Ssam		b1 = gen_linktype(LLCSAP_NETBEUI);
498998533Sfenner		break;
499098533Sfenner
4991147897Ssam	case Q_RADIO:
4992147897Ssam		bpf_error("'radio' is not a valid protocol type");
4993147897Ssam
499417683Spst	default:
499517683Spst		abort();
499617683Spst	}
499717683Spst	return b1;
499817683Spst}
499917683Spst
500017683Spststatic struct block *
500117683Spstgen_ipfrag()
500217683Spst{
500317683Spst	struct slist *s;
500417683Spst	struct block *b;
500517683Spst
5006236167Sdelphij	/* not IPv4 frag other than the first frag */
5007147897Ssam	s = gen_load_a(OR_NET, 6, BPF_H);
500817683Spst	b = new_block(JMP(BPF_JSET));
500917683Spst	b->s.k = 0x1fff;
501017683Spst	b->stmts = s;
501117683Spst	gen_not(b);
501217683Spst
501317683Spst	return b;
501417683Spst}
501517683Spst
5016147897Ssam/*
5017147897Ssam * Generate a comparison to a port value in the transport-layer header
5018147897Ssam * at the specified offset from the beginning of that header.
5019147897Ssam *
5020147897Ssam * XXX - this handles a variable-length prefix preceding the link-layer
5021147897Ssam * header, such as the radiotap or AVS radio prefix, but doesn't handle
5022147897Ssam * variable-length link-layer headers (such as Token Ring or 802.11
5023147897Ssam * headers).
5024147897Ssam */
502517683Spststatic struct block *
502617683Spstgen_portatom(off, v)
502717683Spst	int off;
502817683Spst	bpf_int32 v;
502917683Spst{
5030147897Ssam	return gen_cmp(OR_TRAN_IPV4, off, BPF_H, v);
503117683Spst}
503217683Spst
503356891Sfennerstatic struct block *
503456891Sfennergen_portatom6(off, v)
503556891Sfenner	int off;
503656891Sfenner	bpf_int32 v;
503756891Sfenner{
5038147897Ssam	return gen_cmp(OR_TRAN_IPV6, off, BPF_H, v);
503956891Sfenner}
504056891Sfenner
504117683Spststruct block *
504217683Spstgen_portop(port, proto, dir)
504317683Spst	int port, proto, dir;
504417683Spst{
504517683Spst	struct block *b0, *b1, *tmp;
504617683Spst
5047236167Sdelphij	/* ip proto 'proto' and not a fragment other than the first fragment */
5048147897Ssam	tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto);
504917683Spst	b0 = gen_ipfrag();
505017683Spst	gen_and(tmp, b0);
505117683Spst
505217683Spst	switch (dir) {
505317683Spst	case Q_SRC:
505417683Spst		b1 = gen_portatom(0, (bpf_int32)port);
505517683Spst		break;
505617683Spst
505717683Spst	case Q_DST:
505817683Spst		b1 = gen_portatom(2, (bpf_int32)port);
505917683Spst		break;
506017683Spst
506117683Spst	case Q_OR:
506217683Spst	case Q_DEFAULT:
506317683Spst		tmp = gen_portatom(0, (bpf_int32)port);
506417683Spst		b1 = gen_portatom(2, (bpf_int32)port);
506517683Spst		gen_or(tmp, b1);
506617683Spst		break;
506717683Spst
506817683Spst	case Q_AND:
506917683Spst		tmp = gen_portatom(0, (bpf_int32)port);
507017683Spst		b1 = gen_portatom(2, (bpf_int32)port);
507117683Spst		gen_and(tmp, b1);
507217683Spst		break;
507317683Spst
507417683Spst	default:
507517683Spst		abort();
507617683Spst	}
507717683Spst	gen_and(b0, b1);
507817683Spst
507917683Spst	return b1;
508017683Spst}
508117683Spst
508217683Spststatic struct block *
508317683Spstgen_port(port, ip_proto, dir)
508417683Spst	int port;
508517683Spst	int ip_proto;
508617683Spst	int dir;
508717683Spst{
508817683Spst	struct block *b0, *b1, *tmp;
508917683Spst
5090127667Sbms	/*
5091127667Sbms	 * ether proto ip
5092127667Sbms	 *
5093127667Sbms	 * For FDDI, RFC 1188 says that SNAP encapsulation is used,
5094127667Sbms	 * not LLC encapsulation with LLCSAP_IP.
5095127667Sbms	 *
5096127667Sbms	 * For IEEE 802 networks - which includes 802.5 token ring
5097127667Sbms	 * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042
5098127667Sbms	 * says that SNAP encapsulation is used, not LLC encapsulation
5099127667Sbms	 * with LLCSAP_IP.
5100127667Sbms	 *
5101127667Sbms	 * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and
5102127667Sbms	 * RFC 2225 say that SNAP encapsulation is used, not LLC
5103127667Sbms	 * encapsulation with LLCSAP_IP.
5104127667Sbms	 *
5105127667Sbms	 * So we always check for ETHERTYPE_IP.
5106127667Sbms	 */
510717683Spst	b0 =  gen_linktype(ETHERTYPE_IP);
510817683Spst
510917683Spst	switch (ip_proto) {
511017683Spst	case IPPROTO_UDP:
511117683Spst	case IPPROTO_TCP:
511298533Sfenner	case IPPROTO_SCTP:
511317683Spst		b1 = gen_portop(port, ip_proto, dir);
511417683Spst		break;
511517683Spst
511617683Spst	case PROTO_UNDEF:
511717683Spst		tmp = gen_portop(port, IPPROTO_TCP, dir);
511817683Spst		b1 = gen_portop(port, IPPROTO_UDP, dir);
511917683Spst		gen_or(tmp, b1);
512098533Sfenner		tmp = gen_portop(port, IPPROTO_SCTP, dir);
512198533Sfenner		gen_or(tmp, b1);
512217683Spst		break;
512317683Spst
512417683Spst	default:
512517683Spst		abort();
512617683Spst	}
512717683Spst	gen_and(b0, b1);
512817683Spst	return b1;
512917683Spst}
513017683Spst
513156891Sfennerstruct block *
513256891Sfennergen_portop6(port, proto, dir)
513356891Sfenner	int port, proto, dir;
513456891Sfenner{
513556891Sfenner	struct block *b0, *b1, *tmp;
513656891Sfenner
5137147897Ssam	/* ip6 proto 'proto' */
5138236167Sdelphij	/* XXX - catch the first fragment of a fragmented packet? */
5139147897Ssam	b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto);
514056891Sfenner
514156891Sfenner	switch (dir) {
514256891Sfenner	case Q_SRC:
514356891Sfenner		b1 = gen_portatom6(0, (bpf_int32)port);
514456891Sfenner		break;
514556891Sfenner
514656891Sfenner	case Q_DST:
514756891Sfenner		b1 = gen_portatom6(2, (bpf_int32)port);
514856891Sfenner		break;
514956891Sfenner
515056891Sfenner	case Q_OR:
515156891Sfenner	case Q_DEFAULT:
515256891Sfenner		tmp = gen_portatom6(0, (bpf_int32)port);
515356891Sfenner		b1 = gen_portatom6(2, (bpf_int32)port);
515456891Sfenner		gen_or(tmp, b1);
515556891Sfenner		break;
515656891Sfenner
515756891Sfenner	case Q_AND:
515856891Sfenner		tmp = gen_portatom6(0, (bpf_int32)port);
515956891Sfenner		b1 = gen_portatom6(2, (bpf_int32)port);
516056891Sfenner		gen_and(tmp, b1);
516156891Sfenner		break;
516256891Sfenner
516356891Sfenner	default:
516456891Sfenner		abort();
516556891Sfenner	}
516656891Sfenner	gen_and(b0, b1);
516756891Sfenner
516856891Sfenner	return b1;
516956891Sfenner}
517056891Sfenner
517156891Sfennerstatic struct block *
517256891Sfennergen_port6(port, ip_proto, dir)
517356891Sfenner	int port;
517456891Sfenner	int ip_proto;
517556891Sfenner	int dir;
517656891Sfenner{
517756891Sfenner	struct block *b0, *b1, *tmp;
517856891Sfenner
5179147897Ssam	/* link proto ip6 */
518056891Sfenner	b0 =  gen_linktype(ETHERTYPE_IPV6);
518156891Sfenner
518256891Sfenner	switch (ip_proto) {
518356891Sfenner	case IPPROTO_UDP:
518456891Sfenner	case IPPROTO_TCP:
518598533Sfenner	case IPPROTO_SCTP:
518656891Sfenner		b1 = gen_portop6(port, ip_proto, dir);
518756891Sfenner		break;
518856891Sfenner
518956891Sfenner	case PROTO_UNDEF:
519056891Sfenner		tmp = gen_portop6(port, IPPROTO_TCP, dir);
519156891Sfenner		b1 = gen_portop6(port, IPPROTO_UDP, dir);
519256891Sfenner		gen_or(tmp, b1);
519398533Sfenner		tmp = gen_portop6(port, IPPROTO_SCTP, dir);
519498533Sfenner		gen_or(tmp, b1);
519556891Sfenner		break;
519656891Sfenner
519756891Sfenner	default:
519856891Sfenner		abort();
519956891Sfenner	}
520056891Sfenner	gen_and(b0, b1);
520156891Sfenner	return b1;
520256891Sfenner}
520356891Sfenner
5204147897Ssam/* gen_portrange code */
5205147897Ssamstatic struct block *
5206147897Ssamgen_portrangeatom(off, v1, v2)
5207147897Ssam	int off;
5208147897Ssam	bpf_int32 v1, v2;
5209147897Ssam{
5210147897Ssam	struct block *b1, *b2;
5211147897Ssam
5212147897Ssam	if (v1 > v2) {
5213147897Ssam		/*
5214147897Ssam		 * Reverse the order of the ports, so v1 is the lower one.
5215147897Ssam		 */
5216147897Ssam		bpf_int32 vtemp;
5217147897Ssam
5218147897Ssam		vtemp = v1;
5219147897Ssam		v1 = v2;
5220147897Ssam		v2 = vtemp;
5221147897Ssam	}
5222147897Ssam
5223147897Ssam	b1 = gen_cmp_ge(OR_TRAN_IPV4, off, BPF_H, v1);
5224147897Ssam	b2 = gen_cmp_le(OR_TRAN_IPV4, off, BPF_H, v2);
5225147897Ssam
5226147897Ssam	gen_and(b1, b2);
5227147897Ssam
5228147897Ssam	return b2;
5229147897Ssam}
5230147897Ssam
5231147897Ssamstruct block *
5232147897Ssamgen_portrangeop(port1, port2, proto, dir)
5233147897Ssam	int port1, port2;
5234147897Ssam	int proto;
5235147897Ssam	int dir;
5236147897Ssam{
5237147897Ssam	struct block *b0, *b1, *tmp;
5238147897Ssam
5239236167Sdelphij	/* ip proto 'proto' and not a fragment other than the first fragment */
5240147897Ssam	tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)proto);
5241147897Ssam	b0 = gen_ipfrag();
5242147897Ssam	gen_and(tmp, b0);
5243147897Ssam
5244147897Ssam	switch (dir) {
5245147897Ssam	case Q_SRC:
5246147897Ssam		b1 = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
5247147897Ssam		break;
5248147897Ssam
5249147897Ssam	case Q_DST:
5250147897Ssam		b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
5251147897Ssam		break;
5252147897Ssam
5253147897Ssam	case Q_OR:
5254147897Ssam	case Q_DEFAULT:
5255147897Ssam		tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
5256147897Ssam		b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
5257147897Ssam		gen_or(tmp, b1);
5258147897Ssam		break;
5259147897Ssam
5260147897Ssam	case Q_AND:
5261147897Ssam		tmp = gen_portrangeatom(0, (bpf_int32)port1, (bpf_int32)port2);
5262147897Ssam		b1 = gen_portrangeatom(2, (bpf_int32)port1, (bpf_int32)port2);
5263147897Ssam		gen_and(tmp, b1);
5264147897Ssam		break;
5265147897Ssam
5266147897Ssam	default:
5267147897Ssam		abort();
5268147897Ssam	}
5269147897Ssam	gen_and(b0, b1);
5270147897Ssam
5271147897Ssam	return b1;
5272147897Ssam}
5273147897Ssam
5274147897Ssamstatic struct block *
5275147897Ssamgen_portrange(port1, port2, ip_proto, dir)
5276147897Ssam	int port1, port2;
5277147897Ssam	int ip_proto;
5278147897Ssam	int dir;
5279147897Ssam{
5280147897Ssam	struct block *b0, *b1, *tmp;
5281147897Ssam
5282147897Ssam	/* link proto ip */
5283147897Ssam	b0 =  gen_linktype(ETHERTYPE_IP);
5284147897Ssam
5285147897Ssam	switch (ip_proto) {
5286147897Ssam	case IPPROTO_UDP:
5287147897Ssam	case IPPROTO_TCP:
5288147897Ssam	case IPPROTO_SCTP:
5289147897Ssam		b1 = gen_portrangeop(port1, port2, ip_proto, dir);
5290147897Ssam		break;
5291147897Ssam
5292147897Ssam	case PROTO_UNDEF:
5293147897Ssam		tmp = gen_portrangeop(port1, port2, IPPROTO_TCP, dir);
5294147897Ssam		b1 = gen_portrangeop(port1, port2, IPPROTO_UDP, dir);
5295147897Ssam		gen_or(tmp, b1);
5296147897Ssam		tmp = gen_portrangeop(port1, port2, IPPROTO_SCTP, dir);
5297147897Ssam		gen_or(tmp, b1);
5298147897Ssam		break;
5299147897Ssam
5300147897Ssam	default:
5301147897Ssam		abort();
5302147897Ssam	}
5303147897Ssam	gen_and(b0, b1);
5304147897Ssam	return b1;
5305147897Ssam}
5306147897Ssam
5307147897Ssamstatic struct block *
5308147897Ssamgen_portrangeatom6(off, v1, v2)
5309147897Ssam	int off;
5310147897Ssam	bpf_int32 v1, v2;
5311147897Ssam{
5312147897Ssam	struct block *b1, *b2;
5313147897Ssam
5314147897Ssam	if (v1 > v2) {
5315147897Ssam		/*
5316147897Ssam		 * Reverse the order of the ports, so v1 is the lower one.
5317147897Ssam		 */
5318147897Ssam		bpf_int32 vtemp;
5319147897Ssam
5320147897Ssam		vtemp = v1;
5321147897Ssam		v1 = v2;
5322147897Ssam		v2 = vtemp;
5323147897Ssam	}
5324147897Ssam
5325147897Ssam	b1 = gen_cmp_ge(OR_TRAN_IPV6, off, BPF_H, v1);
5326147897Ssam	b2 = gen_cmp_le(OR_TRAN_IPV6, off, BPF_H, v2);
5327147897Ssam
5328147897Ssam	gen_and(b1, b2);
5329147897Ssam
5330147897Ssam	return b2;
5331147897Ssam}
5332147897Ssam
5333147897Ssamstruct block *
5334147897Ssamgen_portrangeop6(port1, port2, proto, dir)
5335147897Ssam	int port1, port2;
5336147897Ssam	int proto;
5337147897Ssam	int dir;
5338147897Ssam{
5339147897Ssam	struct block *b0, *b1, *tmp;
5340147897Ssam
5341147897Ssam	/* ip6 proto 'proto' */
5342236167Sdelphij	/* XXX - catch the first fragment of a fragmented packet? */
5343147897Ssam	b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)proto);
5344147897Ssam
5345147897Ssam	switch (dir) {
5346147897Ssam	case Q_SRC:
5347147897Ssam		b1 = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
5348147897Ssam		break;
5349147897Ssam
5350147897Ssam	case Q_DST:
5351147897Ssam		b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
5352147897Ssam		break;
5353147897Ssam
5354147897Ssam	case Q_OR:
5355147897Ssam	case Q_DEFAULT:
5356147897Ssam		tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
5357147897Ssam		b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
5358147897Ssam		gen_or(tmp, b1);
5359147897Ssam		break;
5360147897Ssam
5361147897Ssam	case Q_AND:
5362147897Ssam		tmp = gen_portrangeatom6(0, (bpf_int32)port1, (bpf_int32)port2);
5363147897Ssam		b1 = gen_portrangeatom6(2, (bpf_int32)port1, (bpf_int32)port2);
5364147897Ssam		gen_and(tmp, b1);
5365147897Ssam		break;
5366147897Ssam
5367147897Ssam	default:
5368147897Ssam		abort();
5369147897Ssam	}
5370147897Ssam	gen_and(b0, b1);
5371147897Ssam
5372147897Ssam	return b1;
5373147897Ssam}
5374147897Ssam
5375147897Ssamstatic struct block *
5376147897Ssamgen_portrange6(port1, port2, ip_proto, dir)
5377147897Ssam	int port1, port2;
5378147897Ssam	int ip_proto;
5379147897Ssam	int dir;
5380147897Ssam{
5381147897Ssam	struct block *b0, *b1, *tmp;
5382147897Ssam
5383147897Ssam	/* link proto ip6 */
5384147897Ssam	b0 =  gen_linktype(ETHERTYPE_IPV6);
5385147897Ssam
5386147897Ssam	switch (ip_proto) {
5387147897Ssam	case IPPROTO_UDP:
5388147897Ssam	case IPPROTO_TCP:
5389147897Ssam	case IPPROTO_SCTP:
5390147897Ssam		b1 = gen_portrangeop6(port1, port2, ip_proto, dir);
5391147897Ssam		break;
5392147897Ssam
5393147897Ssam	case PROTO_UNDEF:
5394147897Ssam		tmp = gen_portrangeop6(port1, port2, IPPROTO_TCP, dir);
5395147897Ssam		b1 = gen_portrangeop6(port1, port2, IPPROTO_UDP, dir);
5396147897Ssam		gen_or(tmp, b1);
5397147897Ssam		tmp = gen_portrangeop6(port1, port2, IPPROTO_SCTP, dir);
5398147897Ssam		gen_or(tmp, b1);
5399147897Ssam		break;
5400147897Ssam
5401147897Ssam	default:
5402147897Ssam		abort();
5403147897Ssam	}
5404147897Ssam	gen_and(b0, b1);
5405147897Ssam	return b1;
5406147897Ssam}
5407147897Ssam
540817683Spststatic int
540917683Spstlookup_proto(name, proto)
541017683Spst	register const char *name;
541117683Spst	register int proto;
541217683Spst{
541317683Spst	register int v;
541417683Spst
541517683Spst	switch (proto) {
541617683Spst
541717683Spst	case Q_DEFAULT:
541817683Spst	case Q_IP:
541998533Sfenner	case Q_IPV6:
542017683Spst		v = pcap_nametoproto(name);
542117683Spst		if (v == PROTO_UNDEF)
542217683Spst			bpf_error("unknown ip proto '%s'", name);
542317683Spst		break;
542417683Spst
542517683Spst	case Q_LINK:
542617683Spst		/* XXX should look up h/w protocol type based on linktype */
542717683Spst		v = pcap_nametoeproto(name);
5428146771Ssam		if (v == PROTO_UNDEF) {
5429146771Ssam			v = pcap_nametollc(name);
5430146771Ssam			if (v == PROTO_UNDEF)
5431146771Ssam				bpf_error("unknown ether proto '%s'", name);
5432146771Ssam		}
543317683Spst		break;
543417683Spst
543575110Sfenner	case Q_ISO:
543675110Sfenner		if (strcmp(name, "esis") == 0)
543775110Sfenner			v = ISO9542_ESIS;
543875110Sfenner		else if (strcmp(name, "isis") == 0)
543975110Sfenner			v = ISO10589_ISIS;
544075110Sfenner		else if (strcmp(name, "clnp") == 0)
544175110Sfenner			v = ISO8473_CLNP;
544275110Sfenner		else
544375110Sfenner			bpf_error("unknown osi proto '%s'", name);
544475110Sfenner		break;
544575110Sfenner
544617683Spst	default:
544717683Spst		v = PROTO_UNDEF;
544817683Spst		break;
544917683Spst	}
545017683Spst	return v;
545117683Spst}
545217683Spst
545375110Sfenner#if 0
545456891Sfennerstruct stmt *
545556891Sfennergen_joinsp(s, n)
545656891Sfenner	struct stmt **s;
545756891Sfenner	int n;
545856891Sfenner{
545975110Sfenner	return NULL;
546056891Sfenner}
546175110Sfenner#endif
546256891Sfenner
546375110Sfennerstatic struct block *
546456891Sfennergen_protochain(v, proto, dir)
546556891Sfenner	int v;
546656891Sfenner	int proto;
546756891Sfenner	int dir;
546856891Sfenner{
546956891Sfenner#ifdef NO_PROTOCHAIN
547056891Sfenner	return gen_proto(v, proto, dir);
547156891Sfenner#else
547256891Sfenner	struct block *b0, *b;
547375110Sfenner	struct slist *s[100];
547456891Sfenner	int fix2, fix3, fix4, fix5;
547556891Sfenner	int ahcheck, again, end;
547656891Sfenner	int i, max;
547756891Sfenner	int reg2 = alloc_reg();
547856891Sfenner
547956891Sfenner	memset(s, 0, sizeof(s));
548056891Sfenner	fix2 = fix3 = fix4 = fix5 = 0;
548156891Sfenner
548256891Sfenner	switch (proto) {
548356891Sfenner	case Q_IP:
548456891Sfenner	case Q_IPV6:
548556891Sfenner		break;
548656891Sfenner	case Q_DEFAULT:
548756891Sfenner		b0 = gen_protochain(v, Q_IP, dir);
548856891Sfenner		b = gen_protochain(v, Q_IPV6, dir);
548956891Sfenner		gen_or(b0, b);
549056891Sfenner		return b;
549156891Sfenner	default:
549256891Sfenner		bpf_error("bad protocol applied for 'protochain'");
549356891Sfenner		/*NOTREACHED*/
549456891Sfenner	}
549556891Sfenner
5496147897Ssam	/*
5497190225Srpaulo	 * We don't handle variable-length prefixes before the link-layer
5498190225Srpaulo	 * header, or variable-length link-layer headers, here yet.
5499147897Ssam	 * We might want to add BPF instructions to do the protochain
5500147897Ssam	 * work, to simplify that and, on platforms that have a BPF
5501147897Ssam	 * interpreter with the new instructions, let the filtering
5502147897Ssam	 * be done in the kernel.  (We already require a modified BPF
5503147897Ssam	 * engine to do the protochain stuff, to support backward
5504147897Ssam	 * branches, and backward branch support is unlikely to appear
5505147897Ssam	 * in kernel BPF engines.)
5506147897Ssam	 */
5507190225Srpaulo	switch (linktype) {
5508147897Ssam
5509190225Srpaulo	case DLT_IEEE802_11:
5510190225Srpaulo	case DLT_PRISM_HEADER:
5511190225Srpaulo	case DLT_IEEE802_11_RADIO_AVS:
5512190225Srpaulo	case DLT_IEEE802_11_RADIO:
5513190225Srpaulo	case DLT_PPI:
5514190225Srpaulo		bpf_error("'protochain' not supported with 802.11");
5515190225Srpaulo	}
5516172680Smlaier
551756891Sfenner	no_optimize = 1; /*this code is not compatible with optimzer yet */
551856891Sfenner
551956891Sfenner	/*
5520147897Ssam	 * s[0] is a dummy entry to protect other BPF insn from damage
552156891Sfenner	 * by s[fix] = foo with uninitialized variable "fix".  It is somewhat
552256891Sfenner	 * hard to find interdependency made by jump table fixup.
552356891Sfenner	 */
552456891Sfenner	i = 0;
552556891Sfenner	s[i] = new_stmt(0);	/*dummy*/
552656891Sfenner	i++;
552756891Sfenner
552856891Sfenner	switch (proto) {
552956891Sfenner	case Q_IP:
553056891Sfenner		b0 = gen_linktype(ETHERTYPE_IP);
553156891Sfenner
553256891Sfenner		/* A = ip->ip_p */
553356891Sfenner		s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
5534190225Srpaulo		s[i]->s.k = off_macpl + off_nl + 9;
553556891Sfenner		i++;
553656891Sfenner		/* X = ip->ip_hl << 2 */
553756891Sfenner		s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
5538190225Srpaulo		s[i]->s.k = off_macpl + off_nl;
553956891Sfenner		i++;
554056891Sfenner		break;
5541252281Sdelphij
554256891Sfenner	case Q_IPV6:
554356891Sfenner		b0 = gen_linktype(ETHERTYPE_IPV6);
554456891Sfenner
554556891Sfenner		/* A = ip6->ip_nxt */
554656891Sfenner		s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
5547190225Srpaulo		s[i]->s.k = off_macpl + off_nl + 6;
554856891Sfenner		i++;
554956891Sfenner		/* X = sizeof(struct ip6_hdr) */
555056891Sfenner		s[i] = new_stmt(BPF_LDX|BPF_IMM);
555156891Sfenner		s[i]->s.k = 40;
555256891Sfenner		i++;
555356891Sfenner		break;
5554252281Sdelphij
555556891Sfenner	default:
555656891Sfenner		bpf_error("unsupported proto to gen_protochain");
555756891Sfenner		/*NOTREACHED*/
555856891Sfenner	}
555956891Sfenner
556056891Sfenner	/* again: if (A == v) goto end; else fall through; */
556156891Sfenner	again = i;
556256891Sfenner	s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
556356891Sfenner	s[i]->s.k = v;
556456891Sfenner	s[i]->s.jt = NULL;		/*later*/
556556891Sfenner	s[i]->s.jf = NULL;		/*update in next stmt*/
556656891Sfenner	fix5 = i;
556756891Sfenner	i++;
556856891Sfenner
556956891Sfenner#ifndef IPPROTO_NONE
557056891Sfenner#define IPPROTO_NONE	59
557156891Sfenner#endif
557256891Sfenner	/* if (A == IPPROTO_NONE) goto end */
557356891Sfenner	s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
557456891Sfenner	s[i]->s.jt = NULL;	/*later*/
557556891Sfenner	s[i]->s.jf = NULL;	/*update in next stmt*/
557656891Sfenner	s[i]->s.k = IPPROTO_NONE;
557756891Sfenner	s[fix5]->s.jf = s[i];
557856891Sfenner	fix2 = i;
557956891Sfenner	i++;
558056891Sfenner
558156891Sfenner	if (proto == Q_IPV6) {
558256891Sfenner		int v6start, v6end, v6advance, j;
558356891Sfenner
558456891Sfenner		v6start = i;
558556891Sfenner		/* if (A == IPPROTO_HOPOPTS) goto v6advance */
558656891Sfenner		s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
558756891Sfenner		s[i]->s.jt = NULL;	/*later*/
558856891Sfenner		s[i]->s.jf = NULL;	/*update in next stmt*/
558956891Sfenner		s[i]->s.k = IPPROTO_HOPOPTS;
559056891Sfenner		s[fix2]->s.jf = s[i];
559156891Sfenner		i++;
559256891Sfenner		/* if (A == IPPROTO_DSTOPTS) goto v6advance */
559356891Sfenner		s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
559456891Sfenner		s[i]->s.jt = NULL;	/*later*/
559556891Sfenner		s[i]->s.jf = NULL;	/*update in next stmt*/
559656891Sfenner		s[i]->s.k = IPPROTO_DSTOPTS;
559756891Sfenner		i++;
559856891Sfenner		/* if (A == IPPROTO_ROUTING) goto v6advance */
559956891Sfenner		s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
560056891Sfenner		s[i]->s.jt = NULL;	/*later*/
560156891Sfenner		s[i]->s.jf = NULL;	/*update in next stmt*/
560256891Sfenner		s[i]->s.k = IPPROTO_ROUTING;
560356891Sfenner		i++;
560456891Sfenner		/* if (A == IPPROTO_FRAGMENT) goto v6advance; else goto ahcheck; */
560556891Sfenner		s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
560656891Sfenner		s[i]->s.jt = NULL;	/*later*/
560756891Sfenner		s[i]->s.jf = NULL;	/*later*/
560856891Sfenner		s[i]->s.k = IPPROTO_FRAGMENT;
560956891Sfenner		fix3 = i;
561056891Sfenner		v6end = i;
561156891Sfenner		i++;
561256891Sfenner
561356891Sfenner		/* v6advance: */
561456891Sfenner		v6advance = i;
561556891Sfenner
561656891Sfenner		/*
561756891Sfenner		 * in short,
5618236167Sdelphij		 * A = P[X + packet head];
5619236167Sdelphij		 * X = X + (P[X + packet head + 1] + 1) * 8;
562056891Sfenner		 */
562175110Sfenner		/* A = P[X + packet head] */
562275110Sfenner		s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
5623190225Srpaulo		s[i]->s.k = off_macpl + off_nl;
562475110Sfenner		i++;
562575110Sfenner		/* MEM[reg2] = A */
562656891Sfenner		s[i] = new_stmt(BPF_ST);
562775110Sfenner		s[i]->s.k = reg2;
562856891Sfenner		i++;
5629236167Sdelphij		/* A = P[X + packet head + 1]; */
563056891Sfenner		s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
5631236167Sdelphij		s[i]->s.k = off_macpl + off_nl + 1;
563256891Sfenner		i++;
563356891Sfenner		/* A += 1 */
563456891Sfenner		s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
563556891Sfenner		s[i]->s.k = 1;
563656891Sfenner		i++;
563756891Sfenner		/* A *= 8 */
563856891Sfenner		s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
563956891Sfenner		s[i]->s.k = 8;
564056891Sfenner		i++;
5641236167Sdelphij		/* A += X */
5642236167Sdelphij		s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_X);
5643236167Sdelphij		s[i]->s.k = 0;
5644236167Sdelphij		i++;
564556891Sfenner		/* X = A; */
564656891Sfenner		s[i] = new_stmt(BPF_MISC|BPF_TAX);
564756891Sfenner		i++;
564856891Sfenner		/* A = MEM[reg2] */
564956891Sfenner		s[i] = new_stmt(BPF_LD|BPF_MEM);
565056891Sfenner		s[i]->s.k = reg2;
565156891Sfenner		i++;
565256891Sfenner
565356891Sfenner		/* goto again; (must use BPF_JA for backward jump) */
565456891Sfenner		s[i] = new_stmt(BPF_JMP|BPF_JA);
565556891Sfenner		s[i]->s.k = again - i - 1;
565656891Sfenner		s[i - 1]->s.jf = s[i];
565756891Sfenner		i++;
565856891Sfenner
565956891Sfenner		/* fixup */
566056891Sfenner		for (j = v6start; j <= v6end; j++)
566156891Sfenner			s[j]->s.jt = s[v6advance];
5662252281Sdelphij	} else {
566356891Sfenner		/* nop */
566456891Sfenner		s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
566556891Sfenner		s[i]->s.k = 0;
566656891Sfenner		s[fix2]->s.jf = s[i];
566756891Sfenner		i++;
566856891Sfenner	}
566956891Sfenner
567056891Sfenner	/* ahcheck: */
567156891Sfenner	ahcheck = i;
567256891Sfenner	/* if (A == IPPROTO_AH) then fall through; else goto end; */
567356891Sfenner	s[i] = new_stmt(BPF_JMP|BPF_JEQ|BPF_K);
567456891Sfenner	s[i]->s.jt = NULL;	/*later*/
567556891Sfenner	s[i]->s.jf = NULL;	/*later*/
567656891Sfenner	s[i]->s.k = IPPROTO_AH;
567756891Sfenner	if (fix3)
567856891Sfenner		s[fix3]->s.jf = s[ahcheck];
567956891Sfenner	fix4 = i;
568056891Sfenner	i++;
568156891Sfenner
568256891Sfenner	/*
568356891Sfenner	 * in short,
568475110Sfenner	 * A = P[X];
568575110Sfenner	 * X = X + (P[X + 1] + 2) * 4;
568656891Sfenner	 */
568756891Sfenner	/* A = X */
568856891Sfenner	s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA);
568956891Sfenner	i++;
569075110Sfenner	/* A = P[X + packet head]; */
569175110Sfenner	s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
5692190225Srpaulo	s[i]->s.k = off_macpl + off_nl;
569375110Sfenner	i++;
569475110Sfenner	/* MEM[reg2] = A */
569556891Sfenner	s[i] = new_stmt(BPF_ST);
569675110Sfenner	s[i]->s.k = reg2;
569756891Sfenner	i++;
569875110Sfenner	/* A = X */
569975110Sfenner	s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA);
570075110Sfenner	i++;
570156891Sfenner	/* A += 1 */
570256891Sfenner	s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
570356891Sfenner	s[i]->s.k = 1;
570456891Sfenner	i++;
570556891Sfenner	/* X = A */
570656891Sfenner	s[i] = new_stmt(BPF_MISC|BPF_TAX);
570756891Sfenner	i++;
570856891Sfenner	/* A = P[X + packet head] */
570956891Sfenner	s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B);
5710190225Srpaulo	s[i]->s.k = off_macpl + off_nl;
571156891Sfenner	i++;
571256891Sfenner	/* A += 2 */
571356891Sfenner	s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
571456891Sfenner	s[i]->s.k = 2;
571556891Sfenner	i++;
571656891Sfenner	/* A *= 4 */
571756891Sfenner	s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K);
571856891Sfenner	s[i]->s.k = 4;
571956891Sfenner	i++;
572056891Sfenner	/* X = A; */
572156891Sfenner	s[i] = new_stmt(BPF_MISC|BPF_TAX);
572256891Sfenner	i++;
572356891Sfenner	/* A = MEM[reg2] */
572456891Sfenner	s[i] = new_stmt(BPF_LD|BPF_MEM);
572556891Sfenner	s[i]->s.k = reg2;
572656891Sfenner	i++;
572756891Sfenner
572856891Sfenner	/* goto again; (must use BPF_JA for backward jump) */
572956891Sfenner	s[i] = new_stmt(BPF_JMP|BPF_JA);
573056891Sfenner	s[i]->s.k = again - i - 1;
573156891Sfenner	i++;
573256891Sfenner
573356891Sfenner	/* end: nop */
573456891Sfenner	end = i;
573556891Sfenner	s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K);
573656891Sfenner	s[i]->s.k = 0;
573756891Sfenner	s[fix2]->s.jt = s[end];
573856891Sfenner	s[fix4]->s.jf = s[end];
573956891Sfenner	s[fix5]->s.jt = s[end];
574056891Sfenner	i++;
574156891Sfenner
574256891Sfenner	/*
574356891Sfenner	 * make slist chain
574456891Sfenner	 */
574556891Sfenner	max = i;
574656891Sfenner	for (i = 0; i < max - 1; i++)
574756891Sfenner		s[i]->next = s[i + 1];
574856891Sfenner	s[max - 1]->next = NULL;
574956891Sfenner
575056891Sfenner	/*
575156891Sfenner	 * emit final check
575256891Sfenner	 */
575356891Sfenner	b = new_block(JMP(BPF_JEQ));
575456891Sfenner	b->stmts = s[1];	/*remember, s[0] is dummy*/
575556891Sfenner	b->s.k = v;
575656891Sfenner
575756891Sfenner	free_reg(reg2);
575856891Sfenner
575956891Sfenner	gen_and(b0, b);
576056891Sfenner	return b;
576156891Sfenner#endif
576256891Sfenner}
576356891Sfenner
5764190225Srpaulostatic struct block *
5765190225Srpaulogen_check_802_11_data_frame()
5766190225Srpaulo{
5767190225Srpaulo	struct slist *s;
5768190225Srpaulo	struct block *b0, *b1;
5769172680Smlaier
5770190225Srpaulo	/*
5771190225Srpaulo	 * A data frame has the 0x08 bit (b3) in the frame control field set
5772190225Srpaulo	 * and the 0x04 bit (b2) clear.
5773190225Srpaulo	 */
5774190225Srpaulo	s = gen_load_a(OR_LINK, 0, BPF_B);
5775190225Srpaulo	b0 = new_block(JMP(BPF_JSET));
5776190225Srpaulo	b0->s.k = 0x08;
5777190225Srpaulo	b0->stmts = s;
5778190225Srpaulo
5779190225Srpaulo	s = gen_load_a(OR_LINK, 0, BPF_B);
5780190225Srpaulo	b1 = new_block(JMP(BPF_JSET));
5781190225Srpaulo	b1->s.k = 0x04;
5782190225Srpaulo	b1->stmts = s;
5783190225Srpaulo	gen_not(b1);
5784190225Srpaulo
5785190225Srpaulo	gen_and(b1, b0);
5786190225Srpaulo
5787190225Srpaulo	return b0;
5788190225Srpaulo}
5789190225Srpaulo
5790147897Ssam/*
5791147897Ssam * Generate code that checks whether the packet is a packet for protocol
5792147897Ssam * <proto> and whether the type field in that protocol's header has
5793147897Ssam * the value <v>, e.g. if <proto> is Q_IP, it checks whether it's an
5794147897Ssam * IP packet and checks the protocol number in the IP header against <v>.
5795147897Ssam *
5796147897Ssam * If <proto> is Q_DEFAULT, i.e. just "proto" was specified, it checks
5797147897Ssam * against Q_IP and Q_IPV6.
5798147897Ssam */
579917683Spststatic struct block *
580017683Spstgen_proto(v, proto, dir)
580117683Spst	int v;
580217683Spst	int proto;
580317683Spst	int dir;
580417683Spst{
580517683Spst	struct block *b0, *b1;
5806242484Sdelphij#ifndef CHASE_CHAIN
5807242484Sdelphij	struct block *b2;
5808242484Sdelphij#endif
580917683Spst
581017683Spst	if (dir != Q_DEFAULT)
581117683Spst		bpf_error("direction applied to 'proto'");
581217683Spst
581317683Spst	switch (proto) {
581417683Spst	case Q_DEFAULT:
581556891Sfenner		b0 = gen_proto(v, Q_IP, dir);
581656891Sfenner		b1 = gen_proto(v, Q_IPV6, dir);
581756891Sfenner		gen_or(b0, b1);
581856891Sfenner		return b1;
5819252281Sdelphij
582017683Spst	case Q_IP:
5821127667Sbms		/*
5822127667Sbms		 * For FDDI, RFC 1188 says that SNAP encapsulation is used,
5823127667Sbms		 * not LLC encapsulation with LLCSAP_IP.
5824127667Sbms		 *
5825127667Sbms		 * For IEEE 802 networks - which includes 802.5 token ring
5826127667Sbms		 * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042
5827127667Sbms		 * says that SNAP encapsulation is used, not LLC encapsulation
5828127667Sbms		 * with LLCSAP_IP.
5829127667Sbms		 *
5830127667Sbms		 * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and
5831127667Sbms		 * RFC 2225 say that SNAP encapsulation is used, not LLC
5832127667Sbms		 * encapsulation with LLCSAP_IP.
5833127667Sbms		 *
5834127667Sbms		 * So we always check for ETHERTYPE_IP.
5835127667Sbms		 */
583617683Spst		b0 = gen_linktype(ETHERTYPE_IP);
583756891Sfenner#ifndef CHASE_CHAIN
5838147897Ssam		b1 = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32)v);
583956891Sfenner#else
584056891Sfenner		b1 = gen_protochain(v, Q_IP);
584156891Sfenner#endif
584217683Spst		gen_and(b0, b1);
584317683Spst		return b1;
584417683Spst
584517749Spst	case Q_ISO:
5846127667Sbms		switch (linktype) {
5847127667Sbms
5848127667Sbms		case DLT_FRELAY:
5849127667Sbms			/*
5850127667Sbms			 * Frame Relay packets typically have an OSI
5851127667Sbms			 * NLPID at the beginning; "gen_linktype(LLCSAP_ISONS)"
5852127667Sbms			 * generates code to check for all the OSI
5853127667Sbms			 * NLPIDs, so calling it and then adding a check
5854127667Sbms			 * for the particular NLPID for which we're
5855127667Sbms			 * looking is bogus, as we can just check for
5856127667Sbms			 * the NLPID.
5857127667Sbms			 *
5858127667Sbms			 * What we check for is the NLPID and a frame
5859127667Sbms			 * control field value of UI, i.e. 0x03 followed
5860127667Sbms			 * by the NLPID.
5861127667Sbms			 *
5862127667Sbms			 * XXX - assumes a 2-byte Frame Relay header with
5863127667Sbms			 * DLCI and flags.  What if the address is longer?
5864127667Sbms			 *
5865127667Sbms			 * XXX - what about SNAP-encapsulated frames?
5866127667Sbms			 */
5867147897Ssam			return gen_cmp(OR_LINK, 2, BPF_H, (0x03<<8) | v);
5868146771Ssam			/*NOTREACHED*/
5869127667Sbms			break;
5870127667Sbms
5871127667Sbms		case DLT_C_HDLC:
5872127667Sbms			/*
5873127667Sbms			 * Cisco uses an Ethertype lookalike - for OSI,
5874127667Sbms			 * it's 0xfefe.
5875127667Sbms			 */
5876127667Sbms			b0 = gen_linktype(LLCSAP_ISONS<<8 | LLCSAP_ISONS);
5877127667Sbms			/* OSI in C-HDLC is stuffed with a fudge byte */
5878147897Ssam			b1 = gen_cmp(OR_NET_NOSNAP, 1, BPF_B, (long)v);
5879127667Sbms			gen_and(b0, b1);
5880127667Sbms			return b1;
5881127667Sbms
5882127667Sbms		default:
5883127667Sbms			b0 = gen_linktype(LLCSAP_ISONS);
5884147897Ssam			b1 = gen_cmp(OR_NET_NOSNAP, 0, BPF_B, (long)v);
5885127667Sbms			gen_and(b0, b1);
5886127667Sbms			return b1;
5887127667Sbms		}
5888127667Sbms
5889127667Sbms	case Q_ISIS:
5890127667Sbms		b0 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
5891127667Sbms		/*
5892127667Sbms		 * 4 is the offset of the PDU type relative to the IS-IS
5893127667Sbms		 * header.
5894127667Sbms		 */
5895147897Ssam		b1 = gen_cmp(OR_NET_NOSNAP, 4, BPF_B, (long)v);
589617749Spst		gen_and(b0, b1);
589717749Spst		return b1;
589817749Spst
589917683Spst	case Q_ARP:
590017683Spst		bpf_error("arp does not encapsulate another protocol");
590117683Spst		/* NOTREACHED */
590217683Spst
590317683Spst	case Q_RARP:
590417683Spst		bpf_error("rarp does not encapsulate another protocol");
590517683Spst		/* NOTREACHED */
590617683Spst
590717683Spst	case Q_ATALK:
590817683Spst		bpf_error("atalk encapsulation is not specifiable");
590917683Spst		/* NOTREACHED */
591017683Spst
591117683Spst	case Q_DECNET:
591217683Spst		bpf_error("decnet encapsulation is not specifiable");
591317683Spst		/* NOTREACHED */
591417683Spst
591517683Spst	case Q_SCA:
591617683Spst		bpf_error("sca does not encapsulate another protocol");
591717683Spst		/* NOTREACHED */
591817683Spst
591917683Spst	case Q_LAT:
592017683Spst		bpf_error("lat does not encapsulate another protocol");
592117683Spst		/* NOTREACHED */
592217683Spst
592317683Spst	case Q_MOPRC:
592417683Spst		bpf_error("moprc does not encapsulate another protocol");
592517683Spst		/* NOTREACHED */
592617683Spst
592717683Spst	case Q_MOPDL:
592817683Spst		bpf_error("mopdl does not encapsulate another protocol");
592917683Spst		/* NOTREACHED */
593017683Spst
593117683Spst	case Q_LINK:
593217683Spst		return gen_linktype(v);
593317683Spst
593417683Spst	case Q_UDP:
593517683Spst		bpf_error("'udp proto' is bogus");
593617683Spst		/* NOTREACHED */
593717683Spst
593817683Spst	case Q_TCP:
593917683Spst		bpf_error("'tcp proto' is bogus");
594017683Spst		/* NOTREACHED */
594117683Spst
594298533Sfenner	case Q_SCTP:
594398533Sfenner		bpf_error("'sctp proto' is bogus");
594498533Sfenner		/* NOTREACHED */
594598533Sfenner
594617683Spst	case Q_ICMP:
594717683Spst		bpf_error("'icmp proto' is bogus");
594817683Spst		/* NOTREACHED */
594917683Spst
595017683Spst	case Q_IGMP:
595117683Spst		bpf_error("'igmp proto' is bogus");
595217683Spst		/* NOTREACHED */
595317683Spst
595417683Spst	case Q_IGRP:
595517683Spst		bpf_error("'igrp proto' is bogus");
595617683Spst		/* NOTREACHED */
595717683Spst
595856891Sfenner	case Q_PIM:
595956891Sfenner		bpf_error("'pim proto' is bogus");
596056891Sfenner		/* NOTREACHED */
596156891Sfenner
596298533Sfenner	case Q_VRRP:
596398533Sfenner		bpf_error("'vrrp proto' is bogus");
596498533Sfenner		/* NOTREACHED */
596598533Sfenner
5966236167Sdelphij	case Q_CARP:
5967236167Sdelphij		bpf_error("'carp proto' is bogus");
5968236167Sdelphij		/* NOTREACHED */
5969236167Sdelphij
597056891Sfenner	case Q_IPV6:
597156891Sfenner		b0 = gen_linktype(ETHERTYPE_IPV6);
597256891Sfenner#ifndef CHASE_CHAIN
5973242484Sdelphij		/*
5974242484Sdelphij		 * Also check for a fragment header before the final
5975242484Sdelphij		 * header.
5976242484Sdelphij		 */
5977242484Sdelphij		b2 = gen_cmp(OR_NET, 6, BPF_B, IPPROTO_FRAGMENT);
5978242484Sdelphij		b1 = gen_cmp(OR_NET, 40, BPF_B, (bpf_int32)v);
5979242484Sdelphij		gen_and(b2, b1);
5980242484Sdelphij		b2 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32)v);
5981242484Sdelphij		gen_or(b2, b1);
598256891Sfenner#else
598356891Sfenner		b1 = gen_protochain(v, Q_IPV6);
598456891Sfenner#endif
598556891Sfenner		gen_and(b0, b1);
598656891Sfenner		return b1;
598756891Sfenner
598856891Sfenner	case Q_ICMPV6:
598956891Sfenner		bpf_error("'icmp6 proto' is bogus");
599056891Sfenner
599156891Sfenner	case Q_AH:
599256891Sfenner		bpf_error("'ah proto' is bogus");
599356891Sfenner
599456891Sfenner	case Q_ESP:
599556891Sfenner		bpf_error("'ah proto' is bogus");
599656891Sfenner
599798533Sfenner	case Q_STP:
599898533Sfenner		bpf_error("'stp proto' is bogus");
599998533Sfenner
600098533Sfenner	case Q_IPX:
600198533Sfenner		bpf_error("'ipx proto' is bogus");
600298533Sfenner
600398533Sfenner	case Q_NETBEUI:
600498533Sfenner		bpf_error("'netbeui proto' is bogus");
600598533Sfenner
6006147897Ssam	case Q_RADIO:
6007147897Ssam		bpf_error("'radio proto' is bogus");
6008147897Ssam
600917683Spst	default:
601017683Spst		abort();
601117683Spst		/* NOTREACHED */
601217683Spst	}
601317683Spst	/* NOTREACHED */
601417683Spst}
601517683Spst
601617683Spststruct block *
601717683Spstgen_scode(name, q)
601817683Spst	register const char *name;
601917683Spst	struct qual q;
602017683Spst{
602117683Spst	int proto = q.proto;
602217683Spst	int dir = q.dir;
602326178Sfenner	int tproto;
602417683Spst	u_char *eaddr;
602575110Sfenner	bpf_u_int32 mask, addr;
602675110Sfenner#ifndef INET6
602775110Sfenner	bpf_u_int32 **alist;
602875110Sfenner#else
602956891Sfenner	int tproto6;
6030172680Smlaier	struct sockaddr_in *sin4;
603156891Sfenner	struct sockaddr_in6 *sin6;
603256891Sfenner	struct addrinfo *res, *res0;
603356891Sfenner	struct in6_addr mask128;
603456891Sfenner#endif /*INET6*/
603517683Spst	struct block *b, *tmp;
603617683Spst	int port, real_proto;
6037147897Ssam	int port1, port2;
603817683Spst
603917683Spst	switch (q.addr) {
604017683Spst
604117683Spst	case Q_NET:
604217683Spst		addr = pcap_nametonetaddr(name);
604317683Spst		if (addr == 0)
604417683Spst			bpf_error("unknown network '%s'", name);
604517683Spst		/* Left justify network addr and calculate its network mask */
604617683Spst		mask = 0xffffffff;
604717683Spst		while (addr && (addr & 0xff000000) == 0) {
604817683Spst			addr <<= 8;
604917683Spst			mask <<= 8;
605017683Spst		}
6051172680Smlaier		return gen_host(addr, mask, proto, dir, q.addr);
605217683Spst
605317683Spst	case Q_DEFAULT:
605417683Spst	case Q_HOST:
605517683Spst		if (proto == Q_LINK) {
605617683Spst			switch (linktype) {
605717683Spst
605817683Spst			case DLT_EN10MB:
6059236167Sdelphij			case DLT_NETANALYZER:
6060236167Sdelphij			case DLT_NETANALYZER_TRANSPARENT:
606117683Spst				eaddr = pcap_ether_hostton(name);
606217683Spst				if (eaddr == NULL)
606317683Spst					bpf_error(
606417683Spst					    "unknown ether host '%s'", name);
606598533Sfenner				b = gen_ehostop(eaddr, dir);
606698533Sfenner				free(eaddr);
606798533Sfenner				return b;
606817683Spst
606917683Spst			case DLT_FDDI:
607017683Spst				eaddr = pcap_ether_hostton(name);
607117683Spst				if (eaddr == NULL)
607217683Spst					bpf_error(
607317683Spst					    "unknown FDDI host '%s'", name);
607498533Sfenner				b = gen_fhostop(eaddr, dir);
607598533Sfenner				free(eaddr);
607698533Sfenner				return b;
607717683Spst
607875110Sfenner			case DLT_IEEE802:
607975110Sfenner				eaddr = pcap_ether_hostton(name);
608075110Sfenner				if (eaddr == NULL)
608175110Sfenner					bpf_error(
608275110Sfenner					    "unknown token ring host '%s'", name);
608398533Sfenner				b = gen_thostop(eaddr, dir);
608498533Sfenner				free(eaddr);
608598533Sfenner				return b;
608675110Sfenner
6087122029Sgreen			case DLT_IEEE802_11:
6088190225Srpaulo			case DLT_PRISM_HEADER:
6089147897Ssam			case DLT_IEEE802_11_RADIO_AVS:
6090147897Ssam			case DLT_IEEE802_11_RADIO:
6091172680Smlaier			case DLT_PPI:
6092122029Sgreen				eaddr = pcap_ether_hostton(name);
6093122029Sgreen				if (eaddr == NULL)
6094122029Sgreen					bpf_error(
6095127667Sbms					    "unknown 802.11 host '%s'", name);
6096127667Sbms				b = gen_wlanhostop(eaddr, dir);
6097127667Sbms				free(eaddr);
6098127667Sbms				return b;
6099127667Sbms
6100127667Sbms			case DLT_IP_OVER_FC:
6101127667Sbms				eaddr = pcap_ether_hostton(name);
6102127667Sbms				if (eaddr == NULL)
6103127667Sbms					bpf_error(
6104127667Sbms					    "unknown Fibre Channel host '%s'", name);
6105127667Sbms				b = gen_ipfchostop(eaddr, dir);
6106127667Sbms				free(eaddr);
6107127667Sbms				return b;
6108127667Sbms
6109127667Sbms			case DLT_SUNATM:
6110127667Sbms				if (!is_lane)
6111127667Sbms					break;
6112127667Sbms
6113127667Sbms				/*
6114127667Sbms				 * Check that the packet doesn't begin
6115127667Sbms				 * with an LE Control marker.  (We've
6116127667Sbms				 * already generated a test for LANE.)
6117127667Sbms				 */
6118147897Ssam				tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
6119147897Ssam				    BPF_H, 0xFF00);
6120127667Sbms				gen_not(tmp);
6121127667Sbms
6122127667Sbms				eaddr = pcap_ether_hostton(name);
6123127667Sbms				if (eaddr == NULL)
6124127667Sbms					bpf_error(
6125122029Sgreen					    "unknown ether host '%s'", name);
6126127667Sbms				b = gen_ehostop(eaddr, dir);
6127127667Sbms				gen_and(tmp, b);
6128122029Sgreen				free(eaddr);
6129122029Sgreen				return b;
6130127667Sbms			}
6131122029Sgreen
6132127667Sbms			bpf_error("only ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel supports link-level host name");
613317683Spst		} else if (proto == Q_DECNET) {
613417683Spst			unsigned short dn_addr = __pcap_nametodnaddr(name);
613517683Spst			/*
613617683Spst			 * I don't think DECNET hosts can be multihomed, so
613717683Spst			 * there is no need to build up a list of addresses
613817683Spst			 */
6139172680Smlaier			return (gen_host(dn_addr, 0, proto, dir, q.addr));
614017683Spst		} else {
614156891Sfenner#ifndef INET6
614217683Spst			alist = pcap_nametoaddr(name);
614317683Spst			if (alist == NULL || *alist == NULL)
614417683Spst				bpf_error("unknown host '%s'", name);
614526178Sfenner			tproto = proto;
6146127667Sbms			if (off_linktype == (u_int)-1 && tproto == Q_DEFAULT)
614726178Sfenner				tproto = Q_IP;
6148172680Smlaier			b = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr);
614917683Spst			while (*alist) {
615017683Spst				tmp = gen_host(**alist++, 0xffffffff,
6151172680Smlaier					       tproto, dir, q.addr);
615217683Spst				gen_or(b, tmp);
615317683Spst				b = tmp;
615417683Spst			}
615517683Spst			return b;
615656891Sfenner#else
615756891Sfenner			memset(&mask128, 0xff, sizeof(mask128));
615875110Sfenner			res0 = res = pcap_nametoaddrinfo(name);
615956891Sfenner			if (res == NULL)
616056891Sfenner				bpf_error("unknown host '%s'", name);
6161214518Srpaulo			ai = res;
616256891Sfenner			b = tmp = NULL;
616356891Sfenner			tproto = tproto6 = proto;
616456891Sfenner			if (off_linktype == -1 && tproto == Q_DEFAULT) {
616556891Sfenner				tproto = Q_IP;
616656891Sfenner				tproto6 = Q_IPV6;
616756891Sfenner			}
616857763Sfenner			for (res = res0; res; res = res->ai_next) {
616956891Sfenner				switch (res->ai_family) {
617056891Sfenner				case AF_INET:
617157763Sfenner					if (tproto == Q_IPV6)
617257763Sfenner						continue;
617357763Sfenner
6174172680Smlaier					sin4 = (struct sockaddr_in *)
617556891Sfenner						res->ai_addr;
6176172680Smlaier					tmp = gen_host(ntohl(sin4->sin_addr.s_addr),
6177172680Smlaier						0xffffffff, tproto, dir, q.addr);
617856891Sfenner					break;
617956891Sfenner				case AF_INET6:
618057763Sfenner					if (tproto6 == Q_IP)
618157763Sfenner						continue;
618257763Sfenner
618356891Sfenner					sin6 = (struct sockaddr_in6 *)
618456891Sfenner						res->ai_addr;
618556891Sfenner					tmp = gen_host6(&sin6->sin6_addr,
6186172680Smlaier						&mask128, tproto6, dir, q.addr);
618756891Sfenner					break;
618898533Sfenner				default:
618998533Sfenner					continue;
619056891Sfenner				}
619156891Sfenner				if (b)
619256891Sfenner					gen_or(b, tmp);
619356891Sfenner				b = tmp;
619456891Sfenner			}
6195214518Srpaulo			ai = NULL;
619656891Sfenner			freeaddrinfo(res0);
619757763Sfenner			if (b == NULL) {
619857763Sfenner				bpf_error("unknown host '%s'%s", name,
619957763Sfenner				    (proto == Q_DEFAULT)
620057763Sfenner					? ""
620157763Sfenner					: " for specified address family");
620257763Sfenner			}
620356891Sfenner			return b;
620456891Sfenner#endif /*INET6*/
620517683Spst		}
620617683Spst
620717683Spst	case Q_PORT:
620898533Sfenner		if (proto != Q_DEFAULT &&
620998533Sfenner		    proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
621017683Spst			bpf_error("illegal qualifier of 'port'");
621117683Spst		if (pcap_nametoport(name, &port, &real_proto) == 0)
621217683Spst			bpf_error("unknown port '%s'", name);
621317683Spst		if (proto == Q_UDP) {
621417683Spst			if (real_proto == IPPROTO_TCP)
621517683Spst				bpf_error("port '%s' is tcp", name);
621698533Sfenner			else if (real_proto == IPPROTO_SCTP)
621798533Sfenner				bpf_error("port '%s' is sctp", name);
621817683Spst			else
621917683Spst				/* override PROTO_UNDEF */
622017683Spst				real_proto = IPPROTO_UDP;
622117683Spst		}
622217683Spst		if (proto == Q_TCP) {
622317683Spst			if (real_proto == IPPROTO_UDP)
622417683Spst				bpf_error("port '%s' is udp", name);
622598533Sfenner
622698533Sfenner			else if (real_proto == IPPROTO_SCTP)
622798533Sfenner				bpf_error("port '%s' is sctp", name);
622817683Spst			else
622917683Spst				/* override PROTO_UNDEF */
623017683Spst				real_proto = IPPROTO_TCP;
623117683Spst		}
623298533Sfenner		if (proto == Q_SCTP) {
623398533Sfenner			if (real_proto == IPPROTO_UDP)
623498533Sfenner				bpf_error("port '%s' is udp", name);
623598533Sfenner
623698533Sfenner			else if (real_proto == IPPROTO_TCP)
623798533Sfenner				bpf_error("port '%s' is tcp", name);
623898533Sfenner			else
623998533Sfenner				/* override PROTO_UNDEF */
624098533Sfenner				real_proto = IPPROTO_SCTP;
624198533Sfenner		}
6242236167Sdelphij		if (port < 0)
6243236167Sdelphij			bpf_error("illegal port number %d < 0", port);
6244236167Sdelphij		if (port > 65535)
6245236167Sdelphij			bpf_error("illegal port number %d > 65535", port);
624656891Sfenner		b = gen_port(port, real_proto, dir);
624756891Sfenner		gen_or(gen_port6(port, real_proto, dir), b);
624856891Sfenner		return b;
624917683Spst
6250147897Ssam	case Q_PORTRANGE:
6251147897Ssam		if (proto != Q_DEFAULT &&
6252147897Ssam		    proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
6253147897Ssam			bpf_error("illegal qualifier of 'portrange'");
6254147897Ssam		if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0)
6255147897Ssam			bpf_error("unknown port in range '%s'", name);
6256147897Ssam		if (proto == Q_UDP) {
6257147897Ssam			if (real_proto == IPPROTO_TCP)
6258147897Ssam				bpf_error("port in range '%s' is tcp", name);
6259147897Ssam			else if (real_proto == IPPROTO_SCTP)
6260147897Ssam				bpf_error("port in range '%s' is sctp", name);
6261147897Ssam			else
6262147897Ssam				/* override PROTO_UNDEF */
6263147897Ssam				real_proto = IPPROTO_UDP;
6264147897Ssam		}
6265147897Ssam		if (proto == Q_TCP) {
6266147897Ssam			if (real_proto == IPPROTO_UDP)
6267147897Ssam				bpf_error("port in range '%s' is udp", name);
6268147897Ssam			else if (real_proto == IPPROTO_SCTP)
6269147897Ssam				bpf_error("port in range '%s' is sctp", name);
6270147897Ssam			else
6271147897Ssam				/* override PROTO_UNDEF */
6272147897Ssam				real_proto = IPPROTO_TCP;
6273147897Ssam		}
6274147897Ssam		if (proto == Q_SCTP) {
6275147897Ssam			if (real_proto == IPPROTO_UDP)
6276147897Ssam				bpf_error("port in range '%s' is udp", name);
6277147897Ssam			else if (real_proto == IPPROTO_TCP)
6278147897Ssam				bpf_error("port in range '%s' is tcp", name);
6279147897Ssam			else
6280147897Ssam				/* override PROTO_UNDEF */
6281147897Ssam				real_proto = IPPROTO_SCTP;
6282147897Ssam		}
6283236167Sdelphij		if (port1 < 0)
6284236167Sdelphij			bpf_error("illegal port number %d < 0", port1);
6285236167Sdelphij		if (port1 > 65535)
6286236167Sdelphij			bpf_error("illegal port number %d > 65535", port1);
6287236167Sdelphij		if (port2 < 0)
6288236167Sdelphij			bpf_error("illegal port number %d < 0", port2);
6289236167Sdelphij		if (port2 > 65535)
6290236167Sdelphij			bpf_error("illegal port number %d > 65535", port2);
6291236167Sdelphij
6292147897Ssam		b = gen_portrange(port1, port2, real_proto, dir);
6293147897Ssam		gen_or(gen_portrange6(port1, port2, real_proto, dir), b);
6294147897Ssam		return b;
6295147897Ssam
629617683Spst	case Q_GATEWAY:
629756891Sfenner#ifndef INET6
629817683Spst		eaddr = pcap_ether_hostton(name);
629917683Spst		if (eaddr == NULL)
630017683Spst			bpf_error("unknown ether host: %s", name);
630117683Spst
630217683Spst		alist = pcap_nametoaddr(name);
630317683Spst		if (alist == NULL || *alist == NULL)
630417683Spst			bpf_error("unknown host '%s'", name);
630598533Sfenner		b = gen_gateway(eaddr, alist, proto, dir);
630698533Sfenner		free(eaddr);
630798533Sfenner		return b;
630856891Sfenner#else
630956891Sfenner		bpf_error("'gateway' not supported in this configuration");
631056891Sfenner#endif /*INET6*/
631117683Spst
631217683Spst	case Q_PROTO:
631317683Spst		real_proto = lookup_proto(name, proto);
631417683Spst		if (real_proto >= 0)
631517683Spst			return gen_proto(real_proto, proto, dir);
631617683Spst		else
631717683Spst			bpf_error("unknown protocol: %s", name);
631817683Spst
631956891Sfenner	case Q_PROTOCHAIN:
632056891Sfenner		real_proto = lookup_proto(name, proto);
632156891Sfenner		if (real_proto >= 0)
632256891Sfenner			return gen_protochain(real_proto, proto, dir);
632356891Sfenner		else
632456891Sfenner			bpf_error("unknown protocol: %s", name);
632556891Sfenner
632617683Spst	case Q_UNDEF:
632717683Spst		syntax();
632817683Spst		/* NOTREACHED */
632917683Spst	}
633017683Spst	abort();
633117683Spst	/* NOTREACHED */
633217683Spst}
633317683Spst
633417683Spststruct block *
633517683Spstgen_mcode(s1, s2, masklen, q)
633617683Spst	register const char *s1, *s2;
633717683Spst	register int masklen;
633817683Spst	struct qual q;
633917683Spst{
634017683Spst	register int nlen, mlen;
634117683Spst	bpf_u_int32 n, m;
634217683Spst
634317683Spst	nlen = __pcap_atoin(s1, &n);
634417683Spst	/* Promote short ipaddr */
634517683Spst	n <<= 32 - nlen;
634617683Spst
634717683Spst	if (s2 != NULL) {
634817683Spst		mlen = __pcap_atoin(s2, &m);
634917683Spst		/* Promote short ipaddr */
635017683Spst		m <<= 32 - mlen;
635139294Sfenner		if ((n & ~m) != 0)
635239294Sfenner			bpf_error("non-network bits set in \"%s mask %s\"",
635339294Sfenner			    s1, s2);
635417683Spst	} else {
635517683Spst		/* Convert mask len to mask */
635617683Spst		if (masklen > 32)
635717683Spst			bpf_error("mask length must be <= 32");
6358172680Smlaier		if (masklen == 0) {
6359172680Smlaier			/*
6360172680Smlaier			 * X << 32 is not guaranteed by C to be 0; it's
6361172680Smlaier			 * undefined.
6362172680Smlaier			 */
6363172680Smlaier			m = 0;
6364172680Smlaier		} else
6365172680Smlaier			m = 0xffffffff << (32 - masklen);
636639294Sfenner		if ((n & ~m) != 0)
636739294Sfenner			bpf_error("non-network bits set in \"%s/%d\"",
636839294Sfenner			    s1, masklen);
636917683Spst	}
637017683Spst
637117683Spst	switch (q.addr) {
637217683Spst
637317683Spst	case Q_NET:
6374172680Smlaier		return gen_host(n, m, q.proto, q.dir, q.addr);
637517683Spst
637617683Spst	default:
637717683Spst		bpf_error("Mask syntax for networks only");
637817683Spst		/* NOTREACHED */
637917683Spst	}
6380146771Ssam	/* NOTREACHED */
6381172680Smlaier	return NULL;
638217683Spst}
638317683Spst
638417683Spststruct block *
638517683Spstgen_ncode(s, v, q)
638617683Spst	register const char *s;
638717683Spst	bpf_u_int32 v;
638817683Spst	struct qual q;
638917683Spst{
639017683Spst	bpf_u_int32 mask;
639117683Spst	int proto = q.proto;
639217683Spst	int dir = q.dir;
639317683Spst	register int vlen;
639417683Spst
639517683Spst	if (s == NULL)
639617683Spst		vlen = 32;
639717683Spst	else if (q.proto == Q_DECNET)
639817683Spst		vlen = __pcap_atodn(s, &v);
639917683Spst	else
640017683Spst		vlen = __pcap_atoin(s, &v);
640117683Spst
640217683Spst	switch (q.addr) {
640317683Spst
640417683Spst	case Q_DEFAULT:
640517683Spst	case Q_HOST:
640617683Spst	case Q_NET:
640717683Spst		if (proto == Q_DECNET)
6408172680Smlaier			return gen_host(v, 0, proto, dir, q.addr);
640917683Spst		else if (proto == Q_LINK) {
641017683Spst			bpf_error("illegal link layer address");
641117683Spst		} else {
641217683Spst			mask = 0xffffffff;
641317683Spst			if (s == NULL && q.addr == Q_NET) {
641417683Spst				/* Promote short net number */
641517683Spst				while (v && (v & 0xff000000) == 0) {
641617683Spst					v <<= 8;
641717683Spst					mask <<= 8;
641817683Spst				}
641917683Spst			} else {
642017683Spst				/* Promote short ipaddr */
642117683Spst				v <<= 32 - vlen;
642217683Spst				mask <<= 32 - vlen;
642317683Spst			}
6424172680Smlaier			return gen_host(v, mask, proto, dir, q.addr);
642517683Spst		}
642617683Spst
642717683Spst	case Q_PORT:
642817683Spst		if (proto == Q_UDP)
642917683Spst			proto = IPPROTO_UDP;
643017683Spst		else if (proto == Q_TCP)
643117683Spst			proto = IPPROTO_TCP;
643298533Sfenner		else if (proto == Q_SCTP)
643398533Sfenner			proto = IPPROTO_SCTP;
643417683Spst		else if (proto == Q_DEFAULT)
643517683Spst			proto = PROTO_UNDEF;
643617683Spst		else
643717683Spst			bpf_error("illegal qualifier of 'port'");
643817683Spst
6439236167Sdelphij		if (v > 65535)
6440236167Sdelphij			bpf_error("illegal port number %u > 65535", v);
6441236167Sdelphij
644256891Sfenner	    {
644356891Sfenner		struct block *b;
644456891Sfenner		b = gen_port((int)v, proto, dir);
644556891Sfenner		gen_or(gen_port6((int)v, proto, dir), b);
644656891Sfenner		return b;
644756891Sfenner	    }
644817683Spst
6449147897Ssam	case Q_PORTRANGE:
6450147897Ssam		if (proto == Q_UDP)
6451147897Ssam			proto = IPPROTO_UDP;
6452147897Ssam		else if (proto == Q_TCP)
6453147897Ssam			proto = IPPROTO_TCP;
6454147897Ssam		else if (proto == Q_SCTP)
6455147897Ssam			proto = IPPROTO_SCTP;
6456147897Ssam		else if (proto == Q_DEFAULT)
6457147897Ssam			proto = PROTO_UNDEF;
6458147897Ssam		else
6459147897Ssam			bpf_error("illegal qualifier of 'portrange'");
6460147897Ssam
6461236167Sdelphij		if (v > 65535)
6462236167Sdelphij			bpf_error("illegal port number %u > 65535", v);
6463236167Sdelphij
6464147897Ssam	    {
6465147897Ssam		struct block *b;
6466147897Ssam		b = gen_portrange((int)v, (int)v, proto, dir);
6467147897Ssam		gen_or(gen_portrange6((int)v, (int)v, proto, dir), b);
6468147897Ssam		return b;
6469147897Ssam	    }
6470147897Ssam
647117683Spst	case Q_GATEWAY:
647217683Spst		bpf_error("'gateway' requires a name");
647317683Spst		/* NOTREACHED */
647417683Spst
647517683Spst	case Q_PROTO:
647617683Spst		return gen_proto((int)v, proto, dir);
647717683Spst
647856891Sfenner	case Q_PROTOCHAIN:
647956891Sfenner		return gen_protochain((int)v, proto, dir);
648056891Sfenner
648117683Spst	case Q_UNDEF:
648217683Spst		syntax();
648317683Spst		/* NOTREACHED */
648417683Spst
648517683Spst	default:
648617683Spst		abort();
648717683Spst		/* NOTREACHED */
648817683Spst	}
648917683Spst	/* NOTREACHED */
649017683Spst}
649117683Spst
649256891Sfenner#ifdef INET6
649317683Spststruct block *
649456891Sfennergen_mcode6(s1, s2, masklen, q)
649556891Sfenner	register const char *s1, *s2;
649656891Sfenner	register int masklen;
649756891Sfenner	struct qual q;
649856891Sfenner{
649956891Sfenner	struct addrinfo *res;
650056891Sfenner	struct in6_addr *addr;
650156891Sfenner	struct in6_addr mask;
650256891Sfenner	struct block *b;
650356891Sfenner	u_int32_t *a, *m;
650456891Sfenner
650556891Sfenner	if (s2)
650656891Sfenner		bpf_error("no mask %s supported", s2);
650756891Sfenner
650875110Sfenner	res = pcap_nametoaddrinfo(s1);
650956891Sfenner	if (!res)
651056891Sfenner		bpf_error("invalid ip6 address %s", s1);
6511214518Srpaulo	ai = res;
651256891Sfenner	if (res->ai_next)
651356891Sfenner		bpf_error("%s resolved to multiple address", s1);
651456891Sfenner	addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
651556891Sfenner
651656891Sfenner	if (sizeof(mask) * 8 < masklen)
651756891Sfenner		bpf_error("mask length must be <= %u", (unsigned int)(sizeof(mask) * 8));
651898533Sfenner	memset(&mask, 0, sizeof(mask));
651956891Sfenner	memset(&mask, 0xff, masklen / 8);
652056891Sfenner	if (masklen % 8) {
652156891Sfenner		mask.s6_addr[masklen / 8] =
652256891Sfenner			(0xff << (8 - masklen % 8)) & 0xff;
652356891Sfenner	}
652456891Sfenner
652556891Sfenner	a = (u_int32_t *)addr;
652656891Sfenner	m = (u_int32_t *)&mask;
652756891Sfenner	if ((a[0] & ~m[0]) || (a[1] & ~m[1])
652856891Sfenner	 || (a[2] & ~m[2]) || (a[3] & ~m[3])) {
652956891Sfenner		bpf_error("non-network bits set in \"%s/%d\"", s1, masklen);
653056891Sfenner	}
653156891Sfenner
653256891Sfenner	switch (q.addr) {
653356891Sfenner
653456891Sfenner	case Q_DEFAULT:
653556891Sfenner	case Q_HOST:
653656891Sfenner		if (masklen != 128)
653756891Sfenner			bpf_error("Mask syntax for networks only");
653856891Sfenner		/* FALLTHROUGH */
653956891Sfenner
654056891Sfenner	case Q_NET:
6541172680Smlaier		b = gen_host6(addr, &mask, q.proto, q.dir, q.addr);
6542214518Srpaulo		ai = NULL;
654356891Sfenner		freeaddrinfo(res);
654456891Sfenner		return b;
654556891Sfenner
654656891Sfenner	default:
654756891Sfenner		bpf_error("invalid qualifier against IPv6 address");
654856891Sfenner		/* NOTREACHED */
654956891Sfenner	}
6550172680Smlaier	return NULL;
655156891Sfenner}
655256891Sfenner#endif /*INET6*/
655356891Sfenner
655456891Sfennerstruct block *
655517683Spstgen_ecode(eaddr, q)
655617683Spst	register const u_char *eaddr;
655717683Spst	struct qual q;
655817683Spst{
6559127667Sbms	struct block *b, *tmp;
6560127667Sbms
656117683Spst	if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
6562190225Srpaulo		switch (linktype) {
6563190225Srpaulo		case DLT_EN10MB:
6564236167Sdelphij		case DLT_NETANALYZER:
6565236167Sdelphij		case DLT_NETANALYZER_TRANSPARENT:
6566190225Srpaulo			return gen_ehostop(eaddr, (int)q.dir);
6567190225Srpaulo		case DLT_FDDI:
6568190225Srpaulo			return gen_fhostop(eaddr, (int)q.dir);
6569190225Srpaulo		case DLT_IEEE802:
6570190225Srpaulo			return gen_thostop(eaddr, (int)q.dir);
6571190225Srpaulo		case DLT_IEEE802_11:
6572190225Srpaulo		case DLT_PRISM_HEADER:
6573190225Srpaulo		case DLT_IEEE802_11_RADIO_AVS:
6574190225Srpaulo		case DLT_IEEE802_11_RADIO:
6575190225Srpaulo		case DLT_PPI:
6576190225Srpaulo			return gen_wlanhostop(eaddr, (int)q.dir);
6577190225Srpaulo		case DLT_SUNATM:
6578190225Srpaulo			if (is_lane) {
6579190225Srpaulo				/*
6580190225Srpaulo				 * Check that the packet doesn't begin with an
6581190225Srpaulo				 * LE Control marker.  (We've already generated
6582190225Srpaulo				 * a test for LANE.)
6583190225Srpaulo				 */
6584190225Srpaulo				tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H,
6585190225Srpaulo					0xFF00);
6586190225Srpaulo				gen_not(tmp);
6587127667Sbms
6588190225Srpaulo				/*
6589190225Srpaulo				 * Now check the MAC address.
6590190225Srpaulo				 */
6591190225Srpaulo				b = gen_ehostop(eaddr, (int)q.dir);
6592190225Srpaulo				gen_and(tmp, b);
6593190225Srpaulo				return b;
6594190225Srpaulo			}
6595190225Srpaulo			break;
6596190225Srpaulo		case DLT_IP_OVER_FC:
6597190225Srpaulo			return gen_ipfchostop(eaddr, (int)q.dir);
6598190225Srpaulo		default:
6599190225Srpaulo			bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
6600190225Srpaulo			break;
6601190225Srpaulo		}
660217683Spst	}
660317683Spst	bpf_error("ethernet address used in non-ether expression");
660417683Spst	/* NOTREACHED */
6605172680Smlaier	return NULL;
660617683Spst}
660717683Spst
660817683Spstvoid
660917683Spstsappend(s0, s1)
661017683Spst	struct slist *s0, *s1;
661117683Spst{
661217683Spst	/*
661317683Spst	 * This is definitely not the best way to do this, but the
661417683Spst	 * lists will rarely get long.
661517683Spst	 */
661617683Spst	while (s0->next)
661717683Spst		s0 = s0->next;
661817683Spst	s0->next = s1;
661917683Spst}
662017683Spst
662117683Spststatic struct slist *
662217683Spstxfer_to_x(a)
662317683Spst	struct arth *a;
662417683Spst{
662517683Spst	struct slist *s;
662617683Spst
662717683Spst	s = new_stmt(BPF_LDX|BPF_MEM);
662817683Spst	s->s.k = a->regno;
662917683Spst	return s;
663017683Spst}
663117683Spst
663217683Spststatic struct slist *
663317683Spstxfer_to_a(a)
663417683Spst	struct arth *a;
663517683Spst{
663617683Spst	struct slist *s;
663717683Spst
663817683Spst	s = new_stmt(BPF_LD|BPF_MEM);
663917683Spst	s->s.k = a->regno;
664017683Spst	return s;
664117683Spst}
664217683Spst
6643147897Ssam/*
6644147897Ssam * Modify "index" to use the value stored into its register as an
6645147897Ssam * offset relative to the beginning of the header for the protocol
6646147897Ssam * "proto", and allocate a register and put an item "size" bytes long
6647147897Ssam * (1, 2, or 4) at that offset into that register, making it the register
6648147897Ssam * for "index".
6649147897Ssam */
665017683Spststruct arth *
6651172680Smlaiergen_load(proto, inst, size)
665217683Spst	int proto;
6653172680Smlaier	struct arth *inst;
665417683Spst	int size;
665517683Spst{
665617683Spst	struct slist *s, *tmp;
665717683Spst	struct block *b;
665817683Spst	int regno = alloc_reg();
665917683Spst
6660172680Smlaier	free_reg(inst->regno);
666117683Spst	switch (size) {
666217683Spst
666317683Spst	default:
666417683Spst		bpf_error("data size must be 1, 2, or 4");
666517683Spst
666617683Spst	case 1:
666717683Spst		size = BPF_B;
666817683Spst		break;
666917683Spst
667017683Spst	case 2:
667117683Spst		size = BPF_H;
667217683Spst		break;
667317683Spst
667417683Spst	case 4:
667517683Spst		size = BPF_W;
667617683Spst		break;
667717683Spst	}
667817683Spst	switch (proto) {
667917683Spst	default:
668017683Spst		bpf_error("unsupported index operation");
668117683Spst
6682147897Ssam	case Q_RADIO:
6683147897Ssam		/*
6684147897Ssam		 * The offset is relative to the beginning of the packet
6685147897Ssam		 * data, if we have a radio header.  (If we don't, this
6686147897Ssam		 * is an error.)
6687147897Ssam		 */
6688147897Ssam		if (linktype != DLT_IEEE802_11_RADIO_AVS &&
6689147897Ssam		    linktype != DLT_IEEE802_11_RADIO &&
6690147897Ssam		    linktype != DLT_PRISM_HEADER)
6691147897Ssam			bpf_error("radio information not present in capture");
6692147897Ssam
6693147897Ssam		/*
6694147897Ssam		 * Load into the X register the offset computed into the
6695236167Sdelphij		 * register specified by "index".
6696147897Ssam		 */
6697172680Smlaier		s = xfer_to_x(inst);
6698147897Ssam
6699147897Ssam		/*
6700147897Ssam		 * Load the item at that offset.
6701147897Ssam		 */
6702147897Ssam		tmp = new_stmt(BPF_LD|BPF_IND|size);
6703147897Ssam		sappend(s, tmp);
6704172680Smlaier		sappend(inst->s, s);
6705147897Ssam		break;
6706147897Ssam
670717683Spst	case Q_LINK:
6708127667Sbms		/*
6709147897Ssam		 * The offset is relative to the beginning of
6710147897Ssam		 * the link-layer header.
6711147897Ssam		 *
6712127667Sbms		 * XXX - what about ATM LANE?  Should the index be
6713127667Sbms		 * relative to the beginning of the AAL5 frame, so
6714127667Sbms		 * that 0 refers to the beginning of the LE Control
6715127667Sbms		 * field, or relative to the beginning of the LAN
6716127667Sbms		 * frame, so that 0 refers, for Ethernet LANE, to
6717127667Sbms		 * the beginning of the destination address?
6718127667Sbms		 */
6719147897Ssam		s = gen_llprefixlen();
6720147897Ssam
6721147897Ssam		/*
6722147897Ssam		 * If "s" is non-null, it has code to arrange that the
6723147897Ssam		 * X register contains the length of the prefix preceding
6724147897Ssam		 * the link-layer header.  Add to it the offset computed
6725147897Ssam		 * into the register specified by "index", and move that
6726147897Ssam		 * into the X register.  Otherwise, just load into the X
6727236167Sdelphij		 * register the offset computed into the register specified
6728147897Ssam		 * by "index".
6729147897Ssam		 */
6730147897Ssam		if (s != NULL) {
6731172680Smlaier			sappend(s, xfer_to_a(inst));
6732147897Ssam			sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
6733147897Ssam			sappend(s, new_stmt(BPF_MISC|BPF_TAX));
6734147897Ssam		} else
6735172680Smlaier			s = xfer_to_x(inst);
6736147897Ssam
6737147897Ssam		/*
6738147897Ssam		 * Load the item at the sum of the offset we've put in the
6739147897Ssam		 * X register and the offset of the start of the link
6740147897Ssam		 * layer header (which is 0 if the radio header is
6741147897Ssam		 * variable-length; that header length is what we put
6742147897Ssam		 * into the X register and then added to the index).
6743147897Ssam		 */
674417683Spst		tmp = new_stmt(BPF_LD|BPF_IND|size);
6745147897Ssam		tmp->s.k = off_ll;
674617683Spst		sappend(s, tmp);
6747172680Smlaier		sappend(inst->s, s);
674817683Spst		break;
674917683Spst
675017683Spst	case Q_IP:
675117683Spst	case Q_ARP:
675217683Spst	case Q_RARP:
675317683Spst	case Q_ATALK:
675417683Spst	case Q_DECNET:
675517683Spst	case Q_SCA:
675617683Spst	case Q_LAT:
675717683Spst	case Q_MOPRC:
675817683Spst	case Q_MOPDL:
675956891Sfenner	case Q_IPV6:
6760147897Ssam		/*
6761147897Ssam		 * The offset is relative to the beginning of
6762147897Ssam		 * the network-layer header.
6763147897Ssam		 * XXX - are there any cases where we want
6764147897Ssam		 * off_nl_nosnap?
6765147897Ssam		 */
6766190225Srpaulo		s = gen_off_macpl();
6767147897Ssam
6768147897Ssam		/*
6769147897Ssam		 * If "s" is non-null, it has code to arrange that the
6770190225Srpaulo		 * X register contains the offset of the MAC-layer
6771190225Srpaulo		 * payload.  Add to it the offset computed into the
6772190225Srpaulo		 * register specified by "index", and move that into
6773190225Srpaulo		 * the X register.  Otherwise, just load into the X
6774236167Sdelphij		 * register the offset computed into the register specified
6775147897Ssam		 * by "index".
6776147897Ssam		 */
6777147897Ssam		if (s != NULL) {
6778172680Smlaier			sappend(s, xfer_to_a(inst));
6779147897Ssam			sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
6780147897Ssam			sappend(s, new_stmt(BPF_MISC|BPF_TAX));
6781147897Ssam		} else
6782172680Smlaier			s = xfer_to_x(inst);
6783147897Ssam
6784147897Ssam		/*
6785147897Ssam		 * Load the item at the sum of the offset we've put in the
6786172680Smlaier		 * X register, the offset of the start of the network
6787190225Srpaulo		 * layer header from the beginning of the MAC-layer
6788190225Srpaulo		 * payload, and the purported offset of the start of the
6789190225Srpaulo		 * MAC-layer payload (which might be 0 if there's a
6790190225Srpaulo		 * variable-length prefix before the link-layer header
6791190225Srpaulo		 * or the link-layer header itself is variable-length;
6792190225Srpaulo		 * the variable-length offset of the start of the
6793190225Srpaulo		 * MAC-layer payload is what we put into the X register
6794190225Srpaulo		 * and then added to the index).
6795147897Ssam		 */
679617683Spst		tmp = new_stmt(BPF_LD|BPF_IND|size);
6797190225Srpaulo		tmp->s.k = off_macpl + off_nl;
679817683Spst		sappend(s, tmp);
6799172680Smlaier		sappend(inst->s, s);
680017683Spst
6801147897Ssam		/*
6802147897Ssam		 * Do the computation only if the packet contains
6803147897Ssam		 * the protocol in question.
6804147897Ssam		 */
680517683Spst		b = gen_proto_abbrev(proto);
6806172680Smlaier		if (inst->b)
6807172680Smlaier			gen_and(inst->b, b);
6808172680Smlaier		inst->b = b;
680917683Spst		break;
681017683Spst
681198533Sfenner	case Q_SCTP:
681217683Spst	case Q_TCP:
681317683Spst	case Q_UDP:
681417683Spst	case Q_ICMP:
681517683Spst	case Q_IGMP:
681617683Spst	case Q_IGRP:
681756891Sfenner	case Q_PIM:
681898533Sfenner	case Q_VRRP:
6819236167Sdelphij	case Q_CARP:
6820147897Ssam		/*
6821147897Ssam		 * The offset is relative to the beginning of
6822147897Ssam		 * the transport-layer header.
6823172680Smlaier		 *
6824172680Smlaier		 * Load the X register with the length of the IPv4 header
6825172680Smlaier		 * (plus the offset of the link-layer header, if it's
6826172680Smlaier		 * a variable-length header), in bytes.
6827172680Smlaier		 *
6828147897Ssam		 * XXX - are there any cases where we want
6829147897Ssam		 * off_nl_nosnap?
6830147897Ssam		 * XXX - we should, if we're built with
6831147897Ssam		 * IPv6 support, generate code to load either
6832147897Ssam		 * IPv4, IPv6, or both, as appropriate.
6833147897Ssam		 */
6834147897Ssam		s = gen_loadx_iphdrlen();
6835147897Ssam
6836147897Ssam		/*
6837172680Smlaier		 * The X register now contains the sum of the length
6838172680Smlaier		 * of any variable-length header preceding the link-layer
6839190225Srpaulo		 * header, any variable-length link-layer header, and the
6840190225Srpaulo		 * length of the network-layer header.
6841190225Srpaulo		 *
6842172680Smlaier		 * Load into the A register the offset relative to
6843147897Ssam		 * the beginning of the transport layer header,
6844147897Ssam		 * add the X register to that, move that to the
6845147897Ssam		 * X register, and load with an offset from the
6846147897Ssam		 * X register equal to the offset of the network
6847147897Ssam		 * layer header relative to the beginning of
6848190225Srpaulo		 * the MAC-layer payload plus the fixed-length
6849190225Srpaulo		 * portion of the offset of the MAC-layer payload
6850190225Srpaulo		 * from the beginning of the raw packet data.
6851147897Ssam		 */
6852172680Smlaier		sappend(s, xfer_to_a(inst));
685317683Spst		sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
685417683Spst		sappend(s, new_stmt(BPF_MISC|BPF_TAX));
685517683Spst		sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size));
6856190225Srpaulo		tmp->s.k = off_macpl + off_nl;
6857172680Smlaier		sappend(inst->s, s);
685817683Spst
6859147897Ssam		/*
6860147897Ssam		 * Do the computation only if the packet contains
6861147897Ssam		 * the protocol in question - which is true only
6862147897Ssam		 * if this is an IP datagram and is the first or
6863147897Ssam		 * only fragment of that datagram.
6864147897Ssam		 */
686517683Spst		gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
6866172680Smlaier		if (inst->b)
6867172680Smlaier			gen_and(inst->b, b);
686856891Sfenner		gen_and(gen_proto_abbrev(Q_IP), b);
6869172680Smlaier		inst->b = b;
687017683Spst		break;
687156891Sfenner	case Q_ICMPV6:
687256891Sfenner		bpf_error("IPv6 upper-layer protocol is not supported by proto[x]");
687356891Sfenner		/*NOTREACHED*/
687417683Spst	}
6875172680Smlaier	inst->regno = regno;
687617683Spst	s = new_stmt(BPF_ST);
687717683Spst	s->s.k = regno;
6878172680Smlaier	sappend(inst->s, s);
687917683Spst
6880172680Smlaier	return inst;
688117683Spst}
688217683Spst
688317683Spststruct block *
688417683Spstgen_relation(code, a0, a1, reversed)
688517683Spst	int code;
688617683Spst	struct arth *a0, *a1;
688717683Spst	int reversed;
688817683Spst{
688917683Spst	struct slist *s0, *s1, *s2;
689017683Spst	struct block *b, *tmp;
689117683Spst
689217683Spst	s0 = xfer_to_x(a1);
689317683Spst	s1 = xfer_to_a(a0);
6894127667Sbms	if (code == BPF_JEQ) {
6895127667Sbms		s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X);
6896127667Sbms		b = new_block(JMP(code));
6897127667Sbms		sappend(s1, s2);
689817683Spst	}
6899127667Sbms	else
6900127667Sbms		b = new_block(BPF_JMP|code|BPF_X);
690117683Spst	if (reversed)
690217683Spst		gen_not(b);
690317683Spst
690417683Spst	sappend(s0, s1);
690517683Spst	sappend(a1->s, s0);
690617683Spst	sappend(a0->s, a1->s);
690717683Spst
690817683Spst	b->stmts = a0->s;
690917683Spst
691017683Spst	free_reg(a0->regno);
691117683Spst	free_reg(a1->regno);
691217683Spst
691317683Spst	/* 'and' together protocol checks */
691417683Spst	if (a0->b) {
691517683Spst		if (a1->b) {
691617683Spst			gen_and(a0->b, tmp = a1->b);
691717683Spst		}
691817683Spst		else
691917683Spst			tmp = a0->b;
692017683Spst	} else
692117683Spst		tmp = a1->b;
692217683Spst
692317683Spst	if (tmp)
692417683Spst		gen_and(tmp, b);
692517683Spst
692617683Spst	return b;
692717683Spst}
692817683Spst
692917683Spststruct arth *
693017683Spstgen_loadlen()
693117683Spst{
693217683Spst	int regno = alloc_reg();
693317683Spst	struct arth *a = (struct arth *)newchunk(sizeof(*a));
693417683Spst	struct slist *s;
693517683Spst
693617683Spst	s = new_stmt(BPF_LD|BPF_LEN);
693717683Spst	s->next = new_stmt(BPF_ST);
693817683Spst	s->next->s.k = regno;
693917683Spst	a->s = s;
694017683Spst	a->regno = regno;
694117683Spst
694217683Spst	return a;
694317683Spst}
694417683Spst
694517683Spststruct arth *
694617683Spstgen_loadi(val)
694717683Spst	int val;
694817683Spst{
694917683Spst	struct arth *a;
695017683Spst	struct slist *s;
695117683Spst	int reg;
695217683Spst
695317683Spst	a = (struct arth *)newchunk(sizeof(*a));
695417683Spst
695517683Spst	reg = alloc_reg();
695617683Spst
695717683Spst	s = new_stmt(BPF_LD|BPF_IMM);
695817683Spst	s->s.k = val;
695917683Spst	s->next = new_stmt(BPF_ST);
696017683Spst	s->next->s.k = reg;
696117683Spst	a->s = s;
696217683Spst	a->regno = reg;
696317683Spst
696417683Spst	return a;
696517683Spst}
696617683Spst
696717683Spststruct arth *
696817683Spstgen_neg(a)
696917683Spst	struct arth *a;
697017683Spst{
697117683Spst	struct slist *s;
697217683Spst
697317683Spst	s = xfer_to_a(a);
697417683Spst	sappend(a->s, s);
697517683Spst	s = new_stmt(BPF_ALU|BPF_NEG);
697617683Spst	s->s.k = 0;
697717683Spst	sappend(a->s, s);
697817683Spst	s = new_stmt(BPF_ST);
697917683Spst	s->s.k = a->regno;
698017683Spst	sappend(a->s, s);
698117683Spst
698217683Spst	return a;
698317683Spst}
698417683Spst
698517683Spststruct arth *
698617683Spstgen_arth(code, a0, a1)
698717683Spst	int code;
698817683Spst	struct arth *a0, *a1;
698917683Spst{
699017683Spst	struct slist *s0, *s1, *s2;
699117683Spst
699217683Spst	s0 = xfer_to_x(a1);
699317683Spst	s1 = xfer_to_a(a0);
699417683Spst	s2 = new_stmt(BPF_ALU|BPF_X|code);
699517683Spst
699617683Spst	sappend(s1, s2);
699717683Spst	sappend(s0, s1);
699817683Spst	sappend(a1->s, s0);
699917683Spst	sappend(a0->s, a1->s);
700017683Spst
7001127667Sbms	free_reg(a0->regno);
700217683Spst	free_reg(a1->regno);
700317683Spst
700417683Spst	s0 = new_stmt(BPF_ST);
700517683Spst	a0->regno = s0->s.k = alloc_reg();
700617683Spst	sappend(a0->s, s0);
700717683Spst
700817683Spst	return a0;
700917683Spst}
701017683Spst
701117683Spst/*
701217683Spst * Here we handle simple allocation of the scratch registers.
701317683Spst * If too many registers are alloc'd, the allocator punts.
701417683Spst */
701517683Spststatic int regused[BPF_MEMWORDS];
701617683Spststatic int curreg;
701717683Spst
701817683Spst/*
7019190225Srpaulo * Initialize the table of used registers and the current register.
7020190225Srpaulo */
7021190225Srpaulostatic void
7022190225Srpauloinit_regs()
7023190225Srpaulo{
7024190225Srpaulo	curreg = 0;
7025190225Srpaulo	memset(regused, 0, sizeof regused);
7026190225Srpaulo}
7027190225Srpaulo
7028190225Srpaulo/*
702917683Spst * Return the next free register.
703017683Spst */
703117683Spststatic int
703217683Spstalloc_reg()
703317683Spst{
703417683Spst	int n = BPF_MEMWORDS;
703517683Spst
703617683Spst	while (--n >= 0) {
703717683Spst		if (regused[curreg])
703817683Spst			curreg = (curreg + 1) % BPF_MEMWORDS;
703917683Spst		else {
704017683Spst			regused[curreg] = 1;
704117683Spst			return curreg;
704217683Spst		}
704317683Spst	}
704417683Spst	bpf_error("too many registers needed to evaluate expression");
704517683Spst	/* NOTREACHED */
7046172680Smlaier	return 0;
704717683Spst}
704817683Spst
704917683Spst/*
705017683Spst * Return a register to the table so it can
705117683Spst * be used later.
705217683Spst */
705317683Spststatic void
705417683Spstfree_reg(n)
705517683Spst	int n;
705617683Spst{
705717683Spst	regused[n] = 0;
705817683Spst}
705917683Spst
706017683Spststatic struct block *
706117683Spstgen_len(jmp, n)
706217683Spst	int jmp, n;
706317683Spst{
706417683Spst	struct slist *s;
706517683Spst	struct block *b;
706617683Spst
706717683Spst	s = new_stmt(BPF_LD|BPF_LEN);
706817683Spst	b = new_block(JMP(jmp));
706917683Spst	b->stmts = s;
707017683Spst	b->s.k = n;
707117683Spst
707217683Spst	return b;
707317683Spst}
707417683Spst
707517683Spststruct block *
707617683Spstgen_greater(n)
707717683Spst	int n;
707817683Spst{
707917683Spst	return gen_len(BPF_JGE, n);
708017683Spst}
708117683Spst
708217749Spst/*
708317749Spst * Actually, this is less than or equal.
708417749Spst */
708517683Spststruct block *
708617683Spstgen_less(n)
708717683Spst	int n;
708817683Spst{
708917683Spst	struct block *b;
709017683Spst
709117683Spst	b = gen_len(BPF_JGT, n);
709217683Spst	gen_not(b);
709317683Spst
709417683Spst	return b;
709517683Spst}
709617683Spst
7097147897Ssam/*
7098147897Ssam * This is for "byte {idx} {op} {val}"; "idx" is treated as relative to
7099147897Ssam * the beginning of the link-layer header.
7100147897Ssam * XXX - that means you can't test values in the radiotap header, but
7101147897Ssam * as that header is difficult if not impossible to parse generally
7102147897Ssam * without a loop, that might not be a severe problem.  A new keyword
7103147897Ssam * "radio" could be added for that, although what you'd really want
7104147897Ssam * would be a way of testing particular radio header values, which
7105147897Ssam * would generate code appropriate to the radio header in question.
7106147897Ssam */
710717683Spststruct block *
710817683Spstgen_byteop(op, idx, val)
710917683Spst	int op, idx, val;
711017683Spst{
711117683Spst	struct block *b;
711217683Spst	struct slist *s;
711317683Spst
711417683Spst	switch (op) {
711517683Spst	default:
711617683Spst		abort();
711717683Spst
711817683Spst	case '=':
7119147897Ssam		return gen_cmp(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val);
712017683Spst
712117683Spst	case '<':
7122147897Ssam		b = gen_cmp_lt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val);
712317683Spst		return b;
712417683Spst
712517683Spst	case '>':
7126147897Ssam		b = gen_cmp_gt(OR_LINK, (u_int)idx, BPF_B, (bpf_int32)val);
712717683Spst		return b;
712817683Spst
712917683Spst	case '|':
713017683Spst		s = new_stmt(BPF_ALU|BPF_OR|BPF_K);
713117683Spst		break;
713217683Spst
713317683Spst	case '&':
713417683Spst		s = new_stmt(BPF_ALU|BPF_AND|BPF_K);
713517683Spst		break;
713617683Spst	}
713717683Spst	s->s.k = val;
713817683Spst	b = new_block(JMP(BPF_JEQ));
713917683Spst	b->stmts = s;
714017683Spst	gen_not(b);
714117683Spst
714217683Spst	return b;
714317683Spst}
714417683Spst
714598533Sfennerstatic u_char abroadcast[] = { 0x0 };
714698533Sfenner
714717683Spststruct block *
714817683Spstgen_broadcast(proto)
714917683Spst	int proto;
715017683Spst{
715117683Spst	bpf_u_int32 hostmask;
715217683Spst	struct block *b0, *b1, *b2;
715317683Spst	static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
715417683Spst
715517683Spst	switch (proto) {
715617683Spst
715717683Spst	case Q_DEFAULT:
715817683Spst	case Q_LINK:
7159190225Srpaulo		switch (linktype) {
7160190225Srpaulo		case DLT_ARCNET:
7161190225Srpaulo		case DLT_ARCNET_LINUX:
7162190225Srpaulo			return gen_ahostop(abroadcast, Q_DST);
7163190225Srpaulo		case DLT_EN10MB:
7164236167Sdelphij		case DLT_NETANALYZER:
7165236167Sdelphij		case DLT_NETANALYZER_TRANSPARENT:
7166190225Srpaulo			return gen_ehostop(ebroadcast, Q_DST);
7167190225Srpaulo		case DLT_FDDI:
7168190225Srpaulo			return gen_fhostop(ebroadcast, Q_DST);
7169190225Srpaulo		case DLT_IEEE802:
7170190225Srpaulo			return gen_thostop(ebroadcast, Q_DST);
7171190225Srpaulo		case DLT_IEEE802_11:
7172190225Srpaulo		case DLT_PRISM_HEADER:
7173190225Srpaulo		case DLT_IEEE802_11_RADIO_AVS:
7174190225Srpaulo		case DLT_IEEE802_11_RADIO:
7175190225Srpaulo		case DLT_PPI:
7176190225Srpaulo			return gen_wlanhostop(ebroadcast, Q_DST);
7177190225Srpaulo		case DLT_IP_OVER_FC:
7178190225Srpaulo			return gen_ipfchostop(ebroadcast, Q_DST);
7179190225Srpaulo		case DLT_SUNATM:
7180190225Srpaulo			if (is_lane) {
7181190225Srpaulo				/*
7182190225Srpaulo				 * Check that the packet doesn't begin with an
7183190225Srpaulo				 * LE Control marker.  (We've already generated
7184190225Srpaulo				 * a test for LANE.)
7185190225Srpaulo				 */
7186190225Srpaulo				b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
7187190225Srpaulo				    BPF_H, 0xFF00);
7188190225Srpaulo				gen_not(b1);
7189127667Sbms
7190190225Srpaulo				/*
7191190225Srpaulo				 * Now check the MAC address.
7192190225Srpaulo				 */
7193190225Srpaulo				b0 = gen_ehostop(ebroadcast, Q_DST);
7194190225Srpaulo				gen_and(b1, b0);
7195190225Srpaulo				return b0;
7196190225Srpaulo			}
7197190225Srpaulo			break;
7198190225Srpaulo		default:
7199190225Srpaulo			bpf_error("not a broadcast link");
7200190225Srpaulo		}
720117683Spst		break;
720217683Spst
720317683Spst	case Q_IP:
7204214518Srpaulo		/*
7205214518Srpaulo		 * We treat a netmask of PCAP_NETMASK_UNKNOWN (0xffffffff)
7206214518Srpaulo		 * as an indication that we don't know the netmask, and fail
7207214518Srpaulo		 * in that case.
7208214518Srpaulo		 */
7209214518Srpaulo		if (netmask == PCAP_NETMASK_UNKNOWN)
7210214518Srpaulo			bpf_error("netmask not known, so 'ip broadcast' not supported");
721117683Spst		b0 = gen_linktype(ETHERTYPE_IP);
721217683Spst		hostmask = ~netmask;
7213147897Ssam		b1 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32)0, hostmask);
7214147897Ssam		b2 = gen_mcmp(OR_NET, 16, BPF_W,
721517683Spst			      (bpf_int32)(~0 & hostmask), hostmask);
721617683Spst		gen_or(b1, b2);
721717683Spst		gen_and(b0, b2);
721817683Spst		return b2;
721917683Spst	}
7220127667Sbms	bpf_error("only link-layer/IP broadcast filters supported");
7221146771Ssam	/* NOTREACHED */
7222172680Smlaier	return NULL;
722317683Spst}
722417683Spst
7225127667Sbms/*
7226127667Sbms * Generate code to test the low-order bit of a MAC address (that's
7227127667Sbms * the bottom bit of the *first* byte).
7228127667Sbms */
7229127667Sbmsstatic struct block *
7230127667Sbmsgen_mac_multicast(offset)
7231127667Sbms	int offset;
7232127667Sbms{
7233127667Sbms	register struct block *b0;
7234127667Sbms	register struct slist *s;
7235127667Sbms
7236127667Sbms	/* link[offset] & 1 != 0 */
7237147897Ssam	s = gen_load_a(OR_LINK, offset, BPF_B);
7238127667Sbms	b0 = new_block(JMP(BPF_JSET));
7239127667Sbms	b0->s.k = 1;
7240127667Sbms	b0->stmts = s;
7241127667Sbms	return b0;
7242127667Sbms}
7243127667Sbms
724417683Spststruct block *
724517683Spstgen_multicast(proto)
724617683Spst	int proto;
724717683Spst{
7248127667Sbms	register struct block *b0, *b1, *b2;
724917683Spst	register struct slist *s;
725017683Spst
725117683Spst	switch (proto) {
725217683Spst
725317683Spst	case Q_DEFAULT:
725417683Spst	case Q_LINK:
7255190225Srpaulo		switch (linktype) {
7256190225Srpaulo		case DLT_ARCNET:
7257190225Srpaulo		case DLT_ARCNET_LINUX:
7258190225Srpaulo			/* all ARCnet multicasts use the same address */
7259190225Srpaulo			return gen_ahostop(abroadcast, Q_DST);
7260190225Srpaulo		case DLT_EN10MB:
7261236167Sdelphij		case DLT_NETANALYZER:
7262236167Sdelphij		case DLT_NETANALYZER_TRANSPARENT:
7263190225Srpaulo			/* ether[0] & 1 != 0 */
7264190225Srpaulo			return gen_mac_multicast(0);
7265190225Srpaulo		case DLT_FDDI:
7266127667Sbms			/*
7267190225Srpaulo			 * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX
7268190225Srpaulo			 *
7269190225Srpaulo			 * XXX - was that referring to bit-order issues?
7270127667Sbms			 */
7271190225Srpaulo			/* fddi[1] & 1 != 0 */
7272190225Srpaulo			return gen_mac_multicast(1);
7273190225Srpaulo		case DLT_IEEE802:
7274190225Srpaulo			/* tr[2] & 1 != 0 */
7275190225Srpaulo			return gen_mac_multicast(2);
7276190225Srpaulo		case DLT_IEEE802_11:
7277190225Srpaulo		case DLT_PRISM_HEADER:
7278190225Srpaulo		case DLT_IEEE802_11_RADIO_AVS:
7279190225Srpaulo		case DLT_IEEE802_11_RADIO:
7280190225Srpaulo		case DLT_PPI:
7281190225Srpaulo			/*
7282190225Srpaulo			 * Oh, yuk.
7283190225Srpaulo			 *
7284190225Srpaulo			 *	For control frames, there is no DA.
7285190225Srpaulo			 *
7286190225Srpaulo			 *	For management frames, DA is at an
7287190225Srpaulo			 *	offset of 4 from the beginning of
7288190225Srpaulo			 *	the packet.
7289190225Srpaulo			 *
7290190225Srpaulo			 *	For data frames, DA is at an offset
7291190225Srpaulo			 *	of 4 from the beginning of the packet
7292190225Srpaulo			 *	if To DS is clear and at an offset of
7293190225Srpaulo			 *	16 from the beginning of the packet
7294190225Srpaulo			 *	if To DS is set.
7295190225Srpaulo			 */
7296190225Srpaulo
7297190225Srpaulo			/*
7298190225Srpaulo			 * Generate the tests to be done for data frames.
7299190225Srpaulo			 *
7300190225Srpaulo			 * First, check for To DS set, i.e. "link[1] & 0x01".
7301190225Srpaulo			 */
7302190225Srpaulo			s = gen_load_a(OR_LINK, 1, BPF_B);
7303190225Srpaulo			b1 = new_block(JMP(BPF_JSET));
7304190225Srpaulo			b1->s.k = 0x01;	/* To DS */
7305190225Srpaulo			b1->stmts = s;
7306190225Srpaulo
7307190225Srpaulo			/*
7308190225Srpaulo			 * If To DS is set, the DA is at 16.
7309190225Srpaulo			 */
7310190225Srpaulo			b0 = gen_mac_multicast(16);
7311190225Srpaulo			gen_and(b1, b0);
7312190225Srpaulo
7313190225Srpaulo			/*
7314190225Srpaulo			 * Now, check for To DS not set, i.e. check
7315190225Srpaulo			 * "!(link[1] & 0x01)".
7316190225Srpaulo			 */
7317190225Srpaulo			s = gen_load_a(OR_LINK, 1, BPF_B);
7318190225Srpaulo			b2 = new_block(JMP(BPF_JSET));
7319190225Srpaulo			b2->s.k = 0x01;	/* To DS */
7320190225Srpaulo			b2->stmts = s;
7321190225Srpaulo			gen_not(b2);
7322190225Srpaulo
7323190225Srpaulo			/*
7324190225Srpaulo			 * If To DS is not set, the DA is at 4.
7325190225Srpaulo			 */
7326190225Srpaulo			b1 = gen_mac_multicast(4);
7327190225Srpaulo			gen_and(b2, b1);
7328190225Srpaulo
7329190225Srpaulo			/*
7330190225Srpaulo			 * Now OR together the last two checks.  That gives
7331190225Srpaulo			 * the complete set of checks for data frames.
7332190225Srpaulo			 */
7333190225Srpaulo			gen_or(b1, b0);
7334190225Srpaulo
7335190225Srpaulo			/*
7336190225Srpaulo			 * Now check for a data frame.
7337190225Srpaulo			 * I.e, check "link[0] & 0x08".
7338190225Srpaulo			 */
7339190225Srpaulo			s = gen_load_a(OR_LINK, 0, BPF_B);
7340190225Srpaulo			b1 = new_block(JMP(BPF_JSET));
7341190225Srpaulo			b1->s.k = 0x08;
7342190225Srpaulo			b1->stmts = s;
7343190225Srpaulo
7344190225Srpaulo			/*
7345190225Srpaulo			 * AND that with the checks done for data frames.
7346190225Srpaulo			 */
7347190225Srpaulo			gen_and(b1, b0);
7348190225Srpaulo
7349190225Srpaulo			/*
7350190225Srpaulo			 * If the high-order bit of the type value is 0, this
7351190225Srpaulo			 * is a management frame.
7352190225Srpaulo			 * I.e, check "!(link[0] & 0x08)".
7353190225Srpaulo			 */
7354190225Srpaulo			s = gen_load_a(OR_LINK, 0, BPF_B);
7355190225Srpaulo			b2 = new_block(JMP(BPF_JSET));
7356190225Srpaulo			b2->s.k = 0x08;
7357190225Srpaulo			b2->stmts = s;
7358190225Srpaulo			gen_not(b2);
7359190225Srpaulo
7360190225Srpaulo			/*
7361190225Srpaulo			 * For management frames, the DA is at 4.
7362190225Srpaulo			 */
7363190225Srpaulo			b1 = gen_mac_multicast(4);
7364190225Srpaulo			gen_and(b2, b1);
7365190225Srpaulo
7366190225Srpaulo			/*
7367190225Srpaulo			 * OR that with the checks done for data frames.
7368190225Srpaulo			 * That gives the checks done for management and
7369190225Srpaulo			 * data frames.
7370190225Srpaulo			 */
7371190225Srpaulo			gen_or(b1, b0);
7372190225Srpaulo
7373190225Srpaulo			/*
7374190225Srpaulo			 * If the low-order bit of the type value is 1,
7375190225Srpaulo			 * this is either a control frame or a frame
7376190225Srpaulo			 * with a reserved type, and thus not a
7377190225Srpaulo			 * frame with an SA.
7378190225Srpaulo			 *
7379190225Srpaulo			 * I.e., check "!(link[0] & 0x04)".
7380190225Srpaulo			 */
7381190225Srpaulo			s = gen_load_a(OR_LINK, 0, BPF_B);
7382190225Srpaulo			b1 = new_block(JMP(BPF_JSET));
7383190225Srpaulo			b1->s.k = 0x04;
7384190225Srpaulo			b1->stmts = s;
7385127667Sbms			gen_not(b1);
7386127667Sbms
7387190225Srpaulo			/*
7388190225Srpaulo			 * AND that with the checks for data and management
7389190225Srpaulo			 * frames.
7390190225Srpaulo			 */
7391127667Sbms			gen_and(b1, b0);
7392127667Sbms			return b0;
7393190225Srpaulo		case DLT_IP_OVER_FC:
7394190225Srpaulo			b0 = gen_mac_multicast(2);
7395190225Srpaulo			return b0;
7396190225Srpaulo		case DLT_SUNATM:
7397190225Srpaulo			if (is_lane) {
7398190225Srpaulo				/*
7399190225Srpaulo				 * Check that the packet doesn't begin with an
7400190225Srpaulo				 * LE Control marker.  (We've already generated
7401190225Srpaulo				 * a test for LANE.)
7402190225Srpaulo				 */
7403190225Srpaulo				b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS,
7404190225Srpaulo				    BPF_H, 0xFF00);
7405190225Srpaulo				gen_not(b1);
7406127667Sbms
7407190225Srpaulo				/* ether[off_mac] & 1 != 0 */
7408190225Srpaulo				b0 = gen_mac_multicast(off_mac);
7409190225Srpaulo				gen_and(b1, b0);
7410190225Srpaulo				return b0;
7411190225Srpaulo			}
7412190225Srpaulo			break;
7413190225Srpaulo		default:
7414190225Srpaulo			break;
7415190225Srpaulo		}
7416190225Srpaulo		/* Link not known to support multicasts */
7417190225Srpaulo		break;
7418190225Srpaulo
741917683Spst	case Q_IP:
742017683Spst		b0 = gen_linktype(ETHERTYPE_IP);
7421147897Ssam		b1 = gen_cmp_ge(OR_NET, 16, BPF_B, (bpf_int32)224);
742217683Spst		gen_and(b0, b1);
742317683Spst		return b1;
742456891Sfenner
742556891Sfenner	case Q_IPV6:
742656891Sfenner		b0 = gen_linktype(ETHERTYPE_IPV6);
7427147897Ssam		b1 = gen_cmp(OR_NET, 24, BPF_B, (bpf_int32)255);
742856891Sfenner		gen_and(b0, b1);
742956891Sfenner		return b1;
743017683Spst	}
7431127667Sbms	bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
7432146771Ssam	/* NOTREACHED */
7433172680Smlaier	return NULL;
743417683Spst}
743517683Spst
743617683Spst/*
7437242484Sdelphij * Filter on inbound (dir == 0) or outbound (dir == 1) traffic.
7438242484Sdelphij * Outbound traffic is sent by this machine, while inbound traffic is
7439242484Sdelphij * sent by a remote machine (and may include packets destined for a
7440242484Sdelphij * unicast or multicast link-layer address we are not subscribing to).
7441242484Sdelphij * These are the same definitions implemented by pcap_setdirection().
7442242484Sdelphij * Capturing only unicast traffic destined for this host is probably
7443242484Sdelphij * better accomplished using a higher-layer filter.
744417683Spst */
744517683Spststruct block *
744617683Spstgen_inbound(dir)
744717683Spst	int dir;
744817683Spst{
744917683Spst	register struct block *b0;
745017683Spst
745175110Sfenner	/*
745275110Sfenner	 * Only some data link types support inbound/outbound qualifiers.
745375110Sfenner	 */
745475110Sfenner	switch (linktype) {
745575110Sfenner	case DLT_SLIP:
745675110Sfenner		b0 = gen_relation(BPF_JEQ,
745717683Spst			  gen_load(Q_LINK, gen_loadi(0), 1),
745817683Spst			  gen_loadi(0),
745917683Spst			  dir);
746075110Sfenner		break;
746175110Sfenner
7462214518Srpaulo	case DLT_IPNET:
7463214518Srpaulo		if (dir) {
7464214518Srpaulo			/* match outgoing packets */
7465214518Srpaulo			b0 = gen_cmp(OR_LINK, 2, BPF_H, IPNET_OUTBOUND);
7466214518Srpaulo		} else {
7467214518Srpaulo			/* match incoming packets */
7468214518Srpaulo			b0 = gen_cmp(OR_LINK, 2, BPF_H, IPNET_INBOUND);
7469214518Srpaulo		}
7470214518Srpaulo		break;
7471214518Srpaulo
7472127667Sbms	case DLT_LINUX_SLL:
7473242484Sdelphij		/* match outgoing packets */
7474242484Sdelphij		b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING);
7475242484Sdelphij		if (!dir) {
7476242484Sdelphij			/* to filter on inbound traffic, invert the match */
7477242484Sdelphij			gen_not(b0);
7478127667Sbms		}
7479127667Sbms		break;
7480127667Sbms
7481172680Smlaier#ifdef HAVE_NET_PFVAR_H
7482127667Sbms	case DLT_PFLOG:
7483147897Ssam		b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, dir), BPF_B,
7484127667Sbms		    (bpf_int32)((dir == 0) ? PF_IN : PF_OUT));
7485127667Sbms		break;
7486172680Smlaier#endif
7487127667Sbms
7488146771Ssam	case DLT_PPP_PPPD:
7489146771Ssam		if (dir) {
7490146771Ssam			/* match outgoing packets */
7491147897Ssam			b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_OUT);
7492146771Ssam		} else {
7493146771Ssam			/* match incoming packets */
7494147897Ssam			b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_IN);
7495146771Ssam		}
7496146771Ssam		break;
7497146771Ssam
7498162015Ssam        case DLT_JUNIPER_MFR:
7499146771Ssam        case DLT_JUNIPER_MLFR:
7500146771Ssam        case DLT_JUNIPER_MLPPP:
7501146771Ssam	case DLT_JUNIPER_ATM1:
7502146771Ssam	case DLT_JUNIPER_ATM2:
7503147897Ssam	case DLT_JUNIPER_PPPOE:
7504147897Ssam	case DLT_JUNIPER_PPPOE_ATM:
7505147897Ssam        case DLT_JUNIPER_GGSN:
7506147897Ssam        case DLT_JUNIPER_ES:
7507147897Ssam        case DLT_JUNIPER_MONITOR:
7508147897Ssam        case DLT_JUNIPER_SERVICES:
7509162015Ssam        case DLT_JUNIPER_ETHER:
7510162015Ssam        case DLT_JUNIPER_PPP:
7511162015Ssam        case DLT_JUNIPER_FRELAY:
7512162015Ssam        case DLT_JUNIPER_CHDLC:
7513172680Smlaier        case DLT_JUNIPER_VP:
7514190225Srpaulo        case DLT_JUNIPER_ST:
7515190225Srpaulo        case DLT_JUNIPER_ISM:
7516236167Sdelphij        case DLT_JUNIPER_VS:
7517236167Sdelphij        case DLT_JUNIPER_SRX_E2E:
7518236167Sdelphij        case DLT_JUNIPER_FIBRECHANNEL:
7519236167Sdelphij	case DLT_JUNIPER_ATM_CEMIC:
7520236167Sdelphij
7521146771Ssam		/* juniper flags (including direction) are stored
7522146771Ssam		 * the byte after the 3-byte magic number */
7523146771Ssam		if (dir) {
7524146771Ssam			/* match outgoing packets */
7525147897Ssam			b0 = gen_mcmp(OR_LINK, 3, BPF_B, 0, 0x01);
7526146771Ssam		} else {
7527146771Ssam			/* match incoming packets */
7528147897Ssam			b0 = gen_mcmp(OR_LINK, 3, BPF_B, 1, 0x01);
7529146771Ssam		}
7530190225Srpaulo		break;
7531146771Ssam
753275110Sfenner	default:
7533242484Sdelphij		/*
7534242484Sdelphij		 * If we have packet meta-data indicating a direction,
7535242484Sdelphij		 * check it, otherwise give up as this link-layer type
7536242484Sdelphij		 * has nothing in the packet data.
7537242484Sdelphij		 */
7538242484Sdelphij#if defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
7539242484Sdelphij		/*
7540242484Sdelphij		 * We infer that this is Linux with PF_PACKET support.
7541242484Sdelphij		 * If this is a *live* capture, we can look at
7542242484Sdelphij		 * special meta-data in the filter expression;
7543242484Sdelphij		 * if it's a savefile, we can't.
7544242484Sdelphij		 */
7545242484Sdelphij		if (bpf_pcap->sf.rfile != NULL) {
7546242484Sdelphij			/* We have a FILE *, so this is a savefile */
7547242484Sdelphij			bpf_error("inbound/outbound not supported on linktype %d when reading savefiles",
7548242484Sdelphij			    linktype);
7549242484Sdelphij			b0 = NULL;
7550242484Sdelphij			/* NOTREACHED */
7551242484Sdelphij		}
7552242484Sdelphij		/* match outgoing packets */
7553242484Sdelphij		b0 = gen_cmp(OR_LINK, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H,
7554242484Sdelphij		             PACKET_OUTGOING);
7555242484Sdelphij		if (!dir) {
7556242484Sdelphij			/* to filter on inbound traffic, invert the match */
7557242484Sdelphij			gen_not(b0);
7558242484Sdelphij		}
7559242484Sdelphij#else /* defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
7560127667Sbms		bpf_error("inbound/outbound not supported on linktype %d",
756175110Sfenner		    linktype);
756275110Sfenner		b0 = NULL;
756375110Sfenner		/* NOTREACHED */
7564242484Sdelphij#endif /* defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
756575110Sfenner	}
756617683Spst	return (b0);
756717683Spst}
756875110Sfenner
7569172680Smlaier#ifdef HAVE_NET_PFVAR_H
7570127667Sbms/* PF firewall log matched interface */
757198533Sfennerstruct block *
7572127667Sbmsgen_pf_ifname(const char *ifname)
7573127667Sbms{
7574127667Sbms	struct block *b0;
7575127667Sbms	u_int len, off;
7576127667Sbms
7577190225Srpaulo	if (linktype != DLT_PFLOG) {
7578190225Srpaulo		bpf_error("ifname supported only on PF linktype");
7579127667Sbms		/* NOTREACHED */
7580127667Sbms	}
7581190225Srpaulo	len = sizeof(((struct pfloghdr *)0)->ifname);
7582190225Srpaulo	off = offsetof(struct pfloghdr, ifname);
7583127667Sbms	if (strlen(ifname) >= len) {
7584127667Sbms		bpf_error("ifname interface names can only be %d characters",
7585127667Sbms		    len-1);
7586127667Sbms		/* NOTREACHED */
7587127667Sbms	}
7588147897Ssam	b0 = gen_bcmp(OR_LINK, off, strlen(ifname), (const u_char *)ifname);
7589127667Sbms	return (b0);
7590127667Sbms}
7591127667Sbms
7592162015Ssam/* PF firewall log ruleset name */
7593127667Sbmsstruct block *
7594127667Sbmsgen_pf_ruleset(char *ruleset)
7595127667Sbms{
7596127667Sbms	struct block *b0;
7597127667Sbms
7598127667Sbms	if (linktype != DLT_PFLOG) {
7599190225Srpaulo		bpf_error("ruleset supported only on PF linktype");
7600127667Sbms		/* NOTREACHED */
7601127667Sbms	}
7602190225Srpaulo
7603127667Sbms	if (strlen(ruleset) >= sizeof(((struct pfloghdr *)0)->ruleset)) {
7604127667Sbms		bpf_error("ruleset names can only be %ld characters",
7605127667Sbms		    (long)(sizeof(((struct pfloghdr *)0)->ruleset) - 1));
7606127667Sbms		/* NOTREACHED */
7607127667Sbms	}
7608190225Srpaulo
7609147897Ssam	b0 = gen_bcmp(OR_LINK, offsetof(struct pfloghdr, ruleset),
7610146771Ssam	    strlen(ruleset), (const u_char *)ruleset);
7611127667Sbms	return (b0);
7612127667Sbms}
7613127667Sbms
7614127667Sbms/* PF firewall log rule number */
7615127667Sbmsstruct block *
7616127667Sbmsgen_pf_rnr(int rnr)
7617127667Sbms{
7618127667Sbms	struct block *b0;
7619127667Sbms
7620190225Srpaulo	if (linktype != DLT_PFLOG) {
7621190225Srpaulo		bpf_error("rnr supported only on PF linktype");
7622127667Sbms		/* NOTREACHED */
7623127667Sbms	}
7624127667Sbms
7625190225Srpaulo	b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, rulenr), BPF_W,
7626190225Srpaulo		 (bpf_int32)rnr);
7627127667Sbms	return (b0);
7628127667Sbms}
7629127667Sbms
7630127667Sbms/* PF firewall log sub-rule number */
7631127667Sbmsstruct block *
7632127667Sbmsgen_pf_srnr(int srnr)
7633127667Sbms{
7634127667Sbms	struct block *b0;
7635127667Sbms
7636127667Sbms	if (linktype != DLT_PFLOG) {
7637190225Srpaulo		bpf_error("srnr supported only on PF linktype");
7638127667Sbms		/* NOTREACHED */
7639127667Sbms	}
7640127667Sbms
7641147897Ssam	b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, subrulenr), BPF_W,
7642127667Sbms	    (bpf_int32)srnr);
7643127667Sbms	return (b0);
7644127667Sbms}
7645127667Sbms
7646127667Sbms/* PF firewall log reason code */
7647127667Sbmsstruct block *
7648127667Sbmsgen_pf_reason(int reason)
7649127667Sbms{
7650127667Sbms	struct block *b0;
7651127667Sbms
7652190225Srpaulo	if (linktype != DLT_PFLOG) {
7653190225Srpaulo		bpf_error("reason supported only on PF linktype");
7654127667Sbms		/* NOTREACHED */
7655127667Sbms	}
7656127667Sbms
7657190225Srpaulo	b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, reason), BPF_B,
7658190225Srpaulo	    (bpf_int32)reason);
7659127667Sbms	return (b0);
7660127667Sbms}
7661127667Sbms
7662127667Sbms/* PF firewall log action */
7663127667Sbmsstruct block *
7664127667Sbmsgen_pf_action(int action)
7665127667Sbms{
7666127667Sbms	struct block *b0;
7667127667Sbms
7668190225Srpaulo	if (linktype != DLT_PFLOG) {
7669190225Srpaulo		bpf_error("action supported only on PF linktype");
7670127667Sbms		/* NOTREACHED */
7671127667Sbms	}
7672127667Sbms
7673190225Srpaulo	b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, action), BPF_B,
7674190225Srpaulo	    (bpf_int32)action);
7675127667Sbms	return (b0);
7676127667Sbms}
7677172680Smlaier#else /* !HAVE_NET_PFVAR_H */
7678172680Smlaierstruct block *
7679172680Smlaiergen_pf_ifname(const char *ifname)
7680172680Smlaier{
7681172680Smlaier	bpf_error("libpcap was compiled without pf support");
7682172680Smlaier	/* NOTREACHED */
7683172680Smlaier	return (NULL);
7684172680Smlaier}
7685127667Sbms
7686127667Sbmsstruct block *
7687172680Smlaiergen_pf_ruleset(char *ruleset)
7688172680Smlaier{
7689172680Smlaier	bpf_error("libpcap was compiled on a machine without pf support");
7690172680Smlaier	/* NOTREACHED */
7691172680Smlaier	return (NULL);
7692172680Smlaier}
7693172680Smlaier
7694172680Smlaierstruct block *
7695172680Smlaiergen_pf_rnr(int rnr)
7696172680Smlaier{
7697172680Smlaier	bpf_error("libpcap was compiled on a machine without pf support");
7698172680Smlaier	/* NOTREACHED */
7699172680Smlaier	return (NULL);
7700172680Smlaier}
7701172680Smlaier
7702172680Smlaierstruct block *
7703172680Smlaiergen_pf_srnr(int srnr)
7704172680Smlaier{
7705172680Smlaier	bpf_error("libpcap was compiled on a machine without pf support");
7706172680Smlaier	/* NOTREACHED */
7707172680Smlaier	return (NULL);
7708172680Smlaier}
7709172680Smlaier
7710172680Smlaierstruct block *
7711172680Smlaiergen_pf_reason(int reason)
7712172680Smlaier{
7713172680Smlaier	bpf_error("libpcap was compiled on a machine without pf support");
7714172680Smlaier	/* NOTREACHED */
7715172680Smlaier	return (NULL);
7716172680Smlaier}
7717172680Smlaier
7718172680Smlaierstruct block *
7719172680Smlaiergen_pf_action(int action)
7720172680Smlaier{
7721172680Smlaier	bpf_error("libpcap was compiled on a machine without pf support");
7722172680Smlaier	/* NOTREACHED */
7723172680Smlaier	return (NULL);
7724172680Smlaier}
7725172680Smlaier#endif /* HAVE_NET_PFVAR_H */
7726172680Smlaier
7727190225Srpaulo/* IEEE 802.11 wireless header */
7728172680Smlaierstruct block *
7729190225Srpaulogen_p80211_type(int type, int mask)
7730190225Srpaulo{
7731190225Srpaulo	struct block *b0;
7732190225Srpaulo
7733190225Srpaulo	switch (linktype) {
7734190225Srpaulo
7735190225Srpaulo	case DLT_IEEE802_11:
7736190225Srpaulo	case DLT_PRISM_HEADER:
7737190225Srpaulo	case DLT_IEEE802_11_RADIO_AVS:
7738190225Srpaulo	case DLT_IEEE802_11_RADIO:
7739190225Srpaulo		b0 = gen_mcmp(OR_LINK, 0, BPF_B, (bpf_int32)type,
7740190225Srpaulo		    (bpf_int32)mask);
7741190225Srpaulo		break;
7742190225Srpaulo
7743190225Srpaulo	default:
7744190225Srpaulo		bpf_error("802.11 link-layer types supported only on 802.11");
7745190225Srpaulo		/* NOTREACHED */
7746190225Srpaulo	}
7747190225Srpaulo
7748190225Srpaulo	return (b0);
7749190225Srpaulo}
7750190225Srpaulo
7751190225Srpaulostruct block *
7752190225Srpaulogen_p80211_fcdir(int fcdir)
7753190225Srpaulo{
7754190225Srpaulo	struct block *b0;
7755190225Srpaulo
7756190225Srpaulo	switch (linktype) {
7757190225Srpaulo
7758190225Srpaulo	case DLT_IEEE802_11:
7759190225Srpaulo	case DLT_PRISM_HEADER:
7760190225Srpaulo	case DLT_IEEE802_11_RADIO_AVS:
7761190225Srpaulo	case DLT_IEEE802_11_RADIO:
7762190225Srpaulo		break;
7763190225Srpaulo
7764190225Srpaulo	default:
7765190225Srpaulo		bpf_error("frame direction supported only with 802.11 headers");
7766190225Srpaulo		/* NOTREACHED */
7767190225Srpaulo	}
7768190225Srpaulo
7769190225Srpaulo	b0 = gen_mcmp(OR_LINK, 1, BPF_B, (bpf_int32)fcdir,
7770190225Srpaulo		(bpf_u_int32)IEEE80211_FC1_DIR_MASK);
7771190225Srpaulo
7772190225Srpaulo	return (b0);
7773190225Srpaulo}
7774190225Srpaulo
7775190225Srpaulostruct block *
777698533Sfennergen_acode(eaddr, q)
777798533Sfenner	register const u_char *eaddr;
777898533Sfenner	struct qual q;
777998533Sfenner{
7780190225Srpaulo	switch (linktype) {
7781190225Srpaulo
7782190225Srpaulo	case DLT_ARCNET:
7783190225Srpaulo	case DLT_ARCNET_LINUX:
7784190225Srpaulo		if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) &&
7785190225Srpaulo		    q.proto == Q_LINK)
7786190225Srpaulo			return (gen_ahostop(eaddr, (int)q.dir));
7787190225Srpaulo		else {
7788190225Srpaulo			bpf_error("ARCnet address used in non-arc expression");
7789190225Srpaulo			/* NOTREACHED */
7790190225Srpaulo		}
7791190225Srpaulo		break;
7792190225Srpaulo
7793190225Srpaulo	default:
7794190225Srpaulo		bpf_error("aid supported only on ARCnet");
7795190225Srpaulo		/* NOTREACHED */
779698533Sfenner	}
779798533Sfenner	bpf_error("ARCnet address used in non-arc expression");
779898533Sfenner	/* NOTREACHED */
7799172680Smlaier	return NULL;
780098533Sfenner}
780198533Sfenner
780298533Sfennerstatic struct block *
780398533Sfennergen_ahostop(eaddr, dir)
780498533Sfenner	register const u_char *eaddr;
780598533Sfenner	register int dir;
780698533Sfenner{
780798533Sfenner	register struct block *b0, *b1;
780898533Sfenner
780998533Sfenner	switch (dir) {
781098533Sfenner	/* src comes first, different from Ethernet */
781198533Sfenner	case Q_SRC:
7812147897Ssam		return gen_bcmp(OR_LINK, 0, 1, eaddr);
781398533Sfenner
781498533Sfenner	case Q_DST:
7815147897Ssam		return gen_bcmp(OR_LINK, 1, 1, eaddr);
781698533Sfenner
781798533Sfenner	case Q_AND:
781898533Sfenner		b0 = gen_ahostop(eaddr, Q_SRC);
781998533Sfenner		b1 = gen_ahostop(eaddr, Q_DST);
782098533Sfenner		gen_and(b0, b1);
782198533Sfenner		return b1;
782298533Sfenner
782398533Sfenner	case Q_DEFAULT:
782498533Sfenner	case Q_OR:
782598533Sfenner		b0 = gen_ahostop(eaddr, Q_SRC);
782698533Sfenner		b1 = gen_ahostop(eaddr, Q_DST);
782798533Sfenner		gen_or(b0, b1);
782898533Sfenner		return b1;
7829236167Sdelphij
7830236167Sdelphij	case Q_ADDR1:
7831236167Sdelphij		bpf_error("'addr1' is only supported on 802.11");
7832236167Sdelphij		break;
7833236167Sdelphij
7834236167Sdelphij	case Q_ADDR2:
7835236167Sdelphij		bpf_error("'addr2' is only supported on 802.11");
7836236167Sdelphij		break;
7837236167Sdelphij
7838236167Sdelphij	case Q_ADDR3:
7839236167Sdelphij		bpf_error("'addr3' is only supported on 802.11");
7840236167Sdelphij		break;
7841236167Sdelphij
7842236167Sdelphij	case Q_ADDR4:
7843236167Sdelphij		bpf_error("'addr4' is only supported on 802.11");
7844236167Sdelphij		break;
7845236167Sdelphij
7846236167Sdelphij	case Q_RA:
7847236167Sdelphij		bpf_error("'ra' is only supported on 802.11");
7848236167Sdelphij		break;
7849236167Sdelphij
7850236167Sdelphij	case Q_TA:
7851236167Sdelphij		bpf_error("'ta' is only supported on 802.11");
7852236167Sdelphij		break;
785398533Sfenner	}
785498533Sfenner	abort();
785598533Sfenner	/* NOTREACHED */
785698533Sfenner}
785798533Sfenner
785875110Sfenner/*
785975110Sfenner * support IEEE 802.1Q VLAN trunk over ethernet
786075110Sfenner */
786175110Sfennerstruct block *
786275110Sfennergen_vlan(vlan_num)
786375110Sfenner	int vlan_num;
786475110Sfenner{
7865162015Ssam	struct	block	*b0, *b1;
786675110Sfenner
7867162015Ssam	/* can't check for VLAN-encapsulated packets inside MPLS */
7868162015Ssam	if (label_stack_depth > 0)
7869162015Ssam		bpf_error("no VLAN match after MPLS");
7870162015Ssam
787175110Sfenner	/*
7872190225Srpaulo	 * Check for a VLAN packet, and then change the offsets to point
7873190225Srpaulo	 * to the type and data fields within the VLAN packet.  Just
7874190225Srpaulo	 * increment the offsets, so that we can support a hierarchy, e.g.
7875190225Srpaulo	 * "vlan 300 && vlan 200" to capture VLAN 200 encapsulated within
7876190225Srpaulo	 * VLAN 100.
7877147897Ssam	 *
7878147897Ssam	 * XXX - this is a bit of a kludge.  If we were to split the
7879147897Ssam	 * compiler into a parser that parses an expression and
7880147897Ssam	 * generates an expression tree, and a code generator that
7881147897Ssam	 * takes an expression tree (which could come from our
7882147897Ssam	 * parser or from some other parser) and generates BPF code,
7883147897Ssam	 * we could perhaps make the offsets parameters of routines
7884147897Ssam	 * and, in the handler for an "AND" node, pass to subnodes
7885147897Ssam	 * other than the VLAN node the adjusted offsets.
7886147897Ssam	 *
7887147897Ssam	 * This would mean that "vlan" would, instead of changing the
7888147897Ssam	 * behavior of *all* tests after it, change only the behavior
7889147897Ssam	 * of tests ANDed with it.  That would change the documented
7890147897Ssam	 * semantics of "vlan", which might break some expressions.
7891147897Ssam	 * However, it would mean that "(vlan and ip) or ip" would check
7892147897Ssam	 * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
7893147897Ssam	 * checking only for VLAN-encapsulated IP, so that could still
7894147897Ssam	 * be considered worth doing; it wouldn't break expressions
7895147897Ssam	 * that are of the form "vlan and ..." or "vlan N and ...",
7896147897Ssam	 * which I suspect are the most common expressions involving
7897147897Ssam	 * "vlan".  "vlan or ..." doesn't necessarily do what the user
7898147897Ssam	 * would really want, now, as all the "or ..." tests would
7899147897Ssam	 * be done assuming a VLAN, even though the "or" could be viewed
7900147897Ssam	 * as meaning "or, if this isn't a VLAN packet...".
790175110Sfenner	 */
7902162015Ssam	orig_nl = off_nl;
790375110Sfenner
7904162015Ssam	switch (linktype) {
790575110Sfenner
7906162015Ssam	case DLT_EN10MB:
7907236167Sdelphij	case DLT_NETANALYZER:
7908236167Sdelphij	case DLT_NETANALYZER_TRANSPARENT:
7909236167Sdelphij		/* check for VLAN, including QinQ */
7910190225Srpaulo		b0 = gen_cmp(OR_LINK, off_linktype, BPF_H,
7911190225Srpaulo		    (bpf_int32)ETHERTYPE_8021Q);
7912236167Sdelphij		b1 = gen_cmp(OR_LINK, off_linktype, BPF_H,
7913236167Sdelphij		    (bpf_int32)ETHERTYPE_8021QINQ);
7914236167Sdelphij		gen_or(b0,b1);
7915236167Sdelphij		b0 = b1;
7916190225Srpaulo
7917190225Srpaulo		/* If a specific VLAN is requested, check VLAN id */
7918190225Srpaulo		if (vlan_num >= 0) {
7919190225Srpaulo			b1 = gen_mcmp(OR_MACPL, 0, BPF_H,
7920190225Srpaulo			    (bpf_int32)vlan_num, 0x0fff);
7921190225Srpaulo			gen_and(b0, b1);
7922190225Srpaulo			b0 = b1;
7923190225Srpaulo		}
7924190225Srpaulo
7925190225Srpaulo		off_macpl += 4;
7926162015Ssam		off_linktype += 4;
7927190225Srpaulo#if 0
7928162015Ssam		off_nl_nosnap += 4;
7929162015Ssam		off_nl += 4;
7930190225Srpaulo#endif
7931162015Ssam		break;
793275110Sfenner
7933162015Ssam	default:
7934162015Ssam		bpf_error("no VLAN support for data link type %d",
7935162015Ssam		      linktype);
7936162015Ssam		/*NOTREACHED*/
7937162015Ssam	}
793875110Sfenner
793975110Sfenner	return (b0);
794075110Sfenner}
7941127667Sbms
7942146771Ssam/*
7943146771Ssam * support for MPLS
7944146771Ssam */
7945127667Sbmsstruct block *
7946146771Ssamgen_mpls(label_num)
7947146771Ssam	int label_num;
7948146771Ssam{
7949162015Ssam	struct	block	*b0,*b1;
7950146771Ssam
7951146771Ssam	/*
7952146771Ssam	 * Change the offsets to point to the type and data fields within
7953147897Ssam	 * the MPLS packet.  Just increment the offsets, so that we
7954147897Ssam	 * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to
7955147897Ssam	 * capture packets with an outer label of 100000 and an inner
7956147897Ssam	 * label of 1024.
7957147897Ssam	 *
7958147897Ssam	 * XXX - this is a bit of a kludge.  See comments in gen_vlan().
7959146771Ssam	 */
7960147897Ssam        orig_nl = off_nl;
7961146771Ssam
7962162015Ssam        if (label_stack_depth > 0) {
7963162015Ssam            /* just match the bottom-of-stack bit clear */
7964190225Srpaulo            b0 = gen_mcmp(OR_MACPL, orig_nl-2, BPF_B, 0, 0x01);
7965162015Ssam        } else {
7966162015Ssam            /*
7967162015Ssam             * Indicate that we're checking MPLS-encapsulated headers,
7968162015Ssam             * to make sure higher level code generators don't try to
7969162015Ssam             * match against IP-related protocols such as Q_ARP, Q_RARP
7970162015Ssam             * etc.
7971162015Ssam             */
7972162015Ssam            switch (linktype) {
7973162015Ssam
7974162015Ssam            case DLT_C_HDLC: /* fall through */
7975162015Ssam            case DLT_EN10MB:
7976236167Sdelphij            case DLT_NETANALYZER:
7977236167Sdelphij            case DLT_NETANALYZER_TRANSPARENT:
7978172680Smlaier                    b0 = gen_linktype(ETHERTYPE_MPLS);
7979162015Ssam                    break;
7980162015Ssam
7981162015Ssam            case DLT_PPP:
7982172680Smlaier                    b0 = gen_linktype(PPP_MPLS_UCAST);
7983162015Ssam                    break;
7984162015Ssam
7985162015Ssam                    /* FIXME add other DLT_s ...
7986162015Ssam                     * for Frame-Relay/and ATM this may get messy due to SNAP headers
7987162015Ssam                     * leave it for now */
7988162015Ssam
7989162015Ssam            default:
7990162015Ssam                    bpf_error("no MPLS support for data link type %d",
7991147897Ssam                          linktype);
7992162015Ssam                    b0 = NULL;
7993162015Ssam                    /*NOTREACHED*/
7994162015Ssam                    break;
7995162015Ssam            }
7996147897Ssam        }
7997146771Ssam
7998146771Ssam	/* If a specific MPLS label is requested, check it */
7999146771Ssam	if (label_num >= 0) {
8000146771Ssam		label_num = label_num << 12; /* label is shifted 12 bits on the wire */
8001190225Srpaulo		b1 = gen_mcmp(OR_MACPL, orig_nl, BPF_W, (bpf_int32)label_num,
8002147897Ssam		    0xfffff000); /* only compare the first 20 bits */
8003146771Ssam		gen_and(b0, b1);
8004146771Ssam		b0 = b1;
8005146771Ssam	}
8006146771Ssam
8007162015Ssam        off_nl_nosnap += 4;
8008162015Ssam        off_nl += 4;
8009162015Ssam        label_stack_depth++;
8010146771Ssam	return (b0);
8011146771Ssam}
8012146771Ssam
8013162015Ssam/*
8014162015Ssam * Support PPPOE discovery and session.
8015162015Ssam */
8016146771Ssamstruct block *
8017162015Ssamgen_pppoed()
8018162015Ssam{
8019162015Ssam	/* check for PPPoE discovery */
8020162015Ssam	return gen_linktype((bpf_int32)ETHERTYPE_PPPOED);
8021162015Ssam}
8022162015Ssam
8023162015Ssamstruct block *
8024162015Ssamgen_pppoes()
8025162015Ssam{
8026162015Ssam	struct block *b0;
8027162015Ssam
8028162015Ssam	/*
8029162015Ssam	 * Test against the PPPoE session link-layer type.
8030162015Ssam	 */
8031162015Ssam	b0 = gen_linktype((bpf_int32)ETHERTYPE_PPPOES);
8032162015Ssam
8033162015Ssam	/*
8034162015Ssam	 * Change the offsets to point to the type and data fields within
8035190225Srpaulo	 * the PPP packet, and note that this is PPPoE rather than
8036190225Srpaulo	 * raw PPP.
8037162015Ssam	 *
8038162015Ssam	 * XXX - this is a bit of a kludge.  If we were to split the
8039162015Ssam	 * compiler into a parser that parses an expression and
8040162015Ssam	 * generates an expression tree, and a code generator that
8041162015Ssam	 * takes an expression tree (which could come from our
8042162015Ssam	 * parser or from some other parser) and generates BPF code,
8043162015Ssam	 * we could perhaps make the offsets parameters of routines
8044162015Ssam	 * and, in the handler for an "AND" node, pass to subnodes
8045162015Ssam	 * other than the PPPoE node the adjusted offsets.
8046162015Ssam	 *
8047162015Ssam	 * This would mean that "pppoes" would, instead of changing the
8048162015Ssam	 * behavior of *all* tests after it, change only the behavior
8049162015Ssam	 * of tests ANDed with it.  That would change the documented
8050162015Ssam	 * semantics of "pppoes", which might break some expressions.
8051162015Ssam	 * However, it would mean that "(pppoes and ip) or ip" would check
8052162015Ssam	 * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
8053162015Ssam	 * checking only for VLAN-encapsulated IP, so that could still
8054162015Ssam	 * be considered worth doing; it wouldn't break expressions
8055162015Ssam	 * that are of the form "pppoes and ..." which I suspect are the
8056162015Ssam	 * most common expressions involving "pppoes".  "pppoes or ..."
8057162015Ssam	 * doesn't necessarily do what the user would really want, now,
8058162015Ssam	 * as all the "or ..." tests would be done assuming PPPoE, even
8059162015Ssam	 * though the "or" could be viewed as meaning "or, if this isn't
8060162015Ssam	 * a PPPoE packet...".
8061162015Ssam	 */
8062162015Ssam	orig_linktype = off_linktype;	/* save original values */
8063162015Ssam	orig_nl = off_nl;
8064190225Srpaulo	is_pppoes = 1;
8065162015Ssam
8066162015Ssam	/*
8067162015Ssam	 * The "network-layer" protocol is PPPoE, which has a 6-byte
8068190225Srpaulo	 * PPPoE header, followed by a PPP packet.
8069190225Srpaulo	 *
8070190225Srpaulo	 * There is no HDLC encapsulation for the PPP packet (it's
8071190225Srpaulo	 * encapsulated in PPPoES instead), so the link-layer type
8072190225Srpaulo	 * starts at the first byte of the PPP packet.  For PPPoE,
8073190225Srpaulo	 * that offset is relative to the beginning of the total
8074190225Srpaulo	 * link-layer payload, including any 802.2 LLC header, so
8075190225Srpaulo	 * it's 6 bytes past off_nl.
8076162015Ssam	 */
8077190225Srpaulo	off_linktype = off_nl + 6;
8078162015Ssam
8079162015Ssam	/*
8080190225Srpaulo	 * The network-layer offsets are relative to the beginning
8081190225Srpaulo	 * of the MAC-layer payload; that's past the 6-byte
8082190225Srpaulo	 * PPPoE header and the 2-byte PPP header.
8083162015Ssam	 */
8084190225Srpaulo	off_nl = 6+2;
8085190225Srpaulo	off_nl_nosnap = 6+2;
8086162015Ssam
8087162015Ssam	return b0;
8088162015Ssam}
8089162015Ssam
8090162015Ssamstruct block *
8091127667Sbmsgen_atmfield_code(atmfield, jvalue, jtype, reverse)
8092127667Sbms	int atmfield;
8093147897Ssam	bpf_int32 jvalue;
8094127667Sbms	bpf_u_int32 jtype;
8095127667Sbms	int reverse;
8096127667Sbms{
8097127667Sbms	struct block *b0;
8098127667Sbms
8099127667Sbms	switch (atmfield) {
8100127667Sbms
8101127667Sbms	case A_VPI:
8102127667Sbms		if (!is_atm)
8103127667Sbms			bpf_error("'vpi' supported only on raw ATM");
8104127667Sbms		if (off_vpi == (u_int)-1)
8105127667Sbms			abort();
8106147897Ssam		b0 = gen_ncmp(OR_LINK, off_vpi, BPF_B, 0xffffffff, jtype,
8107147897Ssam		    reverse, jvalue);
8108127667Sbms		break;
8109127667Sbms
8110127667Sbms	case A_VCI:
8111127667Sbms		if (!is_atm)
8112127667Sbms			bpf_error("'vci' supported only on raw ATM");
8113127667Sbms		if (off_vci == (u_int)-1)
8114127667Sbms			abort();
8115147897Ssam		b0 = gen_ncmp(OR_LINK, off_vci, BPF_H, 0xffffffff, jtype,
8116147897Ssam		    reverse, jvalue);
8117127667Sbms		break;
8118127667Sbms
8119127667Sbms	case A_PROTOTYPE:
8120127667Sbms		if (off_proto == (u_int)-1)
8121127667Sbms			abort();	/* XXX - this isn't on FreeBSD */
8122147897Ssam		b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0x0f, jtype,
8123147897Ssam		    reverse, jvalue);
8124127667Sbms		break;
8125127667Sbms
8126127667Sbms	case A_MSGTYPE:
8127127667Sbms		if (off_payload == (u_int)-1)
8128127667Sbms			abort();
8129147897Ssam		b0 = gen_ncmp(OR_LINK, off_payload + MSG_TYPE_POS, BPF_B,
8130147897Ssam		    0xffffffff, jtype, reverse, jvalue);
8131127667Sbms		break;
8132127667Sbms
8133127667Sbms	case A_CALLREFTYPE:
8134127667Sbms		if (!is_atm)
8135127667Sbms			bpf_error("'callref' supported only on raw ATM");
8136127667Sbms		if (off_proto == (u_int)-1)
8137127667Sbms			abort();
8138147897Ssam		b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0xffffffff,
8139147897Ssam		    jtype, reverse, jvalue);
8140127667Sbms		break;
8141127667Sbms
8142127667Sbms	default:
8143127667Sbms		abort();
8144127667Sbms	}
8145127667Sbms	return b0;
8146127667Sbms}
8147127667Sbms
8148127667Sbmsstruct block *
8149127667Sbmsgen_atmtype_abbrev(type)
8150127667Sbms	int type;
8151127667Sbms{
8152127667Sbms	struct block *b0, *b1;
8153127667Sbms
8154127667Sbms	switch (type) {
8155127667Sbms
8156127667Sbms	case A_METAC:
8157127667Sbms		/* Get all packets in Meta signalling Circuit */
8158127667Sbms		if (!is_atm)
8159127667Sbms			bpf_error("'metac' supported only on raw ATM");
8160127667Sbms		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8161127667Sbms		b1 = gen_atmfield_code(A_VCI, 1, BPF_JEQ, 0);
8162127667Sbms		gen_and(b0, b1);
8163127667Sbms		break;
8164127667Sbms
8165127667Sbms	case A_BCC:
8166127667Sbms		/* Get all packets in Broadcast Circuit*/
8167127667Sbms		if (!is_atm)
8168127667Sbms			bpf_error("'bcc' supported only on raw ATM");
8169127667Sbms		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8170127667Sbms		b1 = gen_atmfield_code(A_VCI, 2, BPF_JEQ, 0);
8171127667Sbms		gen_and(b0, b1);
8172127667Sbms		break;
8173127667Sbms
8174127667Sbms	case A_OAMF4SC:
8175127667Sbms		/* Get all cells in Segment OAM F4 circuit*/
8176127667Sbms		if (!is_atm)
8177127667Sbms			bpf_error("'oam4sc' supported only on raw ATM");
8178127667Sbms		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8179127667Sbms		b1 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
8180127667Sbms		gen_and(b0, b1);
8181127667Sbms		break;
8182127667Sbms
8183127667Sbms	case A_OAMF4EC:
8184127667Sbms		/* Get all cells in End-to-End OAM F4 Circuit*/
8185127667Sbms		if (!is_atm)
8186127667Sbms			bpf_error("'oam4ec' supported only on raw ATM");
8187127667Sbms		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8188127667Sbms		b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0);
8189127667Sbms		gen_and(b0, b1);
8190127667Sbms		break;
8191127667Sbms
8192127667Sbms	case A_SC:
8193127667Sbms		/*  Get all packets in connection Signalling Circuit */
8194127667Sbms		if (!is_atm)
8195127667Sbms			bpf_error("'sc' supported only on raw ATM");
8196127667Sbms		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8197127667Sbms		b1 = gen_atmfield_code(A_VCI, 5, BPF_JEQ, 0);
8198127667Sbms		gen_and(b0, b1);
8199127667Sbms		break;
8200127667Sbms
8201127667Sbms	case A_ILMIC:
8202127667Sbms		/* Get all packets in ILMI Circuit */
8203127667Sbms		if (!is_atm)
8204127667Sbms			bpf_error("'ilmic' supported only on raw ATM");
8205127667Sbms		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8206127667Sbms		b1 = gen_atmfield_code(A_VCI, 16, BPF_JEQ, 0);
8207127667Sbms		gen_and(b0, b1);
8208127667Sbms		break;
8209127667Sbms
8210127667Sbms	case A_LANE:
8211127667Sbms		/* Get all LANE packets */
8212127667Sbms		if (!is_atm)
8213127667Sbms			bpf_error("'lane' supported only on raw ATM");
8214127667Sbms		b1 = gen_atmfield_code(A_PROTOTYPE, PT_LANE, BPF_JEQ, 0);
8215127667Sbms
8216127667Sbms		/*
8217127667Sbms		 * Arrange that all subsequent tests assume LANE
8218127667Sbms		 * rather than LLC-encapsulated packets, and set
8219127667Sbms		 * the offsets appropriately for LANE-encapsulated
8220127667Sbms		 * Ethernet.
8221127667Sbms		 *
8222127667Sbms		 * "off_mac" is the offset of the Ethernet header,
8223127667Sbms		 * which is 2 bytes past the ATM pseudo-header
8224127667Sbms		 * (skipping the pseudo-header and 2-byte LE Client
8225127667Sbms		 * field).  The other offsets are Ethernet offsets
8226127667Sbms		 * relative to "off_mac".
8227127667Sbms		 */
8228127667Sbms		is_lane = 1;
8229127667Sbms		off_mac = off_payload + 2;	/* MAC header */
8230127667Sbms		off_linktype = off_mac + 12;
8231190225Srpaulo		off_macpl = off_mac + 14;	/* Ethernet */
8232190225Srpaulo		off_nl = 0;			/* Ethernet II */
8233190225Srpaulo		off_nl_nosnap = 3;		/* 802.3+802.2 */
8234127667Sbms		break;
8235127667Sbms
8236127667Sbms	case A_LLC:
8237127667Sbms		/* Get all LLC-encapsulated packets */
8238127667Sbms		if (!is_atm)
8239127667Sbms			bpf_error("'llc' supported only on raw ATM");
8240127667Sbms		b1 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
8241127667Sbms		is_lane = 0;
8242127667Sbms		break;
8243127667Sbms
8244127667Sbms	default:
8245127667Sbms		abort();
8246127667Sbms	}
8247127667Sbms	return b1;
8248127667Sbms}
8249127667Sbms
8250172680Smlaier/*
8251172680Smlaier * Filtering for MTP2 messages based on li value
8252172680Smlaier * FISU, length is null
8253172680Smlaier * LSSU, length is 1 or 2
8254172680Smlaier * MSU, length is 3 or more
8255172680Smlaier */
8256147897Ssamstruct block *
8257172680Smlaiergen_mtp2type_abbrev(type)
8258172680Smlaier	int type;
8259172680Smlaier{
8260172680Smlaier	struct block *b0, *b1;
8261172680Smlaier
8262172680Smlaier	switch (type) {
8263172680Smlaier
8264172680Smlaier	case M_FISU:
8265172680Smlaier		if ( (linktype != DLT_MTP2) &&
8266190225Srpaulo		     (linktype != DLT_ERF) &&
8267172680Smlaier		     (linktype != DLT_MTP2_WITH_PHDR) )
8268172680Smlaier			bpf_error("'fisu' supported only on MTP2");
8269172680Smlaier		/* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */
8270172680Smlaier		b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JEQ, 0, 0);
8271172680Smlaier		break;
8272172680Smlaier
8273172680Smlaier	case M_LSSU:
8274172680Smlaier		if ( (linktype != DLT_MTP2) &&
8275190225Srpaulo		     (linktype != DLT_ERF) &&
8276172680Smlaier		     (linktype != DLT_MTP2_WITH_PHDR) )
8277172680Smlaier			bpf_error("'lssu' supported only on MTP2");
8278172680Smlaier		b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 1, 2);
8279172680Smlaier		b1 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 0);
8280172680Smlaier		gen_and(b1, b0);
8281172680Smlaier		break;
8282172680Smlaier
8283172680Smlaier	case M_MSU:
8284172680Smlaier		if ( (linktype != DLT_MTP2) &&
8285190225Srpaulo		     (linktype != DLT_ERF) &&
8286172680Smlaier		     (linktype != DLT_MTP2_WITH_PHDR) )
8287172680Smlaier			bpf_error("'msu' supported only on MTP2");
8288172680Smlaier		b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 2);
8289172680Smlaier		break;
8290172680Smlaier
8291172680Smlaier	default:
8292172680Smlaier		abort();
8293172680Smlaier	}
8294172680Smlaier	return b0;
8295172680Smlaier}
8296172680Smlaier
8297172680Smlaierstruct block *
8298147897Ssamgen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
8299147897Ssam	int mtp3field;
8300147897Ssam	bpf_u_int32 jvalue;
8301147897Ssam	bpf_u_int32 jtype;
8302147897Ssam	int reverse;
8303147897Ssam{
8304147897Ssam	struct block *b0;
8305147897Ssam	bpf_u_int32 val1 , val2 , val3;
8306127667Sbms
8307147897Ssam	switch (mtp3field) {
8308147897Ssam
8309147897Ssam	case M_SIO:
8310147897Ssam		if (off_sio == (u_int)-1)
8311147897Ssam			bpf_error("'sio' supported only on SS7");
8312147897Ssam		/* sio coded on 1 byte so max value 255 */
8313147897Ssam		if(jvalue > 255)
8314147897Ssam		        bpf_error("sio value %u too big; max value = 255",
8315147897Ssam		            jvalue);
8316147897Ssam		b0 = gen_ncmp(OR_PACKET, off_sio, BPF_B, 0xffffffff,
8317147897Ssam		    (u_int)jtype, reverse, (u_int)jvalue);
8318147897Ssam		break;
8319147897Ssam
8320147897Ssam        case M_OPC:
8321147897Ssam	        if (off_opc == (u_int)-1)
8322147897Ssam			bpf_error("'opc' supported only on SS7");
8323147897Ssam		/* opc coded on 14 bits so max value 16383 */
8324147897Ssam		if (jvalue > 16383)
8325147897Ssam		        bpf_error("opc value %u too big; max value = 16383",
8326147897Ssam		            jvalue);
8327147897Ssam		/* the following instructions are made to convert jvalue
8328147897Ssam		 * to the form used to write opc in an ss7 message*/
8329147897Ssam		val1 = jvalue & 0x00003c00;
8330147897Ssam		val1 = val1 >>10;
8331147897Ssam		val2 = jvalue & 0x000003fc;
8332147897Ssam		val2 = val2 <<6;
8333147897Ssam		val3 = jvalue & 0x00000003;
8334147897Ssam		val3 = val3 <<22;
8335147897Ssam		jvalue = val1 + val2 + val3;
8336147897Ssam		b0 = gen_ncmp(OR_PACKET, off_opc, BPF_W, 0x00c0ff0f,
8337147897Ssam		    (u_int)jtype, reverse, (u_int)jvalue);
8338147897Ssam		break;
8339147897Ssam
8340147897Ssam	case M_DPC:
8341147897Ssam	        if (off_dpc == (u_int)-1)
8342147897Ssam			bpf_error("'dpc' supported only on SS7");
8343147897Ssam		/* dpc coded on 14 bits so max value 16383 */
8344147897Ssam		if (jvalue > 16383)
8345147897Ssam		        bpf_error("dpc value %u too big; max value = 16383",
8346147897Ssam		            jvalue);
8347147897Ssam		/* the following instructions are made to convert jvalue
8348147897Ssam		 * to the forme used to write dpc in an ss7 message*/
8349147897Ssam		val1 = jvalue & 0x000000ff;
8350147897Ssam		val1 = val1 << 24;
8351147897Ssam		val2 = jvalue & 0x00003f00;
8352147897Ssam		val2 = val2 << 8;
8353147897Ssam		jvalue = val1 + val2;
8354147897Ssam		b0 = gen_ncmp(OR_PACKET, off_dpc, BPF_W, 0xff3f0000,
8355147897Ssam		    (u_int)jtype, reverse, (u_int)jvalue);
8356147897Ssam		break;
8357147897Ssam
8358147897Ssam	case M_SLS:
8359147897Ssam	        if (off_sls == (u_int)-1)
8360147897Ssam			bpf_error("'sls' supported only on SS7");
8361147897Ssam		/* sls coded on 4 bits so max value 15 */
8362147897Ssam		if (jvalue > 15)
8363147897Ssam		         bpf_error("sls value %u too big; max value = 15",
8364147897Ssam		             jvalue);
8365147897Ssam		/* the following instruction is made to convert jvalue
8366147897Ssam		 * to the forme used to write sls in an ss7 message*/
8367147897Ssam		jvalue = jvalue << 4;
8368147897Ssam		b0 = gen_ncmp(OR_PACKET, off_sls, BPF_B, 0xf0,
8369147897Ssam		    (u_int)jtype,reverse, (u_int)jvalue);
8370147897Ssam		break;
8371147897Ssam
8372147897Ssam	default:
8373147897Ssam		abort();
8374147897Ssam	}
8375147897Ssam	return b0;
8376147897Ssam}
8377147897Ssam
8378127667Sbmsstatic struct block *
8379127667Sbmsgen_msg_abbrev(type)
8380127667Sbms	int type;
8381127667Sbms{
8382127667Sbms	struct block *b1;
8383127667Sbms
8384127667Sbms	/*
8385127667Sbms	 * Q.2931 signalling protocol messages for handling virtual circuits
8386127667Sbms	 * establishment and teardown
8387127667Sbms	 */
8388127667Sbms	switch (type) {
8389127667Sbms
8390127667Sbms	case A_SETUP:
8391127667Sbms		b1 = gen_atmfield_code(A_MSGTYPE, SETUP, BPF_JEQ, 0);
8392127667Sbms		break;
8393127667Sbms
8394127667Sbms	case A_CALLPROCEED:
8395146771Ssam		b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
8396127667Sbms		break;
8397127667Sbms
8398127667Sbms	case A_CONNECT:
8399127667Sbms		b1 = gen_atmfield_code(A_MSGTYPE, CONNECT, BPF_JEQ, 0);
8400146771Ssam		break;
8401127667Sbms
8402127667Sbms	case A_CONNECTACK:
8403146771Ssam		b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
8404127667Sbms		break;
8405127667Sbms
8406127667Sbms	case A_RELEASE:
8407127667Sbms		b1 = gen_atmfield_code(A_MSGTYPE, RELEASE, BPF_JEQ, 0);
8408127667Sbms		break;
8409127667Sbms
8410127667Sbms	case A_RELEASE_DONE:
8411146771Ssam		b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
8412127667Sbms		break;
8413127667Sbms
8414127667Sbms	default:
8415127667Sbms		abort();
8416127667Sbms	}
8417127667Sbms	return b1;
8418127667Sbms}
8419127667Sbms
8420127667Sbmsstruct block *
8421127667Sbmsgen_atmmulti_abbrev(type)
8422127667Sbms	int type;
8423127667Sbms{
8424127667Sbms	struct block *b0, *b1;
8425127667Sbms
8426127667Sbms	switch (type) {
8427127667Sbms
8428127667Sbms	case A_OAM:
8429127667Sbms		if (!is_atm)
8430127667Sbms			bpf_error("'oam' supported only on raw ATM");
8431127667Sbms		b1 = gen_atmmulti_abbrev(A_OAMF4);
8432127667Sbms		break;
8433127667Sbms
8434127667Sbms	case A_OAMF4:
8435127667Sbms		if (!is_atm)
8436127667Sbms			bpf_error("'oamf4' supported only on raw ATM");
8437127667Sbms		/* OAM F4 type */
8438146771Ssam		b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
8439127667Sbms		b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0);
8440146771Ssam		gen_or(b0, b1);
8441127667Sbms		b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
8442127667Sbms		gen_and(b0, b1);
8443127667Sbms		break;
8444127667Sbms
8445127667Sbms	case A_CONNECTMSG:
8446127667Sbms		/*
8447127667Sbms		 * Get Q.2931 signalling messages for switched
8448127667Sbms		 * virtual connection
8449127667Sbms		 */
8450127667Sbms		if (!is_atm)
8451127667Sbms			bpf_error("'connectmsg' supported only on raw ATM");
8452127667Sbms		b0 = gen_msg_abbrev(A_SETUP);
8453127667Sbms		b1 = gen_msg_abbrev(A_CALLPROCEED);
8454127667Sbms		gen_or(b0, b1);
8455127667Sbms		b0 = gen_msg_abbrev(A_CONNECT);
8456127667Sbms		gen_or(b0, b1);
8457127667Sbms		b0 = gen_msg_abbrev(A_CONNECTACK);
8458127667Sbms		gen_or(b0, b1);
8459127667Sbms		b0 = gen_msg_abbrev(A_RELEASE);
8460127667Sbms		gen_or(b0, b1);
8461127667Sbms		b0 = gen_msg_abbrev(A_RELEASE_DONE);
8462127667Sbms		gen_or(b0, b1);
8463127667Sbms		b0 = gen_atmtype_abbrev(A_SC);
8464127667Sbms		gen_and(b0, b1);
8465127667Sbms		break;
8466127667Sbms
8467127667Sbms	case A_METACONNECT:
8468127667Sbms		if (!is_atm)
8469127667Sbms			bpf_error("'metaconnect' supported only on raw ATM");
8470127667Sbms		b0 = gen_msg_abbrev(A_SETUP);
8471127667Sbms		b1 = gen_msg_abbrev(A_CALLPROCEED);
8472127667Sbms		gen_or(b0, b1);
8473127667Sbms		b0 = gen_msg_abbrev(A_CONNECT);
8474127667Sbms		gen_or(b0, b1);
8475127667Sbms		b0 = gen_msg_abbrev(A_RELEASE);
8476127667Sbms		gen_or(b0, b1);
8477127667Sbms		b0 = gen_msg_abbrev(A_RELEASE_DONE);
8478127667Sbms		gen_or(b0, b1);
8479127667Sbms		b0 = gen_atmtype_abbrev(A_METAC);
8480127667Sbms		gen_and(b0, b1);
8481127667Sbms		break;
8482127667Sbms
8483127667Sbms	default:
8484127667Sbms		abort();
8485127667Sbms	}
8486127667Sbms	return b1;
8487127667Sbms}
8488