1aae9bd2fenner/*#define CHASE_CHAIN*/
2f0fdf33pst/*
3ca0d84cfenner * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
4f0fdf33pst *	The Regents of the University of California.  All rights reserved.
5f0fdf33pst *
6f0fdf33pst * Redistribution and use in source and binary forms, with or without
7f0fdf33pst * modification, are permitted provided that: (1) source code distributions
8f0fdf33pst * retain the above copyright notice and this paragraph in its entirety, (2)
9f0fdf33pst * distributions including binary code include the above copyright notice and
10f0fdf33pst * this paragraph in its entirety in the documentation or other materials
11f0fdf33pst * provided with the distribution, and (3) all advertising materials mentioning
12f0fdf33pst * features or use of this software display the following acknowledgement:
13f0fdf33pst * ``This product includes software developed by the University of California,
14f0fdf33pst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
15f0fdf33pst * the University nor the names of its contributors may be used to endorse
16f0fdf33pst * or promote products derived from this software without specific prior
17f0fdf33pst * written permission.
18f0fdf33pst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19f0fdf33pst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20f0fdf33pst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21f0fdf33pst */
22a6bce88fenner
23a6bce88fenner#ifdef HAVE_CONFIG_H
2419bb0b8hselasky#include <config.h>
25f0fdf33pst#endif
26f0fdf33pst
2719bb0b8hselasky#include <pcap-types.h>
2894960e5delphij#ifdef _WIN32
2919bb0b8hselasky  #include <ws2tcpip.h>
3019bb0b8hselasky#else
3119bb0b8hselasky  #include <sys/socket.h>
32f0fdf33pst
3319bb0b8hselasky  #ifdef __NetBSD__
3419bb0b8hselasky    #include <sys/param.h>
3519bb0b8hselasky  #endif
36f0fdf33pst
3719bb0b8hselasky  #include <netinet/in.h>
3819bb0b8hselasky  #include <arpa/inet.h>
3994960e5delphij#endif /* _WIN32 */
40da13a5abms
41f0fdf33pst#include <stdlib.h>
42a6bce88fenner#include <string.h>
43f0fdf33pst#include <memory.h>
44f0fdf33pst#include <setjmp.h>
45f0fdf33pst#include <stdarg.h>
46f0fdf33pst
4770f7ae4sam#ifdef MSDOS
4870f7ae4sam#include "pcap-dos.h"
4970f7ae4sam#endif
5070f7ae4sam
51f0fdf33pst#include "pcap-int.h"
52f0fdf33pst
53c2630c9philip#include "extract.h"
54c2630c9philip
55f0fdf33pst#include "ethertype.h"
56a6bce88fenner#include "nlpid.h"
571e8ea46fenner#include "llc.h"
58f0fdf33pst#include "gencode.h"
59d8d18f6rpaulo#include "ieee80211.h"
60da13a5abms#include "atmuni31.h"
61da13a5abms#include "sunatmpos.h"
62ca0d84cfenner#include "ppp.h"
63d8d18f6rpaulo#include "pcap/sll.h"
64724e1a0rpaulo#include "pcap/ipnet.h"
651e8ea46fenner#include "arcnet.h"
6694960e5delphij
6794960e5delphij#include "grammar.h"
6894960e5delphij#include "scanner.h"
6994960e5delphij
70489abeddelphij#if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
71506bfc5delphij#include <linux/types.h>
72506bfc5delphij#include <linux/if_packet.h>
73506bfc5delphij#include <linux/filter.h>
74506bfc5delphij#endif
7594960e5delphij
764462427mlaier#ifdef HAVE_NET_PFVAR_H
774462427mlaier#include <sys/socket.h>
784462427mlaier#include <net/if.h>
794462427mlaier#include <net/pfvar.h>
804462427mlaier#include <net/if_pflog.h>
814462427mlaier#endif
8294960e5delphij
83da13a5abms#ifndef offsetof
84da13a5abms#define offsetof(s, e) ((size_t)&((s *)0)->e)
85da13a5abms#endif
8694960e5delphij
8794960e5delphij#ifdef _WIN32
8819bb0b8hselasky  #ifdef INET6
8919bb0b8hselasky    #if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
9094960e5delphij/* IPv6 address */
9194960e5delphijstruct in6_addr
9294960e5delphij  {
9394960e5delphij    union
9494960e5delphij      {
9519bb0b8hselasky	uint8_t		u6_addr8[16];
9619bb0b8hselasky	uint16_t	u6_addr16[8];
9719bb0b8hselasky	uint32_t	u6_addr32[4];
9894960e5delphij      } in6_u;
9994960e5delphij#define s6_addr			in6_u.u6_addr8
10094960e5delphij#define s6_addr16		in6_u.u6_addr16
10194960e5delphij#define s6_addr32		in6_u.u6_addr32
10294960e5delphij#define s6_addr64		in6_u.u6_addr64
10394960e5delphij  };
10494960e5delphij
10594960e5delphijtypedef unsigned short	sa_family_t;
10694960e5delphij
10794960e5delphij#define	__SOCKADDR_COMMON(sa_prefix) \
10894960e5delphij  sa_family_t sa_prefix##family
10994960e5delphij
11094960e5delphij/* Ditto, for IPv6.  */
11194960e5delphijstruct sockaddr_in6
11294960e5delphij  {
11394960e5delphij    __SOCKADDR_COMMON (sin6_);
11419bb0b8hselasky    uint16_t sin6_port;		/* Transport layer port # */
11519bb0b8hselasky    uint32_t sin6_flowinfo;	/* IPv6 flow information */
11694960e5delphij    struct in6_addr sin6_addr;	/* IPv6 address */
11794960e5delphij  };
11894960e5delphij
11919bb0b8hselasky      #ifndef EAI_ADDRFAMILY
12094960e5delphijstruct addrinfo {
12194960e5delphij	int	ai_flags;	/* AI_PASSIVE, AI_CANONNAME */
12294960e5delphij	int	ai_family;	/* PF_xxx */
12394960e5delphij	int	ai_socktype;	/* SOCK_xxx */
12494960e5delphij	int	ai_protocol;	/* 0 or IPPROTO_xxx for IPv4 and IPv6 */
12594960e5delphij	size_t	ai_addrlen;	/* length of ai_addr */
12694960e5delphij	char	*ai_canonname;	/* canonical name for hostname */
12794960e5delphij	struct sockaddr *ai_addr;	/* binary address */
12894960e5delphij	struct addrinfo *ai_next;	/* next structure in linked list */
12994960e5delphij};
13019bb0b8hselasky      #endif /* EAI_ADDRFAMILY */
13119bb0b8hselasky    #endif /* defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF) */
13219bb0b8hselasky  #endif /* INET6 */
13394960e5delphij#else /* _WIN32 */
13419bb0b8hselasky  #include <netdb.h>	/* for "struct addrinfo" */
13594960e5delphij#endif /* _WIN32 */
136d8d18f6rpaulo#include <pcap/namedb.h>
137f0fdf33pst
13894960e5delphij#include "nametoaddr.h"
13994960e5delphij
140a6bce88fenner#define ETHERMTU	1500
141a6bce88fenner
14294960e5delphij#ifndef ETHERTYPE_TEB
14394960e5delphij#define ETHERTYPE_TEB 0x6558
14494960e5delphij#endif
14594960e5delphij
1466181b42delphij#ifndef IPPROTO_HOPOPTS
1476181b42delphij#define IPPROTO_HOPOPTS 0
1486181b42delphij#endif
1496181b42delphij#ifndef IPPROTO_ROUTING
1506181b42delphij#define IPPROTO_ROUTING 43
1516181b42delphij#endif
1526181b42delphij#ifndef IPPROTO_FRAGMENT
1536181b42delphij#define IPPROTO_FRAGMENT 44
1546181b42delphij#endif
1556181b42delphij#ifndef IPPROTO_DSTOPTS
1566181b42delphij#define IPPROTO_DSTOPTS 60
1576181b42delphij#endif
1581e8ea46fenner#ifndef IPPROTO_SCTP
1591e8ea46fenner#define IPPROTO_SCTP 132
1601e8ea46fenner#endif
1611e8ea46fenner
16294960e5delphij#define GENEVE_PORT 6081
16394960e5delphij
164f0fdf33pst#ifdef HAVE_OS_PROTO_H
165f0fdf33pst#include "os-proto.h"
166f0fdf33pst#endif
167f0fdf33pst
168f0fdf33pst#define JMP(c) ((c)|BPF_JMP|BPF_K)
169f0fdf33pst
17094960e5delphij/*
17194960e5delphij * "Push" the current value of the link-layer header type and link-layer
17294960e5delphij * header offset onto a "stack", and set a new value.  (It's not a
17394960e5delphij * full-blown stack; we keep only the top two items.)
17494960e5delphij */
17594960e5delphij#define PUSH_LINKHDR(cs, new_linktype, new_is_variable, new_constant_part, new_reg) \
17694960e5delphij{ \
17794960e5delphij	(cs)->prevlinktype = (cs)->linktype; \
17894960e5delphij	(cs)->off_prevlinkhdr = (cs)->off_linkhdr; \
17994960e5delphij	(cs)->linktype = (new_linktype); \
18094960e5delphij	(cs)->off_linkhdr.is_variable = (new_is_variable); \
18194960e5delphij	(cs)->off_linkhdr.constant_part = (new_constant_part); \
18294960e5delphij	(cs)->off_linkhdr.reg = (new_reg); \
18394960e5delphij	(cs)->is_geneve = 0; \
184f0fdf33pst}
185f0fdf33pst
18694960e5delphij/*
18794960e5delphij * Offset "not set" value.
18894960e5delphij */
18994960e5delphij#define OFFSET_NOT_SET	0xffffffffU
190f0fdf33pst
19194960e5delphij/*
19294960e5delphij * Absolute offsets, which are offsets from the beginning of the raw
19394960e5delphij * packet data, are, in the general case, the sum of a variable value
19494960e5delphij * and a constant value; the variable value may be absent, in which
19594960e5delphij * case the offset is only the constant value, and the constant value
19694960e5delphij * may be zero, in which case the offset is only the variable value.
19794960e5delphij *
19894960e5delphij * bpf_abs_offset is a structure containing all that information:
19994960e5delphij *
20094960e5delphij *   is_variable is 1 if there's a variable part.
20194960e5delphij *
20294960e5delphij *   constant_part is the constant part of the value, possibly zero;
20394960e5delphij *
20494960e5delphij *   if is_variable is 1, reg is the register number for a register
20594960e5delphij *   containing the variable value if the register has been assigned,
20694960e5delphij *   and -1 otherwise.
20794960e5delphij */
20894960e5delphijtypedef struct {
20994960e5delphij	int	is_variable;
21094960e5delphij	u_int	constant_part;
21194960e5delphij	int	reg;
21294960e5delphij} bpf_abs_offset;
213f0fdf33pst
214f0fdf33pst/*
215d1c1ca6sam * Value passed to gen_load_a() to indicate what the offset argument
21694960e5delphij * is relative to the beginning of.
217d1c1ca6sam */
218d1c1ca6samenum e_offrel {
21994960e5delphij	OR_PACKET,		/* full packet data */
22094960e5delphij	OR_LINKHDR,		/* link-layer header */
22194960e5delphij	OR_PREVLINKHDR,		/* previous link-layer header */
22294960e5delphij	OR_LLC,			/* 802.2 LLC header */
22394960e5delphij	OR_PREVMPLSHDR,		/* previous MPLS header */
22494960e5delphij	OR_LINKTYPE,		/* link-layer type */
22594960e5delphij	OR_LINKPL,		/* link-layer payload */
22694960e5delphij	OR_LINKPL_NOSNAP,	/* link-layer payload, with no SNAP header at the link layer */
22794960e5delphij	OR_TRAN_IPV4,		/* transport-layer header, with IPv4 network layer */
22894960e5delphij	OR_TRAN_IPV6		/* transport-layer header, with IPv6 network layer */
229d1c1ca6sam};
230d1c1ca6sam
231d1c1ca6sam/*
232f0fdf33pst * We divy out chunks of memory rather than call malloc each time so
233f0fdf33pst * we don't have to worry about leaking memory.  It's probably
23470f7ae4sam * not a big deal if all this memory was wasted but if this ever
235f0fdf33pst * goes into a library that would probably not be a good idea.
23670f7ae4sam *
23770f7ae4sam * XXX - this *is* in a library....
238f0fdf33pst */
239f0fdf33pst#define NCHUNKS 16
240f0fdf33pst#define CHUNK0SIZE 1024
241f0fdf33pststruct chunk {
24294960e5delphij	size_t n_left;
243f0fdf33pst	void *m;
244f0fdf33pst};
245f0fdf33pst
24694960e5delphij/* Code generator state */
24794960e5delphij
24894960e5delphijstruct _compiler_state {
24994960e5delphij	jmp_buf top_ctx;
25094960e5delphij	pcap_t *bpf_pcap;
25194960e5delphij
25294960e5delphij	struct icode ic;
25394960e5delphij
25494960e5delphij	int snaplen;
25594960e5delphij
25694960e5delphij	int linktype;
25794960e5delphij	int prevlinktype;
25894960e5delphij	int outermostlinktype;
25994960e5delphij
26094960e5delphij	bpf_u_int32 netmask;
26194960e5delphij	int no_optimize;
26294960e5delphij
26394960e5delphij	/* Hack for handling VLAN and MPLS stacks. */
26494960e5delphij	u_int label_stack_depth;
26594960e5delphij	u_int vlan_stack_depth;
26694960e5delphij
26794960e5delphij	/* XXX */
26894960e5delphij	u_int pcap_fddipad;
26994960e5delphij
27094960e5delphij	/*
27194960e5delphij	 * As errors are handled by a longjmp, anything allocated must
27294960e5delphij	 * be freed in the longjmp handler, so it must be reachable
27394960e5delphij	 * from that handler.
27494960e5delphij	 *
27594960e5delphij	 * One thing that's allocated is the result of pcap_nametoaddrinfo();
27694960e5delphij	 * it must be freed with freeaddrinfo().  This variable points to
27794960e5delphij	 * any addrinfo structure that would need to be freed.
27894960e5delphij	 */
27994960e5delphij	struct addrinfo *ai;
28094960e5delphij
28194960e5delphij	/*
282c2630c9philip	 * Another thing that's allocated is the result of pcap_ether_aton();
283c2630c9philip	 * it must be freed with free().  This variable points to any
284c2630c9philip	 * address that would need to be freed.
285c2630c9philip	 */
286c2630c9philip	u_char *e;
287c2630c9philip
288c2630c9philip	/*
28994960e5delphij	 * Various code constructs need to know the layout of the packet.
29094960e5delphij	 * These values give the necessary offsets from the beginning
29194960e5delphij	 * of the packet data.
29294960e5delphij	 */
29394960e5delphij
29494960e5delphij	/*
29594960e5delphij	 * Absolute offset of the beginning of the link-layer header.
29694960e5delphij	 */
29794960e5delphij	bpf_abs_offset off_linkhdr;
29894960e5delphij
29994960e5delphij	/*
30094960e5delphij	 * If we're checking a link-layer header for a packet encapsulated
30194960e5delphij	 * in another protocol layer, this is the equivalent information
30294960e5delphij	 * for the previous layers' link-layer header from the beginning
30394960e5delphij	 * of the raw packet data.
30494960e5delphij	 */
30594960e5delphij	bpf_abs_offset off_prevlinkhdr;
30694960e5delphij
30794960e5delphij	/*
30894960e5delphij	 * This is the equivalent information for the outermost layers'
30994960e5delphij	 * link-layer header.
31094960e5delphij	 */
31194960e5delphij	bpf_abs_offset off_outermostlinkhdr;
31294960e5delphij
31394960e5delphij	/*
31494960e5delphij	 * Absolute offset of the beginning of the link-layer payload.
31594960e5delphij	 */
31694960e5delphij	bpf_abs_offset off_linkpl;
31794960e5delphij
31894960e5delphij	/*
31994960e5delphij	 * "off_linktype" is the offset to information in the link-layer
32094960e5delphij	 * header giving the packet type. This is an absolute offset
32194960e5delphij	 * from the beginning of the packet.
32294960e5delphij	 *
32394960e5delphij	 * For Ethernet, it's the offset of the Ethernet type field; this
32494960e5delphij	 * means that it must have a value that skips VLAN tags.
32594960e5delphij	 *
32694960e5delphij	 * For link-layer types that always use 802.2 headers, it's the
32794960e5delphij	 * offset of the LLC header; this means that it must have a value
32894960e5delphij	 * that skips VLAN tags.
32994960e5delphij	 *
33094960e5delphij	 * For PPP, it's the offset of the PPP type field.
33194960e5delphij	 *
33294960e5delphij	 * For Cisco HDLC, it's the offset of the CHDLC type field.
33394960e5delphij	 *
33494960e5delphij	 * For BSD loopback, it's the offset of the AF_ value.
33594960e5delphij	 *
33694960e5delphij	 * For Linux cooked sockets, it's the offset of the type field.
33794960e5delphij	 *
33894960e5delphij	 * off_linktype.constant_part is set to OFFSET_NOT_SET for no
33994960e5delphij	 * encapsulation, in which case, IP is assumed.
34094960e5delphij	 */
34194960e5delphij	bpf_abs_offset off_linktype;
34294960e5delphij
34394960e5delphij	/*
34494960e5delphij	 * TRUE if the link layer includes an ATM pseudo-header.
34594960e5delphij	 */
34694960e5delphij	int is_atm;
34794960e5delphij
34894960e5delphij	/*
34994960e5delphij	 * TRUE if "geneve" appeared in the filter; it causes us to
35094960e5delphij	 * generate code that checks for a Geneve header and assume
35194960e5delphij	 * that later filters apply to the encapsulated payload.
35294960e5delphij	 */
35394960e5delphij	int is_geneve;
35494960e5delphij
35594960e5delphij	/*
35619bb0b8hselasky	 * TRUE if we need variable length part of VLAN offset
35719bb0b8hselasky	 */
35819bb0b8hselasky	int is_vlan_vloffset;
35919bb0b8hselasky
36019bb0b8hselasky	/*
36194960e5delphij	 * These are offsets for the ATM pseudo-header.
36294960e5delphij	 */
36394960e5delphij	u_int off_vpi;
36494960e5delphij	u_int off_vci;
36594960e5delphij	u_int off_proto;
36694960e5delphij
36794960e5delphij	/*
36894960e5delphij	 * These are offsets for the MTP2 fields.
36994960e5delphij	 */
37094960e5delphij	u_int off_li;
37194960e5delphij	u_int off_li_hsl;
37294960e5delphij
37394960e5delphij	/*
37494960e5delphij	 * These are offsets for the MTP3 fields.
37594960e5delphij	 */
37694960e5delphij	u_int off_sio;
37794960e5delphij	u_int off_opc;
37894960e5delphij	u_int off_dpc;
37994960e5delphij	u_int off_sls;
38094960e5delphij
38194960e5delphij	/*
38294960e5delphij	 * This is the offset of the first byte after the ATM pseudo_header,
38394960e5delphij	 * or -1 if there is no ATM pseudo-header.
38494960e5delphij	 */
38594960e5delphij	u_int off_payload;
38694960e5delphij
38794960e5delphij	/*
38894960e5delphij	 * These are offsets to the beginning of the network-layer header.
38994960e5delphij	 * They are relative to the beginning of the link-layer payload
39094960e5delphij	 * (i.e., they don't include off_linkhdr.constant_part or
39194960e5delphij	 * off_linkpl.constant_part).
39294960e5delphij	 *
39394960e5delphij	 * If the link layer never uses 802.2 LLC:
39494960e5delphij	 *
39594960e5delphij	 *	"off_nl" and "off_nl_nosnap" are the same.
39694960e5delphij	 *
39794960e5delphij	 * If the link layer always uses 802.2 LLC:
39894960e5delphij	 *
39994960e5delphij	 *	"off_nl" is the offset if there's a SNAP header following
40094960e5delphij	 *	the 802.2 header;
40194960e5delphij	 *
40294960e5delphij	 *	"off_nl_nosnap" is the offset if there's no SNAP header.
40394960e5delphij	 *
40494960e5delphij	 * If the link layer is Ethernet:
40594960e5delphij	 *
40694960e5delphij	 *	"off_nl" is the offset if the packet is an Ethernet II packet
40794960e5delphij	 *	(we assume no 802.3+802.2+SNAP);
40894960e5delphij	 *
40994960e5delphij	 *	"off_nl_nosnap" is the offset if the packet is an 802.3 packet
41094960e5delphij	 *	with an 802.2 header following it.
41194960e5delphij	 */
41294960e5delphij	u_int off_nl;
41394960e5delphij	u_int off_nl_nosnap;
41494960e5delphij
41594960e5delphij	/*
41694960e5delphij	 * Here we handle simple allocation of the scratch registers.
41794960e5delphij	 * If too many registers are alloc'd, the allocator punts.
41894960e5delphij	 */
41994960e5delphij	int regused[BPF_MEMWORDS];
42094960e5delphij	int curreg;
42194960e5delphij
42294960e5delphij	/*
42394960e5delphij	 * Memory chunks.
42494960e5delphij	 */
42594960e5delphij	struct chunk chunks[NCHUNKS];
42694960e5delphij	int cur_chunk;
42794960e5delphij};
42894960e5delphij
429c2630c9philip/*
430c2630c9philip * For use by routines outside this file.
431c2630c9philip */
432c2630c9philip/* VARARGS */
433c2630c9philipvoid
434c2630c9philipbpf_set_error(compiler_state_t *cstate, const char *fmt, ...)
43594960e5delphij{
436c2630c9philip	va_list ap;
437c2630c9philip
438c2630c9philip	va_start(ap, fmt);
439c2630c9philip	(void)pcap_vsnprintf(cstate->bpf_pcap->errbuf, PCAP_ERRBUF_SIZE,
440c2630c9philip	    fmt, ap);
441c2630c9philip	va_end(ap);
44294960e5delphij}
443f0fdf33pst
444c2630c9philip/*
445c2630c9philip * For use *ONLY* in routines in this file.
446c2630c9philip */
447c2630c9philipstatic void PCAP_NORETURN bpf_error(compiler_state_t *, const char *, ...)
448c2630c9philip    PCAP_PRINTFLIKE(2, 3);
449c2630c9philip
45094960e5delphij/* VARARGS */
451c2630c9philipstatic void PCAP_NORETURN
45294960e5delphijbpf_error(compiler_state_t *cstate, const char *fmt, ...)
45394960e5delphij{
45494960e5delphij	va_list ap;
45594960e5delphij
45694960e5delphij	va_start(ap, fmt);
457c2630c9philip	(void)pcap_vsnprintf(cstate->bpf_pcap->errbuf, PCAP_ERRBUF_SIZE,
458c2630c9philip	    fmt, ap);
45994960e5delphij	va_end(ap);
46094960e5delphij	longjmp(cstate->top_ctx, 1);
461c2630c9philip	/*NOTREACHED*/
46294960e5delphij}
46394960e5delphij
464c2630c9philipstatic int init_linktype(compiler_state_t *, pcap_t *);
46594960e5delphij
46694960e5delphijstatic void init_regs(compiler_state_t *);
46794960e5delphijstatic int alloc_reg(compiler_state_t *);
46894960e5delphijstatic void free_reg(compiler_state_t *, int);
46994960e5delphij
47094960e5delphijstatic void initchunks(compiler_state_t *cstate);
471c2630c9philipstatic void *newchunk_nolongjmp(compiler_state_t *cstate, size_t);
47294960e5delphijstatic void *newchunk(compiler_state_t *cstate, size_t);
47394960e5delphijstatic void freechunks(compiler_state_t *cstate);
47494960e5delphijstatic inline struct block *new_block(compiler_state_t *cstate, int);
47594960e5delphijstatic inline struct slist *new_stmt(compiler_state_t *cstate, int);
47694960e5delphijstatic struct block *gen_retblk(compiler_state_t *cstate, int);
47794960e5delphijstatic inline void syntax(compiler_state_t *cstate);
478f0fdf33pst
479f0fdf33pststatic void backpatch(struct block *, struct block *);
480f0fdf33pststatic void merge(struct block *, struct block *);
48194960e5delphijstatic struct block *gen_cmp(compiler_state_t *, enum e_offrel, u_int,
48294960e5delphij    u_int, bpf_int32);
48394960e5delphijstatic struct block *gen_cmp_gt(compiler_state_t *, enum e_offrel, u_int,
48494960e5delphij    u_int, bpf_int32);
48594960e5delphijstatic struct block *gen_cmp_ge(compiler_state_t *, enum e_offrel, u_int,
48694960e5delphij    u_int, bpf_int32);
48794960e5delphijstatic struct block *gen_cmp_lt(compiler_state_t *, enum e_offrel, u_int,
48894960e5delphij    u_int, bpf_int32);
48994960e5delphijstatic struct block *gen_cmp_le(compiler_state_t *, enum e_offrel, u_int,
49094960e5delphij    u_int, bpf_int32);
49194960e5delphijstatic struct block *gen_mcmp(compiler_state_t *, enum e_offrel, u_int,
49294960e5delphij    u_int, bpf_int32, bpf_u_int32);
49394960e5delphijstatic struct block *gen_bcmp(compiler_state_t *, enum e_offrel, u_int,
49494960e5delphij    u_int, const u_char *);
49594960e5delphijstatic struct block *gen_ncmp(compiler_state_t *, enum e_offrel, bpf_u_int32,
49694960e5delphij    bpf_u_int32, bpf_u_int32, bpf_u_int32, int, bpf_int32);
49794960e5delphijstatic struct slist *gen_load_absoffsetrel(compiler_state_t *, bpf_abs_offset *,
49894960e5delphij    u_int, u_int);
49994960e5delphijstatic struct slist *gen_load_a(compiler_state_t *, enum e_offrel, u_int,
50094960e5delphij    u_int);
50194960e5delphijstatic struct slist *gen_loadx_iphdrlen(compiler_state_t *);
50294960e5delphijstatic struct block *gen_uncond(compiler_state_t *, int);
50394960e5delphijstatic inline struct block *gen_true(compiler_state_t *);
50494960e5delphijstatic inline struct block *gen_false(compiler_state_t *);
50594960e5delphijstatic struct block *gen_ether_linktype(compiler_state_t *, int);
50694960e5delphijstatic struct block *gen_ipnet_linktype(compiler_state_t *, int);
50794960e5delphijstatic struct block *gen_linux_sll_linktype(compiler_state_t *, int);
50894960e5delphijstatic struct slist *gen_load_prism_llprefixlen(compiler_state_t *);
50994960e5delphijstatic struct slist *gen_load_avs_llprefixlen(compiler_state_t *);
51094960e5delphijstatic struct slist *gen_load_radiotap_llprefixlen(compiler_state_t *);
51194960e5delphijstatic struct slist *gen_load_ppi_llprefixlen(compiler_state_t *);
51294960e5delphijstatic void insert_compute_vloffsets(compiler_state_t *, struct block *);
51394960e5delphijstatic struct slist *gen_abs_offset_varpart(compiler_state_t *,
51494960e5delphij    bpf_abs_offset *);
515d8d18f6rpaulostatic int ethertype_to_ppptype(int);
51694960e5delphijstatic struct block *gen_linktype(compiler_state_t *, int);
51794960e5delphijstatic struct block *gen_snap(compiler_state_t *, bpf_u_int32, bpf_u_int32);
51894960e5delphijstatic struct block *gen_llc_linktype(compiler_state_t *, int);
51994960e5delphijstatic struct block *gen_hostop(compiler_state_t *, bpf_u_int32, bpf_u_int32,
52094960e5delphij    int, int, u_int, u_int);
521aae9bd2fenner#ifdef INET6
52294960e5delphijstatic struct block *gen_hostop6(compiler_state_t *, struct in6_addr *,
52394960e5delphij    struct in6_addr *, int, int, u_int, u_int);
524aae9bd2fenner#endif
52594960e5delphijstatic struct block *gen_ahostop(compiler_state_t *, const u_char *, int);
52694960e5delphijstatic struct block *gen_ehostop(compiler_state_t *, const u_char *, int);
52794960e5delphijstatic struct block *gen_fhostop(compiler_state_t *, const u_char *, int);
52894960e5delphijstatic struct block *gen_thostop(compiler_state_t *, const u_char *, int);
52994960e5delphijstatic struct block *gen_wlanhostop(compiler_state_t *, const u_char *, int);
53094960e5delphijstatic struct block *gen_ipfchostop(compiler_state_t *, const u_char *, int);
53194960e5delphijstatic struct block *gen_dnhostop(compiler_state_t *, bpf_u_int32, int);
53294960e5delphijstatic struct block *gen_mpls_linktype(compiler_state_t *, int);
53394960e5delphijstatic struct block *gen_host(compiler_state_t *, bpf_u_int32, bpf_u_int32,
53494960e5delphij    int, int, int);
535aae9bd2fenner#ifdef INET6
53694960e5delphijstatic struct block *gen_host6(compiler_state_t *, struct in6_addr *,
53794960e5delphij    struct in6_addr *, int, int, int);
538aae9bd2fenner#endif
539a6bce88fenner#ifndef INET6
540104596cdelphijstatic struct block *gen_gateway(compiler_state_t *, const u_char *,
54119bb0b8hselasky    struct addrinfo *, int, int);
542a6bce88fenner#endif
54394960e5delphijstatic struct block *gen_ipfrag(compiler_state_t *);
54494960e5delphijstatic struct block *gen_portatom(compiler_state_t *, int, bpf_int32);
54594960e5delphijstatic struct block *gen_portrangeatom(compiler_state_t *, int, bpf_int32,
54694960e5delphij    bpf_int32);
54794960e5delphijstatic struct block *gen_portatom6(compiler_state_t *, int, bpf_int32);
54894960e5delphijstatic struct block *gen_portrangeatom6(compiler_state_t *, int, bpf_int32,
54994960e5delphij    bpf_int32);
55094960e5delphijstruct block *gen_portop(compiler_state_t *, int, int, int);
55194960e5delphijstatic struct block *gen_port(compiler_state_t *, int, int, int);
55294960e5delphijstruct block *gen_portrangeop(compiler_state_t *, int, int, int, int);
55394960e5delphijstatic struct block *gen_portrange(compiler_state_t *, int, int, int, int);
55494960e5delphijstruct block *gen_portop6(compiler_state_t *, int, int, int);
55594960e5delphijstatic struct block *gen_port6(compiler_state_t *, int, int, int);
55694960e5delphijstruct block *gen_portrangeop6(compiler_state_t *, int, int, int, int);
55794960e5delphijstatic struct block *gen_portrange6(compiler_state_t *, int, int, int, int);
55894960e5delphijstatic int lookup_proto(compiler_state_t *, const char *, int);
55994960e5delphijstatic struct block *gen_protochain(compiler_state_t *, int, int, int);
56094960e5delphijstatic struct block *gen_proto(compiler_state_t *, int, int, int);
56194960e5delphijstatic struct slist *xfer_to_x(compiler_state_t *, struct arth *);
56294960e5delphijstatic struct slist *xfer_to_a(compiler_state_t *, struct arth *);
56394960e5delphijstatic struct block *gen_mac_multicast(compiler_state_t *, int);
56494960e5delphijstatic struct block *gen_len(compiler_state_t *, int, int);
56594960e5delphijstatic struct block *gen_check_802_11_data_frame(compiler_state_t *);
56694960e5delphijstatic struct block *gen_geneve_ll_check(compiler_state_t *cstate);
56794960e5delphij
56894960e5delphijstatic struct block *gen_ppi_dlt_check(compiler_state_t *);
569c2630c9philipstatic struct block *gen_atmfield_code_internal(compiler_state_t *, int,
570c2630c9philip    bpf_int32, bpf_u_int32, int);
571c2630c9philipstatic struct block *gen_atmtype_llc(compiler_state_t *);
57294960e5delphijstatic struct block *gen_msg_abbrev(compiler_state_t *, int type);
57394960e5delphij
57494960e5delphijstatic void
57594960e5delphijinitchunks(compiler_state_t *cstate)
57694960e5delphij{
57794960e5delphij	int i;
57894960e5delphij
57994960e5delphij	for (i = 0; i < NCHUNKS; i++) {
58094960e5delphij		cstate->chunks[i].n_left = 0;
58194960e5delphij		cstate->chunks[i].m = NULL;
58294960e5delphij	}
58394960e5delphij	cstate->cur_chunk = 0;
58494960e5delphij}
585da13a5abms
586f0fdf33pststatic void *
587c2630c9philipnewchunk_nolongjmp(compiler_state_t *cstate, size_t n)
588f0fdf33pst{
589f0fdf33pst	struct chunk *cp;
590da13a5abms	int k;
591da13a5abms	size_t size;
592f0fdf33pst
593aae9bd2fenner#ifndef __NetBSD__
594f0fdf33pst	/* XXX Round up to nearest long. */
595f0fdf33pst	n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);
596aae9bd2fenner#else
597aae9bd2fenner	/* XXX Round up to structure boundary. */
598aae9bd2fenner	n = ALIGN(n);
599aae9bd2fenner#endif
600f0fdf33pst
60194960e5delphij	cp = &cstate->chunks[cstate->cur_chunk];
602f0fdf33pst	if (n > cp->n_left) {
60319bb0b8hselasky		++cp;
60419bb0b8hselasky		k = ++cstate->cur_chunk;
605c2630c9philip		if (k >= NCHUNKS) {
606c2630c9philip			bpf_set_error(cstate, "out of memory");
607c2630c9philip			return (NULL);
608c2630c9philip		}
609f0fdf33pst		size = CHUNK0SIZE << k;
610f0fdf33pst		cp->m = (void *)malloc(size);
611c2630c9philip		if (cp->m == NULL) {
612c2630c9philip			bpf_set_error(cstate, "out of memory");
613c2630c9philip			return (NULL);
614c2630c9philip		}
615f0fdf33pst		memset((char *)cp->m, 0, size);
616f0fdf33pst		cp->n_left = size;
617c2630c9philip		if (n > size) {
618c2630c9philip			bpf_set_error(cstate, "out of memory");
619c2630c9philip			return (NULL);
620c2630c9philip		}
621f0fdf33pst	}
622f0fdf33pst	cp->n_left -= n;
623f0fdf33pst	return (void *)((char *)cp->m + cp->n_left);
624f0fdf33pst}
625f0fdf33pst
626c2630c9philipstatic void *
627c2630c9philipnewchunk(compiler_state_t *cstate, size_t n)
628c2630c9philip{
629c2630c9philip	void *p;
630c2630c9philip
631c2630c9philip	p = newchunk_nolongjmp(cstate, n);
632c2630c9philip	if (p == NULL) {
633c2630c9philip		longjmp(cstate->top_ctx, 1);
634c2630c9philip		/*NOTREACHED*/
635c2630c9philip	}
636c2630c9philip	return (p);
637c2630c9philip}
638c2630c9philip
639f0fdf33pststatic void
64094960e5delphijfreechunks(compiler_state_t *cstate)
641f0fdf33pst{
642f0fdf33pst	int i;
643f0fdf33pst
644f0fdf33pst	for (i = 0; i < NCHUNKS; ++i)
64594960e5delphij		if (cstate->chunks[i].m != NULL)
64694960e5delphij			free(cstate->chunks[i].m);
647f0fdf33pst}
648f0fdf33pst
649f0fdf33pst/*
650f0fdf33pst * A strdup whose allocations are freed after code generation is over.
651c2630c9philip * This is used by the lexical analyzer, so it can't longjmp; it just
652c2630c9philip * returns NULL on an allocation error, and the callers must check
653c2630c9philip * for it.
654f0fdf33pst */
655f0fdf33pstchar *
65694960e5delphijsdup(compiler_state_t *cstate, const char *s)
657f0fdf33pst{
65894960e5delphij	size_t n = strlen(s) + 1;
659c2630c9philip	char *cp = newchunk_nolongjmp(cstate, n);
660f0fdf33pst
661c2630c9philip	if (cp == NULL)
662c2630c9philip		return (NULL);
663c2630c9philip	pcap_strlcpy(cp, s, n);
664f0fdf33pst	return (cp);
665f0fdf33pst}
666f0fdf33pst
667f0fdf33pststatic inline struct block *
66894960e5delphijnew_block(compiler_state_t *cstate, int code)
669f0fdf33pst{
670f0fdf33pst	struct block *p;
671f0fdf33pst
67294960e5delphij	p = (struct block *)newchunk(cstate, sizeof(*p));
673f0fdf33pst	p->s.code = code;
674f0fdf33pst	p->head = p;
675f0fdf33pst
676f0fdf33pst	return p;
677f0fdf33pst}
678f0fdf33pst
679f0fdf33pststatic inline struct slist *
68094960e5delphijnew_stmt(compiler_state_t *cstate, int code)
681f0fdf33pst{
682f0fdf33pst	struct slist *p;
683f0fdf33pst
68494960e5delphij	p = (struct slist *)newchunk(cstate, sizeof(*p));
685f0fdf33pst	p->s.code = code;
686f0fdf33pst
687f0fdf33pst	return p;
688f0fdf33pst}
689f0fdf33pst
690f0fdf33pststatic struct block *
69194960e5delphijgen_retblk(compiler_state_t *cstate, int v)
692f0fdf33pst{
69394960e5delphij	struct block *b = new_block(cstate, BPF_RET|BPF_K);
694f0fdf33pst
695f0fdf33pst	b->s.k = v;
696f0fdf33pst	return b;
697f0fdf33pst}
698f0fdf33pst
69919bb0b8hselaskystatic inline PCAP_NORETURN_DEF void
70094960e5delphijsyntax(compiler_state_t *cstate)
701f0fdf33pst{
70294960e5delphij	bpf_error(cstate, "syntax error in filter expression");
703f0fdf33pst}
704f0fdf33pst
705f0fdf33pstint
706f0fdf33pstpcap_compile(pcap_t *p, struct bpf_program *program,
7074462427mlaier	     const char *buf, int optimize, bpf_u_int32 mask)
708f0fdf33pst{
70919bb0b8hselasky#ifdef _WIN32
71019bb0b8hselasky	static int done = 0;
71119bb0b8hselasky#endif
71294960e5delphij	compiler_state_t cstate;
7134462427mlaier	const char * volatile xbuf = buf;
71494960e5delphij	yyscan_t scanner = NULL;
715c2630c9philip	volatile YY_BUFFER_STATE in_buffer = NULL;
716506bfc5delphij	u_int len;
717489abeddelphij	int  rc;
718489abeddelphij
7196181b42delphij	/*
7206181b42delphij	 * If this pcap_t hasn't been activated, it doesn't have a
7216181b42delphij	 * link-layer type, so we can't use it.
7226181b42delphij	 */
7236181b42delphij	if (!p->activated) {
72494960e5delphij		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
7256181b42delphij		    "not-yet-activated pcap_t passed to pcap_compile");
72619bb0b8hselasky		return (-1);
7276181b42delphij	}
72819bb0b8hselasky
72919bb0b8hselasky#ifdef _WIN32
73019bb0b8hselasky	if (!done)
73119bb0b8hselasky		pcap_wsockinit();
73219bb0b8hselasky	done = 1;
73319bb0b8hselasky#endif
73419bb0b8hselasky
73519bb0b8hselasky#ifdef ENABLE_REMOTE
73619bb0b8hselasky	/*
73719bb0b8hselasky	 * If the device on which we're capturing need to be notified
73819bb0b8hselasky	 * that a new filter is being compiled, do so.
73919bb0b8hselasky	 *
74019bb0b8hselasky	 * This allows them to save a copy of it, in case, for example,
74119bb0b8hselasky	 * they're implementing a form of remote packet capture, and
74219bb0b8hselasky	 * want the remote machine to filter out the packets in which
74319bb0b8hselasky	 * it's sending the packets it's captured.
74419bb0b8hselasky	 *
74519bb0b8hselasky	 * XXX - the fact that we happen to be compiling a filter
74619bb0b8hselasky	 * doesn't necessarily mean we'll be installing it as the
74719bb0b8hselasky	 * filter for this pcap_t; we might be running it from userland
74819bb0b8hselasky	 * on captured packets to do packet classification.  We really
74919bb0b8hselasky	 * need a better way of handling this, but this is all that
750c2630c9philip	 * the WinPcap remote capture code did.
75119bb0b8hselasky	 */
75219bb0b8hselasky	if (p->save_current_filter_op != NULL)
75319bb0b8hselasky		(p->save_current_filter_op)(p, buf);
75419bb0b8hselasky#endif
75519bb0b8hselasky
75694960e5delphij	initchunks(&cstate);
75794960e5delphij	cstate.no_optimize = 0;
758104596cdelphij#ifdef INET6
75994960e5delphij	cstate.ai = NULL;
760104596cdelphij#endif
761c2630c9philip	cstate.e = NULL;
76294960e5delphij	cstate.ic.root = NULL;
76394960e5delphij	cstate.ic.cur_mark = 0;
76494960e5delphij	cstate.bpf_pcap = p;
76594960e5delphij	init_regs(&cstate);
76694960e5delphij
76794960e5delphij	cstate.netmask = mask;
768da13a5abms
76994960e5delphij	cstate.snaplen = pcap_snapshot(p);
77094960e5delphij	if (cstate.snaplen == 0) {
77194960e5delphij		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
772a6bce88fenner			 "snaplen of 0 rejects all packets");
773489abeddelphij		rc = -1;
774489abeddelphij		goto quit;
775a6bce88fenner	}
776f0fdf33pst
77794960e5delphij	if (pcap_lex_init(&scanner) != 0)
77819bb0b8hselasky		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
77919bb0b8hselasky		    errno, "can't initialize scanner");
78094960e5delphij	in_buffer = pcap__scan_string(xbuf ? xbuf : "", scanner);
78194960e5delphij
78294960e5delphij	/*
78394960e5delphij	 * Associate the compiler state with the lexical analyzer
78494960e5delphij	 * state.
78594960e5delphij	 */
78694960e5delphij	pcap_set_extra(&cstate, scanner);
787f0fdf33pst
788c2630c9philip	if (init_linktype(&cstate, p) == -1) {
789c2630c9philip		rc = -1;
790c2630c9philip		goto quit;
791c2630c9philip	}
792c2630c9philip	if (pcap_parse(scanner, &cstate) != 0) {
793c2630c9philip#ifdef INET6
794c2630c9philip		if (cstate.ai != NULL)
795c2630c9philip			freeaddrinfo(cstate.ai);
796c2630c9philip#endif
797c2630c9philip		if (cstate.e != NULL)
798c2630c9philip			free(cstate.e);
799c2630c9philip		rc = -1;
800c2630c9philip		goto quit;
801c2630c9philip	}
802f0fdf33pst
803c2630c9philip	if (cstate.ic.root == NULL) {
804c2630c9philip		/*
805c2630c9philip		 * Catch errors reported by gen_retblk().
806c2630c9philip		 */
807c2630c9philip		if (setjmp(cstate.top_ctx)) {
808c2630c9philip			rc = -1;
809c2630c9philip			goto quit;
810c2630c9philip		}
81194960e5delphij		cstate.ic.root = gen_retblk(&cstate, cstate.snaplen);
812c2630c9philip	}
813f0fdf33pst
81494960e5delphij	if (optimize && !cstate.no_optimize) {
815c2630c9philip		if (bpf_optimize(&cstate.ic, p->errbuf) == -1) {
816c2630c9philip			/* Failure */
817c2630c9philip			rc = -1;
818c2630c9philip			goto quit;
819c2630c9philip		}
82094960e5delphij		if (cstate.ic.root == NULL ||
821c2630c9philip		    (cstate.ic.root->s.code == (BPF_RET|BPF_K) && cstate.ic.root->s.k == 0)) {
822c2630c9philip			(void)pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
823c2630c9philip			    "expression rejects all packets");
824c2630c9philip			rc = -1;
825c2630c9philip			goto quit;
826c2630c9philip		}
827c2630c9philip	}
828c2630c9philip	program->bf_insns = icode_to_fcode(&cstate.ic,
829c2630c9philip	    cstate.ic.root, &len, p->errbuf);
830c2630c9philip	if (program->bf_insns == NULL) {
831c2630c9philip		/* Failure */
832c2630c9philip		rc = -1;
833c2630c9philip		goto quit;
834aae9bd2fenner	}
835aae9bd2fenner	program->bf_len = len;
836aae9bd2fenner
837489abeddelphij	rc = 0;  /* We're all okay */
838489abeddelphij
839489abeddelphijquit:
84094960e5delphij	/*
84194960e5delphij	 * Clean up everything for the lexical analyzer.
84294960e5delphij	 */
84394960e5delphij	if (in_buffer != NULL)
84494960e5delphij		pcap__delete_buffer(in_buffer, scanner);
84594960e5delphij	if (scanner != NULL)
84694960e5delphij		pcap_lex_destroy(scanner);
847489abeddelphij
84894960e5delphij	/*
84994960e5delphij	 * Clean up our own allocated memory.
85094960e5delphij	 */
85194960e5delphij	freechunks(&cstate);
852489abeddelphij
853489abeddelphij	return (rc);
854aae9bd2fenner}
855aae9bd2fenner
856aae9bd2fenner/*
857aae9bd2fenner * entry point for using the compiler with no pcap open
858aae9bd2fenner * pass in all the stuff that is needed explicitly instead.
859aae9bd2fenner */
860aae9bd2fennerint
861aae9bd2fennerpcap_compile_nopcap(int snaplen_arg, int linktype_arg,
862aae9bd2fenner		    struct bpf_program *program,
8634462427mlaier	     const char *buf, int optimize, bpf_u_int32 mask)
864aae9bd2fenner{
865a6bce88fenner	pcap_t *p;
866a6bce88fenner	int ret;
867aae9bd2fenner
868a6bce88fenner	p = pcap_open_dead(linktype_arg, snaplen_arg);
869a6bce88fenner	if (p == NULL)
870aae9bd2fenner		return (-1);
871a6bce88fenner	ret = pcap_compile(p, program, buf, optimize, mask);
872a6bce88fenner	pcap_close(p);
873a6bce88fenner	return (ret);
874a6bce88fenner}
875aae9bd2fenner
876a6bce88fenner/*
877a6bce88fenner * Clean up a "struct bpf_program" by freeing all the memory allocated
878a6bce88fenner * in it.
879a6bce88fenner */
880a6bce88fennervoid
881a6bce88fennerpcap_freecode(struct bpf_program *program)
882a6bce88fenner{
883a6bce88fenner	program->bf_len = 0;
884a6bce88fenner	if (program->bf_insns != NULL) {
885a6bce88fenner		free((char *)program->bf_insns);
886a6bce88fenner		program->bf_insns = NULL;
887f0fdf33pst	}
888f0fdf33pst}
889f0fdf33pst
890f0fdf33pst/*
891f0fdf33pst * Backpatch the blocks in 'list' to 'target'.  The 'sense' field indicates
892f0fdf33pst * which of the jt and jf fields has been resolved and which is a pointer
893f0fdf33pst * back to another unresolved block (or nil).  At least one of the fields
894f0fdf33pst * in each block is already resolved.
895f0fdf33pst */
896f0fdf33pststatic void
89719bb0b8hselaskybackpatch(struct block *list, struct block *target)
898f0fdf33pst{
899f0fdf33pst	struct block *next;
900f0fdf33pst
901f0fdf33pst	while (list) {
902f0fdf33pst		if (!list->sense) {
903f0fdf33pst			next = JT(list);
904f0fdf33pst			JT(list) = target;
905f0fdf33pst		} else {
906f0fdf33pst			next = JF(list);
907f0fdf33pst			JF(list) = target;
908f0fdf33pst		}
909f0fdf33pst		list = next;
910f0fdf33pst	}
911f0fdf33pst}
912f0fdf33pst
913f0fdf33pst/*
914f0fdf33pst * Merge the lists in b0 and b1, using the 'sense' field to indicate
915f0fdf33pst * which of jt and jf is the link.
916f0fdf33pst */
917f0fdf33pststatic void
91819bb0b8hselaskymerge(struct block *b0, struct block *b1)
919f0fdf33pst{
920f0fdf33pst	register struct block **p = &b0;
921f0fdf33pst
922f0fdf33pst	/* Find end of list. */
923f0fdf33pst	while (*p)
924f0fdf33pst		p = !((*p)->sense) ? &JT(*p) : &JF(*p);
925f0fdf33pst
926f0fdf33pst	/* Concatenate the lists. */
927f0fdf33pst	*p = b1;
928f0fdf33pst}
929f0fdf33pst
930c2630c9philipint
93194960e5delphijfinish_parse(compiler_state_t *cstate, struct block *p)
932f0fdf33pst{
9334462427mlaier	struct block *ppi_dlt_check;
934d1c1ca6sam
935d1c1ca6sam	/*
936c2630c9philip	 * Catch errors reported by us and routines below us, and return -1
937c2630c9philip	 * on an error.
938c2630c9philip	 */
939c2630c9philip	if (setjmp(cstate->top_ctx))
940c2630c9philip		return (-1);
941c2630c9philip
942c2630c9philip	/*
943d1c1ca6sam	 * Insert before the statements of the first (root) block any
944d1c1ca6sam	 * statements needed to load the lengths of any variable-length
945d1c1ca6sam	 * headers into registers.
946d1c1ca6sam	 *
947d1c1ca6sam	 * XXX - a fancier strategy would be to insert those before the
948d1c1ca6sam	 * statements of all blocks that use those lengths and that
949d1c1ca6sam	 * have no predecessors that use them, so that we only compute
950d1c1ca6sam	 * the lengths if we need them.  There might be even better
951d8d18f6rpaulo	 * approaches than that.
952d8d18f6rpaulo	 *
953d8d18f6rpaulo	 * However, those strategies would be more complicated, and
954d8d18f6rpaulo	 * as we don't generate code to compute a length if the
955d8d18f6rpaulo	 * program has no tests that use the length, and as most
956d8d18f6rpaulo	 * tests will probably use those lengths, we would just
957d8d18f6rpaulo	 * postpone computing the lengths so that it's not done
958d8d18f6rpaulo	 * for tests that fail early, and it's not clear that's
959d8d18f6rpaulo	 * worth the effort.
960d1c1ca6sam	 */
96194960e5delphij	insert_compute_vloffsets(cstate, p->head);
962489abeddelphij
963d8d18f6rpaulo	/*
964d8d18f6rpaulo	 * For DLT_PPI captures, generate a check of the per-packet
965d8d18f6rpaulo	 * DLT value to make sure it's DLT_IEEE802_11.
96694960e5delphij	 *
96794960e5delphij	 * XXX - TurboCap cards use DLT_PPI for Ethernet.
96894960e5delphij	 * Can we just define some DLT_ETHERNET_WITH_PHDR pseudo-header
96994960e5delphij	 * with appropriate Ethernet information and use that rather
97094960e5delphij	 * than using something such as DLT_PPI where you don't know
97194960e5delphij	 * the link-layer header type until runtime, which, in the
97294960e5delphij	 * general case, would force us to generate both Ethernet *and*
97394960e5delphij	 * 802.11 code (*and* anything else for which PPI is used)
97494960e5delphij	 * and choose between them early in the BPF program?
975d8d18f6rpaulo	 */
97694960e5delphij	ppi_dlt_check = gen_ppi_dlt_check(cstate);
977d8d18f6rpaulo	if (ppi_dlt_check != NULL)
978d8d18f6rpaulo		gen_and(ppi_dlt_check, p);
9794462427mlaier
98094960e5delphij	backpatch(p, gen_retblk(cstate, cstate->snaplen));
981d8d18f6rpaulo	p->sense = !p->sense;
98294960e5delphij	backpatch(p, gen_retblk(cstate, 0));
98394960e5delphij	cstate->ic.root = p->head;
984c2630c9philip	return (0);
985f0fdf33pst}
986f0fdf33pst
987f0fdf33pstvoid
98819bb0b8hselaskygen_and(struct block *b0, struct block *b1)
989f0fdf33pst{
990f0fdf33pst	backpatch(b0, b1->head);
991f0fdf33pst	b0->sense = !b0->sense;
992f0fdf33pst	b1->sense = !b1->sense;
993f0fdf33pst	merge(b1, b0);
994f0fdf33pst	b1->sense = !b1->sense;
995f0fdf33pst	b1->head = b0->head;
996f0fdf33pst}
997f0fdf33pst
998f0fdf33pstvoid
99919bb0b8hselaskygen_or(struct block *b0, struct block *b1)
1000f0fdf33pst{
1001f0fdf33pst	b0->sense = !b0->sense;
1002f0fdf33pst	backpatch(b0, b1->head);
1003f0fdf33pst	b0->sense = !b0->sense;
1004f0fdf33pst	merge(b1, b0);
1005f0fdf33pst	b1->head = b0->head;
1006f0fdf33pst}
1007f0fdf33pst
1008f0fdf33pstvoid
100919bb0b8hselaskygen_not(struct block *b)
1010f0fdf33pst{
1011f0fdf33pst	b->sense = !b->sense;
1012f0fdf33pst}
1013f0fdf33pst
1014f0fdf33pststatic struct block *
101594960e5delphijgen_cmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
101694960e5delphij    u_int size, bpf_int32 v)
1017f0fdf33pst{
101894960e5delphij	return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v);
1019f0fdf33pst}
1020f0fdf33pst
1021f0fdf33pststatic struct block *
102294960e5delphijgen_cmp_gt(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
102394960e5delphij    u_int size, bpf_int32 v)
1024a6bce88fenner{
102594960e5delphij	return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGT, 0, v);
1026d1c1ca6sam}
1027a6bce88fenner
1028d1c1ca6samstatic struct block *
102994960e5delphijgen_cmp_ge(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
103094960e5delphij    u_int size, bpf_int32 v)
1031d1c1ca6sam{
103294960e5delphij	return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGE, 0, v);
1033d1c1ca6sam}
1034a6bce88fenner
1035d1c1ca6samstatic struct block *
103694960e5delphijgen_cmp_lt(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
103794960e5delphij    u_int size, bpf_int32 v)
1038d1c1ca6sam{
103994960e5delphij	return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGE, 1, v);
1040d1c1ca6sam}
1041a6bce88fenner
1042d1c1ca6samstatic struct block *
104394960e5delphijgen_cmp_le(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
104494960e5delphij    u_int size, bpf_int32 v)
1045d1c1ca6sam{
104694960e5delphij	return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGT, 1, v);
1047a6bce88fenner}
1048a6bce88fenner
1049a6bce88fennerstatic struct block *
105094960e5delphijgen_mcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
105194960e5delphij    u_int size, bpf_int32 v, bpf_u_int32 mask)
1052f0fdf33pst{
105394960e5delphij	return gen_ncmp(cstate, offrel, offset, size, mask, BPF_JEQ, 0, v);
1054f0fdf33pst}
1055f0fdf33pst
1056f0fdf33pststatic struct block *
105794960e5delphijgen_bcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
105894960e5delphij    u_int size, const u_char *v)
1059f0fdf33pst{
1060f0fdf33pst	register struct block *b, *tmp;
1061f0fdf33pst
1062c2630c9philip	/*
1063c2630c9philip	 * XXX - the actual *instructions* do unsigned comparisons on
1064c2630c9philip	 * most platforms, and the load instructions don't do sign
1065c2630c9philip	 * extension, so gen_cmp() should really take an unsigned
1066c2630c9philip	 * value argument.
1067c2630c9philip	 *
1068c2630c9philip	 * As the load instructons also don't do sign-extension, we
1069c2630c9philip	 * fetch the values from the byte array as unsigned.  We don't
1070c2630c9philip	 * want to use the signed versions of the extract calls.
1071c2630c9philip	 */
1072f0fdf33pst	b = NULL;
1073f0fdf33pst	while (size >= 4) {
1074f0fdf33pst		register const u_char *p = &v[size - 4];
1075f0fdf33pst
1076c2630c9philip		tmp = gen_cmp(cstate, offrel, offset + size - 4, BPF_W,
1077c2630c9philip		    (bpf_int32)EXTRACT_32BITS(p));
1078f0fdf33pst		if (b != NULL)
1079f0fdf33pst			gen_and(b, tmp);
1080f0fdf33pst		b = tmp;
1081f0fdf33pst		size -= 4;
1082f0fdf33pst	}
1083f0fdf33pst	while (size >= 2) {
1084f0fdf33pst		register const u_char *p = &v[size - 2];
1085f0fdf33pst
1086c2630c9philip		tmp = gen_cmp(cstate, offrel, offset + size - 2, BPF_H,
1087c2630c9philip		    (bpf_int32)EXTRACT_16BITS(p));
1088f0fdf33pst		if (b != NULL)
1089f0fdf33pst			gen_and(b, tmp);
1090f0fdf33pst		b = tmp;
1091f0fdf33pst		size -= 2;
1092f0fdf33pst	}
1093f0fdf33pst	if (size > 0) {
109494960e5delphij		tmp = gen_cmp(cstate, offrel, offset, BPF_B, (bpf_int32)v[0]);
1095f0fdf33pst		if (b != NULL)
1096f0fdf33pst			gen_and(b, tmp);
1097f0fdf33pst		b = tmp;
1098f0fdf33pst	}
1099f0fdf33pst	return b;
1100f0fdf33pst}
1101f0fdf33pst
1102d1c1ca6sam/*
1103d1c1ca6sam * AND the field of size "size" at offset "offset" relative to the header
1104d1c1ca6sam * specified by "offrel" with "mask", and compare it with the value "v"
1105d1c1ca6sam * with the test specified by "jtype"; if "reverse" is true, the test
1106d1c1ca6sam * should test the opposite of "jtype".
1107d1c1ca6sam */
1108da13a5abmsstatic struct block *
110994960e5delphijgen_ncmp(compiler_state_t *cstate, enum e_offrel offrel, bpf_u_int32 offset,
111094960e5delphij    bpf_u_int32 size, bpf_u_int32 mask, bpf_u_int32 jtype, int reverse,
111194960e5delphij    bpf_int32 v)
1112da13a5abms{
1113d1c1ca6sam	struct slist *s, *s2;
1114da13a5abms	struct block *b;
111570f7ae4sam
111694960e5delphij	s = gen_load_a(cstate, offrel, offset, size);
111770f7ae4sam
1118da13a5abms	if (mask != 0xffffffff) {
111994960e5delphij		s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
1120d1c1ca6sam		s2->s.k = mask;
1121d1c1ca6sam		sappend(s, s2);
1122da13a5abms	}
112370f7ae4sam
112494960e5delphij	b = new_block(cstate, JMP(jtype));
1125da13a5abms	b->stmts = s;
1126d1c1ca6sam	b->s.k = v;
1127da13a5abms	if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE))
1128da13a5abms		gen_not(b);
1129da13a5abms	return b;
1130da13a5abms}
1131da13a5abms
1132c2630c9philipstatic int
113394960e5delphijinit_linktype(compiler_state_t *cstate, pcap_t *p)
113494960e5delphij{
113594960e5delphij	cstate->pcap_fddipad = p->fddipad;
11364462427mlaier
113794960e5delphij	/*
113894960e5delphij	 * We start out with only one link-layer header.
113994960e5delphij	 */
114094960e5delphij	cstate->outermostlinktype = pcap_datalink(p);
114194960e5delphij	cstate->off_outermostlinkhdr.constant_part = 0;
114294960e5delphij	cstate->off_outermostlinkhdr.is_variable = 0;
114394960e5delphij	cstate->off_outermostlinkhdr.reg = -1;
1144d1c1ca6sam
114594960e5delphij	cstate->prevlinktype = cstate->outermostlinktype;
114694960e5delphij	cstate->off_prevlinkhdr.constant_part = 0;
114794960e5delphij	cstate->off_prevlinkhdr.is_variable = 0;
114894960e5delphij	cstate->off_prevlinkhdr.reg = -1;
1149da13a5abms
115094960e5delphij	cstate->linktype = cstate->outermostlinktype;
115194960e5delphij	cstate->off_linkhdr.constant_part = 0;
115294960e5delphij	cstate->off_linkhdr.is_variable = 0;
115394960e5delphij	cstate->off_linkhdr.reg = -1;
1154da13a5abms
115594960e5delphij	/*
115694960e5delphij	 * XXX
115794960e5delphij	 */
115894960e5delphij	cstate->off_linkpl.constant_part = 0;
115994960e5delphij	cstate->off_linkpl.is_variable = 0;
116094960e5delphij	cstate->off_linkpl.reg = -1;
1161f0fdf33pst
116294960e5delphij	cstate->off_linktype.constant_part = 0;
116394960e5delphij	cstate->off_linktype.is_variable = 0;
116494960e5delphij	cstate->off_linktype.reg = -1;
1165f0fdf33pst
1166da13a5abms	/*
1167da13a5abms	 * Assume it's not raw ATM with a pseudo-header, for now.
1168da13a5abms	 */
116994960e5delphij	cstate->is_atm = 0;
117019bb0b8hselasky	cstate->off_vpi = OFFSET_NOT_SET;
117119bb0b8hselasky	cstate->off_vci = OFFSET_NOT_SET;
117219bb0b8hselasky	cstate->off_proto = OFFSET_NOT_SET;
117319bb0b8hselasky	cstate->off_payload = OFFSET_NOT_SET;
1174da13a5abms
1175ffd4bfbsam	/*
117694960e5delphij	 * And not Geneve.
1177d8d18f6rpaulo	 */
117894960e5delphij	cstate->is_geneve = 0;
1179d8d18f6rpaulo
1180d8d18f6rpaulo	/*
118119bb0b8hselasky	 * No variable length VLAN offset by default
118219bb0b8hselasky	 */
118319bb0b8hselasky	cstate->is_vlan_vloffset = 0;
118419bb0b8hselasky
118519bb0b8hselasky	/*
1186ffd4bfbsam	 * And assume we're not doing SS7.
1187ffd4bfbsam	 */
118819bb0b8hselasky	cstate->off_li = OFFSET_NOT_SET;
118919bb0b8hselasky	cstate->off_li_hsl = OFFSET_NOT_SET;
119019bb0b8hselasky	cstate->off_sio = OFFSET_NOT_SET;
119119bb0b8hselasky	cstate->off_opc = OFFSET_NOT_SET;
119219bb0b8hselasky	cstate->off_dpc = OFFSET_NOT_SET;
119319bb0b8hselasky	cstate->off_sls = OFFSET_NOT_SET;
1194d1c1ca6sam
119594960e5delphij	cstate->label_stack_depth = 0;
119694960e5delphij	cstate->vlan_stack_depth = 0;
1197d1c1ca6sam
119894960e5delphij	switch (cstate->linktype) {
1199f0fdf33pst
12001e8ea46fenner	case DLT_ARCNET:
120194960e5delphij		cstate->off_linktype.constant_part = 2;
120294960e5delphij		cstate->off_linkpl.constant_part = 6;
120319bb0b8hselasky		cstate->off_nl = 0;		/* XXX in reality, variable! */
120494960e5delphij		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
120594960e5delphij		break;
12061e8ea46fenner
1207da13a5abms	case DLT_ARCNET_LINUX:
120894960e5delphij		cstate->off_linktype.constant_part = 4;
120994960e5delphij		cstate->off_linkpl.constant_part = 8;
121094960e5delphij		cstate->off_nl = 0;		/* XXX in reality, variable! */
121194960e5delphij		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
121294960e5delphij		break;
121334111fdfenner
1214f0fdf33pst	case DLT_EN10MB:
121594960e5delphij		cstate->off_linktype.constant_part = 12;
121694960e5delphij		cstate->off_linkpl.constant_part = 14;	/* Ethernet header length */
121794960e5delphij		cstate->off_nl = 0;		/* Ethernet II */
121894960e5delphij		cstate->off_nl_nosnap = 3;	/* 802.3+802.2 */
121994960e5delphij		break;
1220f0fdf33pst
1221f0fdf33pst	case DLT_SLIP:
1222f0fdf33pst		/*
1223f0fdf33pst		 * SLIP doesn't have a link level type.  The 16 byte
1224f0fdf33pst		 * header is hacked into our SLIP driver.
1225f0fdf33pst		 */
122694960e5delphij		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
122794960e5delphij		cstate->off_linkpl.constant_part = 16;
122894960e5delphij		cstate->off_nl = 0;
122994960e5delphij		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
123094960e5delphij		break;
1231f0fdf33pst
1232ca0d84cfenner	case DLT_SLIP_BSDOS:
1233ca0d84cfenner		/* XXX this may be the same as the DLT_PPP_BSDOS case */
123494960e5delphij		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
1235ca0d84cfenner		/* XXX end */
123694960e5delphij		cstate->off_linkpl.constant_part = 24;
123794960e5delphij		cstate->off_nl = 0;
123894960e5delphij		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
123994960e5delphij		break;
1240ca0d84cfenner
1241f0fdf33pst	case DLT_NULL:
1242a6bce88fenner	case DLT_LOOP:
124394960e5delphij		cstate->off_linktype.constant_part = 0;
124494960e5delphij		cstate->off_linkpl.constant_part = 4;
124594960e5delphij		cstate->off_nl = 0;
124694960e5delphij		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
124794960e5delphij		break;
1248da13a5abms
1249da13a5abms	case DLT_ENC:
125094960e5delphij		cstate->off_linktype.constant_part = 0;
125194960e5delphij		cstate->off_linkpl.constant_part = 12;
125294960e5delphij		cstate->off_nl = 0;
125394960e5delphij		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
125494960e5delphij		break;
1255f0fdf33pst
1256f0fdf33pst	case DLT_PPP:
125770f7ae4sam	case DLT_PPP_PPPD:
12581e8ea46fenner	case DLT_C_HDLC:		/* BSD/OS Cisco HDLC */
12591e8ea46fenner	case DLT_PPP_SERIAL:		/* NetBSD sync/async serial PPP */
126094960e5delphij		cstate->off_linktype.constant_part = 2;	/* skip HDLC-like framing */
126194960e5delphij		cstate->off_linkpl.constant_part = 4;	/* skip HDLC-like framing and protocol field */
126294960e5delphij		cstate->off_nl = 0;
126394960e5delphij		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
126494960e5delphij		break;
1265f0fdf33pst
12661e8ea46fenner	case DLT_PPP_ETHER:
12671e8ea46fenner		/*
12681e8ea46fenner		 * This does no include the Ethernet header, and
12691e8ea46fenner		 * only covers session state.
12701e8ea46fenner		 */
127194960e5delphij		cstate->off_linktype.constant_part = 6;
127294960e5delphij		cstate->off_linkpl.constant_part = 8;
127394960e5delphij		cstate->off_nl = 0;
127494960e5delphij		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
127594960e5delphij		break;
12761e8ea46fenner
1277ca0d84cfenner	case DLT_PPP_BSDOS:
127894960e5delphij		cstate->off_linktype.constant_part = 5;
127994960e5delphij		cstate->off_linkpl.constant_part = 24;
128094960e5delphij		cstate->off_nl = 0;
128194960e5delphij		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
128294960e5delphij		break;
1283ca0d84cfenner
1284f0fdf33pst	case DLT_FDDI:
1285f0fdf33pst		/*
1286f0fdf33pst		 * FDDI doesn't really have a link-level type field.
12871e8ea46fenner		 * We set "off_linktype" to the offset of the LLC header.
1288a6bce88fenner		 *
12891e8ea46fenner		 * To check for Ethernet types, we assume that SSAP = SNAP
12901e8ea46fenner		 * is being used and pick out the encapsulated Ethernet type.
1291a6bce88fenner		 * XXX - should we generate code to check for SNAP?
1292f0fdf33pst		 */
129394960e5delphij		cstate->off_linktype.constant_part = 13;
129494960e5delphij		cstate->off_linktype.constant_part += cstate->pcap_fddipad;
129594960e5delphij		cstate->off_linkpl.constant_part = 13;	/* FDDI MAC header length */
129694960e5delphij		cstate->off_linkpl.constant_part += cstate->pcap_fddipad;
129794960e5delphij		cstate->off_nl = 8;		/* 802.2+SNAP */
129894960e5delphij		cstate->off_nl_nosnap = 3;	/* 802.2 */
129994960e5delphij		break;
1300f0fdf33pst
1301f0fdf33pst	case DLT_IEEE802:
1302a6bce88fenner		/*
1303a6bce88fenner		 * Token Ring doesn't really have a link-level type field.
13041e8ea46fenner		 * We set "off_linktype" to the offset of the LLC header.
1305a6bce88fenner		 *
13061e8ea46fenner		 * To check for Ethernet types, we assume that SSAP = SNAP
13071e8ea46fenner		 * is being used and pick out the encapsulated Ethernet type.
1308a6bce88fenner		 * XXX - should we generate code to check for SNAP?
1309a6bce88fenner		 *
1310a6bce88fenner		 * XXX - the header is actually variable-length.
1311a6bce88fenner		 * Some various Linux patched versions gave 38
1312a6bce88fenner		 * as "off_linktype" and 40 as "off_nl"; however,
1313a6bce88fenner		 * if a token ring packet has *no* routing
1314a6bce88fenner		 * information, i.e. is not source-routed, the correct
1315a6bce88fenner		 * values are 20 and 22, as they are in the vanilla code.
1316a6bce88fenner		 *
1317a6bce88fenner		 * A packet is source-routed iff the uppermost bit
1318a6bce88fenner		 * of the first byte of the source address, at an
1319a6bce88fenner		 * offset of 8, has the uppermost bit set.  If the
1320a6bce88fenner		 * packet is source-routed, the total number of bytes
1321a6bce88fenner		 * of routing information is 2 plus bits 0x1F00 of
1322a6bce88fenner		 * the 16-bit value at an offset of 14 (shifted right
1323a6bce88fenner		 * 8 - figure out which byte that is).
1324a6bce88fenner		 */
132594960e5delphij		cstate->off_linktype.constant_part = 14;
132694960e5delphij		cstate->off_linkpl.constant_part = 14;	/* Token Ring MAC header length */
132794960e5delphij		cstate->off_nl = 8;		/* 802.2+SNAP */
132894960e5delphij		cstate->off_nl_nosnap = 3;	/* 802.2 */
132994960e5delphij		break;
1330f0fdf33pst
1331d8d18f6rpaulo	case DLT_PRISM_HEADER:
1332d8d18f6rpaulo	case DLT_IEEE802_11_RADIO_AVS:
1333d8d18f6rpaulo	case DLT_IEEE802_11_RADIO:
133494960e5delphij		cstate->off_linkhdr.is_variable = 1;
133594960e5delphij		/* Fall through, 802.11 doesn't have a variable link
133694960e5delphij		 * prefix but is otherwise the same. */
1337c2630c9philip		/* FALLTHROUGH */
133894960e5delphij
133994960e5delphij	case DLT_IEEE802_11:
13401e8ea46fenner		/*
13411e8ea46fenner		 * 802.11 doesn't really have a link-level type field.
134294960e5delphij		 * We set "off_linktype.constant_part" to the offset of
134394960e5delphij		 * the LLC header.
13441e8ea46fenner		 *
13451e8ea46fenner		 * To check for Ethernet types, we assume that SSAP = SNAP
13461e8ea46fenner		 * is being used and pick out the encapsulated Ethernet type.
13471e8ea46fenner		 * XXX - should we generate code to check for SNAP?
13481e8ea46fenner		 *
1349d8d18f6rpaulo		 * We also handle variable-length radio headers here.
1350d8d18f6rpaulo		 * The Prism header is in theory variable-length, but in
1351d8d18f6rpaulo		 * practice it's always 144 bytes long.  However, some
1352d8d18f6rpaulo		 * drivers on Linux use ARPHRD_IEEE80211_PRISM, but
1353d8d18f6rpaulo		 * sometimes or always supply an AVS header, so we
1354d8d18f6rpaulo		 * have to check whether the radio header is a Prism
1355d8d18f6rpaulo		 * header or an AVS header, so, in practice, it's
1356d8d18f6rpaulo		 * variable-length.
13571e8ea46fenner		 */
135894960e5delphij		cstate->off_linktype.constant_part = 24;
135994960e5delphij		cstate->off_linkpl.constant_part = 0;	/* link-layer header is variable-length */
136094960e5delphij		cstate->off_linkpl.is_variable = 1;
136194960e5delphij		cstate->off_nl = 8;		/* 802.2+SNAP */
136294960e5delphij		cstate->off_nl_nosnap = 3;	/* 802.2 */
136394960e5delphij		break;
1364da13a5abms
13654462427mlaier	case DLT_PPI:
1366489abeddelphij		/*
1367d8d18f6rpaulo		 * At the moment we treat PPI the same way that we treat
1368d8d18f6rpaulo		 * normal Radiotap encoded packets. The difference is in
1369d8d18f6rpaulo		 * the function that generates the code at the beginning
1370d8d18f6rpaulo		 * to compute the header length.  Since this code generator
1371d8d18f6rpaulo		 * of PPI supports bare 802.11 encapsulation only (i.e.
1372d8d18f6rpaulo		 * the encapsulated DLT should be DLT_IEEE802_11) we
1373d8d18f6rpaulo		 * generate code to check for this too.
1374da13a5abms		 */
137594960e5delphij		cstate->off_linktype.constant_part = 24;
137694960e5delphij		cstate->off_linkpl.constant_part = 0;	/* link-layer header is variable-length */
137794960e5delphij		cstate->off_linkpl.is_variable = 1;
137894960e5delphij		cstate->off_linkhdr.is_variable = 1;
137994960e5delphij		cstate->off_nl = 8;		/* 802.2+SNAP */
138094960e5delphij		cstate->off_nl_nosnap = 3;	/* 802.2 */
138194960e5delphij		break;
13821e8ea46fenner
1383f0fdf33pst	case DLT_ATM_RFC1483:
1384da13a5abms	case DLT_ATM_CLIP:	/* Linux ATM defines this */
1385f0fdf33pst		/*
1386f0fdf33pst		 * assume routed, non-ISO PDUs
1387f0fdf33pst		 * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00)
1388d1c1ca6sam		 *
1389d1c1ca6sam		 * XXX - what about ISO PDUs, e.g. CLNP, ISIS, ESIS,
1390d1c1ca6sam		 * or PPP with the PPP NLPID (e.g., PPPoA)?  The
1391d1c1ca6sam		 * latter would presumably be treated the way PPPoE
1392d1c1ca6sam		 * should be, so you can do "pppoe and udp port 2049"
1393d1c1ca6sam		 * or "pppoa and tcp port 80" and have it check for
1394d1c1ca6sam		 * PPPo{A,E} and a PPP protocol of IP and....
1395f0fdf33pst		 */
139694960e5delphij		cstate->off_linktype.constant_part = 0;
139794960e5delphij		cstate->off_linkpl.constant_part = 0;	/* packet begins with LLC header */
139894960e5delphij		cstate->off_nl = 8;		/* 802.2+SNAP */
139994960e5delphij		cstate->off_nl_nosnap = 3;	/* 802.2 */
140094960e5delphij		break;
1401da13a5abms
1402da13a5abms	case DLT_SUNATM:
1403da13a5abms		/*
1404da13a5abms		 * Full Frontal ATM; you get AALn PDUs with an ATM
1405da13a5abms		 * pseudo-header.
1406da13a5abms		 */
140794960e5delphij		cstate->is_atm = 1;
140894960e5delphij		cstate->off_vpi = SUNATM_VPI_POS;
140994960e5delphij		cstate->off_vci = SUNATM_VCI_POS;
141094960e5delphij		cstate->off_proto = PROTO_POS;
141194960e5delphij		cstate->off_payload = SUNATM_PKT_BEGIN_POS;
141294960e5delphij		cstate->off_linktype.constant_part = cstate->off_payload;
141394960e5delphij		cstate->off_linkpl.constant_part = cstate->off_payload;	/* if LLC-encapsulated */
141494960e5delphij		cstate->off_nl = 8;		/* 802.2+SNAP */
141594960e5delphij		cstate->off_nl_nosnap = 3;	/* 802.2 */
141694960e5delphij		break;
1417737558afenner
1418737558afenner	case DLT_RAW:
1419724e1a0rpaulo	case DLT_IPV4:
1420724e1a0rpaulo	case DLT_IPV6:
142194960e5delphij		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
142294960e5delphij		cstate->off_linkpl.constant_part = 0;
142394960e5delphij		cstate->off_nl = 0;
142494960e5delphij		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
142594960e5delphij		break;
1426a6bce88fenner
1427c2630c9philip	case DLT_LINUX_SLL:	/* fake header for Linux cooked socket v1 */
142894960e5delphij		cstate->off_linktype.constant_part = 14;
142994960e5delphij		cstate->off_linkpl.constant_part = 16;
143094960e5delphij		cstate->off_nl = 0;
143194960e5delphij		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
143294960e5delphij		break;
14331e8ea46fenner
1434c2630c9philip	case DLT_LINUX_SLL2:	/* fake header for Linux cooked socket v2 */
1435c2630c9philip		cstate->off_linktype.constant_part = 0;
1436c2630c9philip		cstate->off_linkpl.constant_part = 20;
1437c2630c9philip		cstate->off_nl = 0;
1438c2630c9philip		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
1439c2630c9philip		break;
1440c2630c9philip
14411e8ea46fenner	case DLT_LTALK:
14421e8ea46fenner		/*
14431e8ea46fenner		 * LocalTalk does have a 1-byte type field in the LLAP header,
14441e8ea46fenner		 * but really it just indicates whether there is a "short" or
14451e8ea46fenner		 * "long" DDP packet following.
14461e8ea46fenner		 */
144794960e5delphij		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
144894960e5delphij		cstate->off_linkpl.constant_part = 0;
144994960e5delphij		cstate->off_nl = 0;
145094960e5delphij		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
145194960e5delphij		break;
1452da13a5abms
1453da13a5abms	case DLT_IP_OVER_FC:
1454da13a5abms		/*
1455da13a5abms		 * RFC 2625 IP-over-Fibre-Channel doesn't really have a
1456da13a5abms		 * link-level type field.  We set "off_linktype" to the
1457da13a5abms		 * offset of the LLC header.
1458da13a5abms		 *
1459da13a5abms		 * To check for Ethernet types, we assume that SSAP = SNAP
1460da13a5abms		 * is being used and pick out the encapsulated Ethernet type.
1461da13a5abms		 * XXX - should we generate code to check for SNAP? RFC
1462da13a5abms		 * 2625 says SNAP should be used.
1463da13a5abms		 */
146494960e5delphij		cstate->off_linktype.constant_part = 16;
146594960e5delphij		cstate->off_linkpl.constant_part = 16;
146694960e5delphij		cstate->off_nl = 8;		/* 802.2+SNAP */
146794960e5delphij		cstate->off_nl_nosnap = 3;	/* 802.2 */
146894960e5delphij		break;
1469da13a5abms
1470da13a5abms	case DLT_FRELAY:
1471da13a5abms		/*
1472da13a5abms		 * XXX - we should set this to handle SNAP-encapsulated
1473da13a5abms		 * frames (NLPID of 0x80).
1474da13a5abms		 */
147594960e5delphij		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
147694960e5delphij		cstate->off_linkpl.constant_part = 0;
147794960e5delphij		cstate->off_nl = 0;
147894960e5delphij		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
147994960e5delphij		break;
1480da13a5abms
14814462427mlaier                /*
14824462427mlaier                 * the only BPF-interesting FRF.16 frames are non-control frames;
14834462427mlaier                 * Frame Relay has a variable length link-layer
14844462427mlaier                 * so lets start with offset 4 for now and increments later on (FIXME);
14854462427mlaier                 */
14864462427mlaier	case DLT_MFR:
148794960e5delphij		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
148894960e5delphij		cstate->off_linkpl.constant_part = 0;
148994960e5delphij		cstate->off_nl = 4;
149094960e5delphij		cstate->off_nl_nosnap = 0;	/* XXX - for now -> no 802.2 LLC */
149194960e5delphij		break;
14924462427mlaier
1493da13a5abms	case DLT_APPLE_IP_OVER_IEEE1394:
149494960e5delphij		cstate->off_linktype.constant_part = 16;
149594960e5delphij		cstate->off_linkpl.constant_part = 18;
149694960e5delphij		cstate->off_nl = 0;
149794960e5delphij		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
149894960e5delphij		break;
1499da13a5abms
150070f7ae4sam	case DLT_SYMANTEC_FIREWALL:
150194960e5delphij		cstate->off_linktype.constant_part = 6;
150294960e5delphij		cstate->off_linkpl.constant_part = 44;
150394960e5delphij		cstate->off_nl = 0;		/* Ethernet II */
150494960e5delphij		cstate->off_nl_nosnap = 0;	/* XXX - what does it do with 802.3 packets? */
150594960e5delphij		break;
150670f7ae4sam
15074462427mlaier#ifdef HAVE_NET_PFVAR_H
1508da13a5abms	case DLT_PFLOG:
150994960e5delphij		cstate->off_linktype.constant_part = 0;
151094960e5delphij		cstate->off_linkpl.constant_part = PFLOG_HDRLEN;
151194960e5delphij		cstate->off_nl = 0;
151294960e5delphij		cstate->off_nl_nosnap = 0;	/* no 802.2 LLC */
151394960e5delphij		break;
15144462427mlaier#endif
1515da13a5abms
1516ffd4bfbsam        case DLT_JUNIPER_MFR:
151770f7ae4sam        case DLT_JUNIPER_MLFR:
151870f7ae4sam        case DLT_JUNIPER_MLPPP:
1519ffd4bfbsam        case DLT_JUNIPER_PPP:
1520ffd4bfbsam        case DLT_JUNIPER_CHDLC:
1521ffd4bfbsam        case DLT_JUNIPER_FRELAY:
152294960e5delphij		cstate->off_linktype.constant_part = 4;
152394960e5delphij		cstate->off_linkpl.constant_part = 4;
152494960e5delphij		cstate->off_nl = 0;
152519bb0b8hselasky		cstate->off_nl_nosnap = OFFSET_NOT_SET;	/* no 802.2 LLC */
152694960e5delphij                break;
152770f7ae4sam
152870f7ae4sam	case DLT_JUNIPER_ATM1:
152994960e5delphij		cstate->off_linktype.constant_part = 4;		/* in reality variable between 4-8 */
153094960e5delphij		cstate->off_linkpl.constant_part = 4;	/* in reality variable between 4-8 */
153194960e5delphij		cstate->off_nl = 0;
153294960e5delphij		cstate->off_nl_nosnap = 10;
153394960e5delphij		break;
153470f7ae4sam
153570f7ae4sam	case DLT_JUNIPER_ATM2:
153694960e5delphij		cstate->off_linktype.constant_part = 8;		/* in reality variable between 8-12 */
153794960e5delphij		cstate->off_linkpl.constant_part = 8;	/* in reality variable between 8-12 */
153894960e5delphij		cstate->off_nl = 0;
153994960e5delphij		cstate->off_nl_nosnap = 10;
154094960e5delphij		break;
154170f7ae4sam
1542d1c1ca6sam		/* frames captured on a Juniper PPPoE service PIC
1543d1c1ca6sam		 * contain raw ethernet frames */
1544d1c1ca6sam	case DLT_JUNIPER_PPPOE:
1545ffd4bfbsam        case DLT_JUNIPER_ETHER:
154694960e5delphij		cstate->off_linkpl.constant_part = 14;
154794960e5delphij		cstate->off_linktype.constant_part = 16;
154894960e5delphij		cstate->off_nl = 18;		/* Ethernet II */
154994960e5delphij		cstate->off_nl_nosnap = 21;	/* 802.3+802.2 */
155094960e5delphij		break;
1551d1c1ca6sam
1552d1c1ca6sam	case DLT_JUNIPER_PPPOE_ATM:
155394960e5delphij		cstate->off_linktype.constant_part = 4;
155494960e5delphij		cstate->off_linkpl.constant_part = 6;
155594960e5delphij		cstate->off_nl = 0;
155619bb0b8hselasky		cstate->off_nl_nosnap = OFFSET_NOT_SET;	/* no 802.2 LLC */
155794960e5delphij		break;
1558d1c1ca6sam
1559d1c1ca6sam	case DLT_JUNIPER_GGSN:
156094960e5delphij		cstate->off_linktype.constant_part = 6;
156194960e5delphij		cstate->off_linkpl.constant_part = 12;
156294960e5delphij		cstate->off_nl = 0;
156319bb0b8hselasky		cstate->off_nl_nosnap = OFFSET_NOT_SET;	/* no 802.2 LLC */
156494960e5delphij		break;
1565d1c1ca6sam
1566d1c1ca6sam	case DLT_JUNIPER_ES:
156794960e5delphij		cstate->off_linktype.constant_part = 6;
156894960e5delphij		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;	/* not really a network layer but raw IP addresses */
156919bb0b8hselasky		cstate->off_nl = OFFSET_NOT_SET;	/* not really a network layer but raw IP addresses */
157019bb0b8hselasky		cstate->off_nl_nosnap = OFFSET_NOT_SET;	/* no 802.2 LLC */
157194960e5delphij		break;
1572d1c1ca6sam
1573d1c1ca6sam	case DLT_JUNIPER_MONITOR:
157494960e5delphij		cstate->off_linktype.constant_part = 12;
157594960e5delphij		cstate->off_linkpl.constant_part = 12;
157619bb0b8hselasky		cstate->off_nl = 0;			/* raw IP/IP6 header */
157719bb0b8hselasky		cstate->off_nl_nosnap = OFFSET_NOT_SET;	/* no 802.2 LLC */
157894960e5delphij		break;
1579d1c1ca6sam
1580489abeddelphij	case DLT_BACNET_MS_TP:
158194960e5delphij		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
158294960e5delphij		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
158319bb0b8hselasky		cstate->off_nl = OFFSET_NOT_SET;
158419bb0b8hselasky		cstate->off_nl_nosnap = OFFSET_NOT_SET;
158594960e5delphij		break;
1586489abeddelphij
1587d1c1ca6sam	case DLT_JUNIPER_SERVICES:
158894960e5delphij		cstate->off_linktype.constant_part = 12;
158994960e5delphij		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;	/* L3 proto location dep. on cookie type */
159019bb0b8hselasky		cstate->off_nl = OFFSET_NOT_SET;	/* L3 proto location dep. on cookie type */
159119bb0b8hselasky		cstate->off_nl_nosnap = OFFSET_NOT_SET;	/* no 802.2 LLC */
159294960e5delphij		break;
1593d1c1ca6sam
15944462427mlaier	case DLT_JUNIPER_VP:
159594960e5delphij		cstate->off_linktype.constant_part = 18;
159694960e5delphij		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
159719bb0b8hselasky		cstate->off_nl = OFFSET_NOT_SET;
159819bb0b8hselasky		cstate->off_nl_nosnap = OFFSET_NOT_SET;
159994960e5delphij		break;
1600d8d18f6rpaulo
1601d8d18f6rpaulo	case DLT_JUNIPER_ST:
160294960e5delphij		cstate->off_linktype.constant_part = 18;
160394960e5delphij		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
160419bb0b8hselasky		cstate->off_nl = OFFSET_NOT_SET;
160519bb0b8hselasky		cstate->off_nl_nosnap = OFFSET_NOT_SET;
160694960e5delphij		break;
1607d8d18f6rpaulo
1608d8d18f6rpaulo	case DLT_JUNIPER_ISM:
160994960e5delphij		cstate->off_linktype.constant_part = 8;
161094960e5delphij		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
161119bb0b8hselasky		cstate->off_nl = OFFSET_NOT_SET;
161219bb0b8hselasky		cstate->off_nl_nosnap = OFFSET_NOT_SET;
161394960e5delphij		break;
16144462427mlaier
1615c5b3ac4gnn	case DLT_JUNIPER_VS:
1616c5b3ac4gnn	case DLT_JUNIPER_SRX_E2E:
1617c5b3ac4gnn	case DLT_JUNIPER_FIBRECHANNEL:
1618c5b3ac4gnn	case DLT_JUNIPER_ATM_CEMIC:
161994960e5delphij		cstate->off_linktype.constant_part = 8;
162094960e5delphij		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
162119bb0b8hselasky		cstate->off_nl = OFFSET_NOT_SET;
162219bb0b8hselasky		cstate->off_nl_nosnap = OFFSET_NOT_SET;
162394960e5delphij		break;
1624c5b3ac4gnn
1625d1c1ca6sam	case DLT_MTP2:
162694960e5delphij		cstate->off_li = 2;
162794960e5delphij		cstate->off_li_hsl = 4;
162894960e5delphij		cstate->off_sio = 3;
162994960e5delphij		cstate->off_opc = 4;
163094960e5delphij		cstate->off_dpc = 4;
163194960e5delphij		cstate->off_sls = 7;
163294960e5delphij		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
163394960e5delphij		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
163419bb0b8hselasky		cstate->off_nl = OFFSET_NOT_SET;
163519bb0b8hselasky		cstate->off_nl_nosnap = OFFSET_NOT_SET;
163694960e5delphij		break;
1637d1c1ca6sam
16384462427mlaier	case DLT_MTP2_WITH_PHDR:
163994960e5delphij		cstate->off_li = 6;
164094960e5delphij		cstate->off_li_hsl = 8;
164194960e5delphij		cstate->off_sio = 7;
164294960e5delphij		cstate->off_opc = 8;
164394960e5delphij		cstate->off_dpc = 8;
164494960e5delphij		cstate->off_sls = 11;
164594960e5delphij		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
164694960e5delphij		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
164719bb0b8hselasky		cstate->off_nl = OFFSET_NOT_SET;
164819bb0b8hselasky		cstate->off_nl_nosnap = OFFSET_NOT_SET;
164994960e5delphij		break;
1650d8d18f6rpaulo
1651d8d18f6rpaulo	case DLT_ERF:
165294960e5delphij		cstate->off_li = 22;
165394960e5delphij		cstate->off_li_hsl = 24;
165494960e5delphij		cstate->off_sio = 23;
165594960e5delphij		cstate->off_opc = 24;
165694960e5delphij		cstate->off_dpc = 24;
165794960e5delphij		cstate->off_sls = 27;
165894960e5delphij		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
165994960e5delphij		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
166019bb0b8hselasky		cstate->off_nl = OFFSET_NOT_SET;
166119bb0b8hselasky		cstate->off_nl_nosnap = OFFSET_NOT_SET;
166294960e5delphij		break;
16634462427mlaier
1664da13a5abms	case DLT_PFSYNC:
166594960e5delphij		cstate->off_linktype.constant_part = OFFSET_NOT_SET;
166694960e5delphij		cstate->off_linkpl.constant_part = 4;
166794960e5delphij		cstate->off_nl = 0;
166894960e5delphij		cstate->off_nl_nosnap = 0;
166994960e5delphij		break;
1670d1c1ca6sam
1671d8d18f6rpaulo	case DLT_AX25_KISS:
1672d8d18f6rpaulo		/*
1673d8d18f6rpaulo		 * Currently, only raw "link[N:M]" filtering is supported.
1674d8d18f6rpaulo		 */
167594960e5delphij		cstate->off_linktype.constant_part = OFFSET_NOT_SET;	/* variable, min 15, max 71 steps of 7 */
167694960e5delphij		cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
167719bb0b8hselasky		cstate->off_nl = OFFSET_NOT_SET;	/* variable, min 16, max 71 steps of 7 */
167819bb0b8hselasky		cstate->off_nl_nosnap = OFFSET_NOT_SET;	/* no 802.2 LLC */
167994960e5delphij		break;
1680d8d18f6rpaulo
1681c5b3ac4gnn	case DLT_IPNET:
168294960e5delphij		cstate->off_linktype.constant_part = 1;
168394960e5delphij		cstate->off_linkpl.constant_part = 24;	/* ipnet header length */
168494960e5delphij		cstate->off_nl = 0;
168519bb0b8hselasky		cstate->off_nl_nosnap = OFFSET_NOT_SET;
168694960e5delphij		break;
1687724e1a0rpaulo
1688c5b3ac4gnn	case DLT_NETANALYZER:
168994960e5delphij		cstate->off_linkhdr.constant_part = 4;	/* Ethernet header is past 4-byte pseudo-header */
169094960e5delphij		cstate->off_linktype.constant_part = cstate->off_linkhdr.constant_part + 12;
169194960e5delphij		cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 14;	/* pseudo-header+Ethernet header length */
169294960e5delphij		cstate->off_nl = 0;		/* Ethernet II */
169394960e5delphij		cstate->off_nl_nosnap = 3;	/* 802.3+802.2 */
169494960e5delphij		break;
1695724e1a0rpaulo
1696c5b3ac4gnn	case DLT_NETANALYZER_TRANSPARENT:
169794960e5delphij		cstate->off_linkhdr.constant_part = 12;	/* MAC header is past 4-byte pseudo-header, preamble, and SFD */
169894960e5delphij		cstate->off_linktype.constant_part = cstate->off_linkhdr.constant_part + 12;
169994960e5delphij		cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 14;	/* pseudo-header+preamble+SFD+Ethernet header length */
170094960e5delphij		cstate->off_nl = 0;		/* Ethernet II */
170194960e5delphij		cstate->off_nl_nosnap = 3;	/* 802.3+802.2 */
170294960e5delphij		break;
1703724e1a0rpaulo
1704c5b3ac4gnn	default:
1705724e1a0rpaulo		/*
1706c5b3ac4gnn		 * For values in the range in which we've assigned new
1707c5b3ac4gnn		 * DLT_ values, only raw "link[N:M]" filtering is supported.
1708724e1a0rpaulo		 */
170994960e5delphij		if (cstate->linktype >= DLT_MATCHING_MIN &&
171094960e5delphij		    cstate->linktype <= DLT_MATCHING_MAX) {
171194960e5delphij			cstate->off_linktype.constant_part = OFFSET_NOT_SET;
171294960e5delphij			cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
171319bb0b8hselasky			cstate->off_nl = OFFSET_NOT_SET;
171419bb0b8hselasky			cstate->off_nl_nosnap = OFFSET_NOT_SET;
171594960e5delphij		} else {
1716c2630c9philip			bpf_set_error(cstate, "unknown data link type %d", cstate->linktype);
1717c2630c9philip			return (-1);
1718c5b3ac4gnn		}
171994960e5delphij		break;
1720f0fdf33pst	}
1721d1c1ca6sam
172294960e5delphij	cstate->off_outermostlinkhdr = cstate->off_prevlinkhdr = cstate->off_linkhdr;
1723c2630c9philip	return (0);
1724d1c1ca6sam}
1725d1c1ca6sam
1726d8d18f6rpaulo/*
172794960e5delphij * Load a value relative to the specified absolute offset.
1728d8d18f6rpaulo */
1729d8d18f6rpaulostatic struct slist *
173094960e5delphijgen_load_absoffsetrel(compiler_state_t *cstate, bpf_abs_offset *abs_offset,
173194960e5delphij    u_int offset, u_int size)
1732d8d18f6rpaulo{
1733d8d18f6rpaulo	struct slist *s, *s2;
1734d8d18f6rpaulo
173594960e5delphij	s = gen_abs_offset_varpart(cstate, abs_offset);
1736d8d18f6rpaulo
1737d8d18f6rpaulo	/*
173894960e5delphij	 * If "s" is non-null, it has code to arrange that the X register
173994960e5delphij	 * contains the variable part of the absolute offset, so we
174094960e5delphij	 * generate a load relative to that, with an offset of
174194960e5delphij	 * abs_offset->constant_part + offset.
1742d8d18f6rpaulo	 *
174394960e5delphij	 * Otherwise, we can do an absolute load with an offset of
174494960e5delphij	 * abs_offset->constant_part + offset.
1745d8d18f6rpaulo	 */
1746d8d18f6rpaulo	if (s != NULL) {
1747d8d18f6rpaulo		/*
174894960e5delphij		 * "s" points to a list of statements that puts the
174994960e5delphij		 * variable part of the absolute offset into the X register.
175094960e5delphij		 * Do an indirect load, to use the X register as an offset.
1751d8d18f6rpaulo		 */
175294960e5delphij		s2 = new_stmt(cstate, BPF_LD|BPF_IND|size);
175394960e5delphij		s2->s.k = abs_offset->constant_part + offset;
1754d8d18f6rpaulo		sappend(s, s2);
1755d8d18f6rpaulo	} else {
1756d8d18f6rpaulo		/*
175794960e5delphij		 * There is no variable part of the absolute offset, so
175894960e5delphij		 * just do an absolute load.
1759d8d18f6rpaulo		 */
176094960e5delphij		s = new_stmt(cstate, BPF_LD|BPF_ABS|size);
176194960e5delphij		s->s.k = abs_offset->constant_part + offset;
1762d8d18f6rpaulo	}
1763d8d18f6rpaulo	return s;
1764d8d18f6rpaulo}
17654462427mlaier
1766d1c1ca6sam/*
1767d1c1ca6sam * Load a value relative to the beginning of the specified header.
1768d1c1ca6sam */
1769d1c1ca6samstatic struct slist *
177094960e5delphijgen_load_a(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
177194960e5delphij    u_int size)
1772d1c1ca6sam{
1773d1c1ca6sam	struct slist *s, *s2;
1774d1c1ca6sam
1775c2630c9philip	/*
1776c2630c9philip	 * Squelch warnings from compilers that *don't* assume that
1777c2630c9philip	 * offrel always has a valid enum value and therefore don't
1778c2630c9philip	 * assume that we'll always go through one of the case arms.
1779c2630c9philip	 *
1780c2630c9philip	 * If we have a default case, compilers that *do* assume that
1781c2630c9philip	 * will then complain about the default case code being
1782c2630c9philip	 * unreachable.
1783c2630c9philip	 *
1784c2630c9philip	 * Damned if you do, damned if you don't.
1785c2630c9philip	 */
1786c2630c9philip	s = NULL;
1787c2630c9philip
1788d1c1ca6sam	switch (offrel) {
1789d1c1ca6sam
1790d1c1ca6sam	case OR_PACKET:
179194960e5delphij                s = new_stmt(cstate, BPF_LD|BPF_ABS|size);
17924462427mlaier                s->s.k = offset;
1793d1c1ca6sam		break;
1794d1c1ca6sam
179594960e5delphij	case OR_LINKHDR:
179694960e5delphij		s = gen_load_absoffsetrel(cstate, &cstate->off_linkhdr, offset, size);
179794960e5delphij		break;
179894960e5delphij
179994960e5delphij	case OR_PREVLINKHDR:
180094960e5delphij		s = gen_load_absoffsetrel(cstate, &cstate->off_prevlinkhdr, offset, size);
1801d1c1ca6sam		break;
1802d1c1ca6sam
180394960e5delphij	case OR_LLC:
180494960e5delphij		s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, offset, size);
1805d8d18f6rpaulo		break;
1806d8d18f6rpaulo
180794960e5delphij	case OR_PREVMPLSHDR:
180894960e5delphij		s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl - 4 + offset, size);
1809d1c1ca6sam		break;
1810d1c1ca6sam
181194960e5delphij	case OR_LINKPL:
181294960e5delphij		s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl + offset, size);
181394960e5delphij		break;
181494960e5delphij
181594960e5delphij	case OR_LINKPL_NOSNAP:
181694960e5delphij		s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl_nosnap + offset, size);
181794960e5delphij		break;
181894960e5delphij
181994960e5delphij	case OR_LINKTYPE:
182094960e5delphij		s = gen_load_absoffsetrel(cstate, &cstate->off_linktype, offset, size);
1821d1c1ca6sam		break;
1822d1c1ca6sam
1823d1c1ca6sam	case OR_TRAN_IPV4:
1824d1c1ca6sam		/*
18254462427mlaier		 * Load the X register with the length of the IPv4 header
18264462427mlaier		 * (plus the offset of the link-layer header, if it's
18274462427mlaier		 * preceded by a variable-length header such as a radio
18284462427mlaier		 * header), in bytes.
1829d1c1ca6sam		 */
183094960e5delphij		s = gen_loadx_iphdrlen(cstate);
1831d1c1ca6sam
1832d1c1ca6sam		/*
183394960e5delphij		 * Load the item at {offset of the link-layer payload} +
183494960e5delphij		 * {offset, relative to the start of the link-layer
1835d8d18f6rpaulo		 * paylod, of the IPv4 header} + {length of the IPv4 header} +
18364462427mlaier		 * {specified offset}.
18374462427mlaier		 *
183894960e5delphij		 * If the offset of the link-layer payload is variable,
183994960e5delphij		 * the variable part of that offset is included in the
184094960e5delphij		 * value in the X register, and we include the constant
184194960e5delphij		 * part in the offset of the load.
1842d1c1ca6sam		 */
184394960e5delphij		s2 = new_stmt(cstate, BPF_LD|BPF_IND|size);
184494960e5delphij		s2->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + offset;
1845d1c1ca6sam		sappend(s, s2);
1846d1c1ca6sam		break;
1847d1c1ca6sam
1848d1c1ca6sam	case OR_TRAN_IPV6:
184994960e5delphij		s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl + 40 + offset, size);
1850d1c1ca6sam		break;
1851d1c1ca6sam	}
1852d1c1ca6sam	return s;
1853d1c1ca6sam}
1854d1c1ca6sam
1855d1c1ca6sam/*
1856d1c1ca6sam * Generate code to load into the X register the sum of the length of
185794960e5delphij * the IPv4 header and the variable part of the offset of the link-layer
185894960e5delphij * payload.
1859d1c1ca6sam */
1860d1c1ca6samstatic struct slist *
186194960e5delphijgen_loadx_iphdrlen(compiler_state_t *cstate)
1862d1c1ca6sam{
1863d1c1ca6sam	struct slist *s, *s2;
1864d1c1ca6sam
186594960e5delphij	s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
1866d1c1ca6sam	if (s != NULL) {
1867d1c1ca6sam		/*
186894960e5delphij		 * The offset of the link-layer payload has a variable
186994960e5delphij		 * part.  "s" points to a list of statements that put
187094960e5delphij		 * the variable part of that offset into the X register.
1871d8d18f6rpaulo		 *
1872d1c1ca6sam		 * The 4*([k]&0xf) addressing mode can't be used, as we
1873d1c1ca6sam		 * don't have a constant offset, so we have to load the
1874d1c1ca6sam		 * value in question into the A register and add to it
1875d1c1ca6sam		 * the value from the X register.
1876d1c1ca6sam		 */
187794960e5delphij		s2 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
187894960e5delphij		s2->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
1879d1c1ca6sam		sappend(s, s2);
188094960e5delphij		s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
1881d1c1ca6sam		s2->s.k = 0xf;
1882d1c1ca6sam		sappend(s, s2);
188394960e5delphij		s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K);
1884d1c1ca6sam		s2->s.k = 2;
1885d1c1ca6sam		sappend(s, s2);
1886d1c1ca6sam
1887d1c1ca6sam		/*
188894960e5delphij		 * The A register now contains the length of the IP header.
188994960e5delphij		 * We need to add to it the variable part of the offset of
189094960e5delphij		 * the link-layer payload, which is still in the X
1891d8d18f6rpaulo		 * register, and move the result into the X register.
1892d1c1ca6sam		 */
189394960e5delphij		sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
189494960e5delphij		sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
1895d1c1ca6sam	} else {
1896d1c1ca6sam		/*
189794960e5delphij		 * The offset of the link-layer payload is a constant,
189894960e5delphij		 * so no code was generated to load the (non-existent)
189994960e5delphij		 * variable part of that offset.
190094960e5delphij		 *
190194960e5delphij		 * This means we can use the 4*([k]&0xf) addressing
190294960e5delphij		 * mode.  Load the length of the IPv4 header, which
190394960e5delphij		 * is at an offset of cstate->off_nl from the beginning of
190494960e5delphij		 * the link-layer payload, and thus at an offset of
190594960e5delphij		 * cstate->off_linkpl.constant_part + cstate->off_nl from the beginning
190694960e5delphij		 * of the raw packet data, using that addressing mode.
190794960e5delphij		 */
190894960e5delphij		s = new_stmt(cstate, BPF_LDX|BPF_MSH|BPF_B);
190994960e5delphij		s->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
1910d1c1ca6sam	}
1911d1c1ca6sam	return s;
1912d1c1ca6sam}
1913d1c1ca6sam
191419bb0b8hselasky
1915f0fdf33pststatic struct block *
191694960e5delphijgen_uncond(compiler_state_t *cstate, int rsense)
1917f0fdf33pst{
1918f0fdf33pst	struct block *b;
1919f0fdf33pst	struct slist *s;
1920f0fdf33pst
192194960e5delphij	s = new_stmt(cstate, BPF_LD|BPF_IMM);
1922f0fdf33pst	s->s.k = !rsense;
192394960e5delphij	b = new_block(cstate, JMP(BPF_JEQ));
1924f0fdf33pst	b->stmts = s;
1925f0fdf33pst
1926f0fdf33pst	return b;
1927f0fdf33pst}
1928f0fdf33pst
1929f0fdf33pststatic inline struct block *
193094960e5delphijgen_true(compiler_state_t *cstate)
1931f0fdf33pst{
193294960e5delphij	return gen_uncond(cstate, 1);
1933f0fdf33pst}
1934f0fdf33pst
1935f0fdf33pststatic inline struct block *
193694960e5delphijgen_false(compiler_state_t *cstate)
1937f0fdf33pst{
193894960e5delphij	return gen_uncond(cstate, 0);
1939f0fdf33pst}
1940f0fdf33pst
1941a6bce88fenner/*
1942a6bce88fenner * Byte-swap a 32-bit number.
1943a6bce88fenner * ("htonl()" or "ntohl()" won't work - we want to byte-swap even on
1944a6bce88fenner * big-endian platforms.)
1945a6bce88fenner */
1946a6bce88fenner#define	SWAPLONG(y) \
1947a6bce88fenner((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
1948a6bce88fenner
1949d1c1ca6sam/*
1950d1c1ca6sam * Generate code to match a particular packet type.
1951d1c1ca6sam *
1952d1c1ca6sam * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
1953d1c1ca6sam * value, if <= ETHERMTU.  We use that to determine whether to
1954d1c1ca6sam * match the type/length field or to check the type/length field for
1955d1c1ca6sam * a value <= ETHERMTU to see whether it's a type field and then do
1956d1c1ca6sam * the appropriate test.
1957d1c1ca6sam */
1958f0fdf33pststatic struct block *
195994960e5delphijgen_ether_linktype(compiler_state_t *cstate, int proto)
1960f0fdf33pst{
1961ca0d84cfenner	struct block *b0, *b1;
1962ca0d84cfenner
1963da13a5abms	switch (proto) {
1964da13a5abms
1965da13a5abms	case LLCSAP_ISONS:
1966da13a5abms	case LLCSAP_IP:
1967da13a5abms	case LLCSAP_NETBEUI:
1968da13a5abms		/*
1969d1c1ca6sam		 * OSI protocols and NetBEUI always use 802.2 encapsulation,
1970d1c1ca6sam		 * so we check the DSAP and SSAP.
1971d1c1ca6sam		 *
1972d1c1ca6sam		 * LLCSAP_IP checks for IP-over-802.2, rather
1973d1c1ca6sam		 * than IP-over-Ethernet or IP-over-SNAP.
1974d1c1ca6sam		 *
1975da13a5abms		 * XXX - should we check both the DSAP and the
1976da13a5abms		 * SSAP, like this, or should we check just the
1977d1c1ca6sam		 * DSAP, as we do for other types <= ETHERMTU
1978d1c1ca6sam		 * (i.e., other SAP values)?
1979da13a5abms		 */
198094960e5delphij		b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
1981da13a5abms		gen_not(b0);
198294960e5delphij		b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)
1983d1c1ca6sam			     ((proto << 8) | proto));
1984da13a5abms		gen_and(b0, b1);
1985da13a5abms		return b1;
1986da13a5abms
1987da13a5abms	case LLCSAP_IPX:
1988da13a5abms		/*
1989da13a5abms		 * Check for;
1990da13a5abms		 *
1991da13a5abms		 *	Ethernet_II frames, which are Ethernet
1992da13a5abms		 *	frames with a frame type of ETHERTYPE_IPX;
1993da13a5abms		 *
1994da13a5abms		 *	Ethernet_802.3 frames, which are 802.3
1995da13a5abms		 *	frames (i.e., the type/length field is
1996da13a5abms		 *	a length field, <= ETHERMTU, rather than
1997da13a5abms		 *	a type field) with the first two bytes
1998da13a5abms		 *	after the Ethernet/802.3 header being
1999da13a5abms		 *	0xFFFF;
2000da13a5abms		 *
2001da13a5abms		 *	Ethernet_802.2 frames, which are 802.3
2002da13a5abms		 *	frames with an 802.2 LLC header and
2003da13a5abms		 *	with the IPX LSAP as the DSAP in the LLC
2004da13a5abms		 *	header;
2005da13a5abms		 *
2006da13a5abms		 *	Ethernet_SNAP frames, which are 802.3
2007da13a5abms		 *	frames with an LLC header and a SNAP
2008da13a5abms		 *	header and with an OUI of 0x000000
2009da13a5abms		 *	(encapsulated Ethernet) and a protocol
2010da13a5abms		 *	ID of ETHERTYPE_IPX in the SNAP header.
2011da13a5abms		 *
2012da13a5abms		 * XXX - should we generate the same code both
2013da13a5abms		 * for tests for LLCSAP_IPX and for ETHERTYPE_IPX?
2014da13a5abms		 */
2015da13a5abms
2016da13a5abms		/*
2017da13a5abms		 * This generates code to check both for the
2018da13a5abms		 * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3.
2019da13a5abms		 */
202094960e5delphij		b0 = gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
202194960e5delphij		b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
2022da13a5abms		gen_or(b0, b1);
2023da13a5abms
2024da13a5abms		/*
2025da13a5abms		 * Now we add code to check for SNAP frames with
2026da13a5abms		 * ETHERTYPE_IPX, i.e. Ethernet_SNAP.
2027da13a5abms		 */
202894960e5delphij		b0 = gen_snap(cstate, 0x000000, ETHERTYPE_IPX);
2029da13a5abms		gen_or(b0, b1);
2030da13a5abms
2031da13a5abms		/*
2032da13a5abms		 * Now we generate code to check for 802.3
2033da13a5abms		 * frames in general.
2034da13a5abms		 */
203594960e5delphij		b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
2036da13a5abms		gen_not(b0);
2037da13a5abms
2038da13a5abms		/*
2039da13a5abms		 * Now add the check for 802.3 frames before the
2040da13a5abms		 * check for Ethernet_802.2 and Ethernet_802.3,
2041da13a5abms		 * as those checks should only be done on 802.3
2042da13a5abms		 * frames, not on Ethernet frames.
2043da13a5abms		 */
2044da13a5abms		gen_and(b0, b1);
2045da13a5abms
2046da13a5abms		/*
2047da13a5abms		 * Now add the check for Ethernet_II frames, and
2048da13a5abms		 * do that before checking for the other frame
2049da13a5abms		 * types.
2050da13a5abms		 */
205194960e5delphij		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
2052da13a5abms		gen_or(b0, b1);
2053da13a5abms		return b1;
2054da13a5abms
2055da13a5abms	case ETHERTYPE_ATALK:
2056da13a5abms	case ETHERTYPE_AARP:
2057da13a5abms		/*
2058da13a5abms		 * EtherTalk (AppleTalk protocols on Ethernet link
2059da13a5abms		 * layer) may use 802.2 encapsulation.
2060da13a5abms		 */
2061da13a5abms
2062da13a5abms		/*
2063da13a5abms		 * Check for 802.2 encapsulation (EtherTalk phase 2?);
2064da13a5abms		 * we check for an Ethernet type field less than
2065da13a5abms		 * 1500, which means it's an 802.3 length field.
2066da13a5abms		 */
206794960e5delphij		b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
2068da13a5abms		gen_not(b0);
2069da13a5abms
2070da13a5abms		/*
2071da13a5abms		 * 802.2-encapsulated ETHERTYPE_ATALK packets are
2072da13a5abms		 * SNAP packets with an organization code of
2073da13a5abms		 * 0x080007 (Apple, for Appletalk) and a protocol
2074da13a5abms		 * type of ETHERTYPE_ATALK (Appletalk).
2075da13a5abms		 *
2076da13a5abms		 * 802.2-encapsulated ETHERTYPE_AARP packets are
2077da13a5abms		 * SNAP packets with an organization code of
2078da13a5abms		 * 0x000000 (encapsulated Ethernet) and a protocol
2079da13a5abms		 * type of ETHERTYPE_AARP (Appletalk ARP).
2080da13a5abms		 */
2081da13a5abms		if (proto == ETHERTYPE_ATALK)
208294960e5delphij			b1 = gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
2083da13a5abms		else	/* proto == ETHERTYPE_AARP */
208494960e5delphij			b1 = gen_snap(cstate, 0x000000, ETHERTYPE_AARP);
2085da13a5abms		gen_and(b0, b1);
2086da13a5abms
2087da13a5abms		/*
2088da13a5abms		 * Check for Ethernet encapsulation (Ethertalk
2089da13a5abms		 * phase 1?); we just check for the Ethernet
2090da13a5abms		 * protocol type.
2091da13a5abms		 */
209294960e5delphij		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
2093da13a5abms
2094da13a5abms		gen_or(b0, b1);
2095da13a5abms		return b1;
2096da13a5abms
2097da13a5abms	default:
2098da13a5abms		if (proto <= ETHERMTU) {
2099da13a5abms			/*
2100da13a5abms			 * This is an LLC SAP value, so the frames
2101da13a5abms			 * that match would be 802.2 frames.
2102da13a5abms			 * Check that the frame is an 802.2 frame
2103da13a5abms			 * (i.e., that the length/type field is
2104da13a5abms			 * a length field, <= ETHERMTU) and
2105da13a5abms			 * then check the DSAP.
2106da13a5abms			 */
210794960e5delphij			b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
2108da13a5abms			gen_not(b0);
210994960e5delphij			b1 = gen_cmp(cstate, OR_LINKTYPE, 2, BPF_B, (bpf_int32)proto);
2110da13a5abms			gen_and(b0, b1);
2111da13a5abms			return b1;
2112da13a5abms		} else {
2113da13a5abms			/*
2114da13a5abms			 * This is an Ethernet type, so compare
2115da13a5abms			 * the length/type field with it (if
2116da13a5abms			 * the frame is an 802.2 frame, the length
2117da13a5abms			 * field will be <= ETHERMTU, and, as
2118da13a5abms			 * "proto" is > ETHERMTU, this test
2119da13a5abms			 * will fail and the frame won't match,
2120da13a5abms			 * which is what we want).
2121da13a5abms			 */
212294960e5delphij			return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H,
2123d1c1ca6sam			    (bpf_int32)proto);
2124da13a5abms		}
2125da13a5abms	}
2126da13a5abms}
2127da13a5abms
212894960e5delphijstatic struct block *
212994960e5delphijgen_loopback_linktype(compiler_state_t *cstate, int proto)
213094960e5delphij{
213194960e5delphij	/*
213294960e5delphij	 * For DLT_NULL, the link-layer header is a 32-bit word
213394960e5delphij	 * containing an AF_ value in *host* byte order, and for
213494960e5delphij	 * DLT_ENC, the link-layer header begins with a 32-bit
213594960e5delphij	 * word containing an AF_ value in host byte order.
213694960e5delphij	 *
213794960e5delphij	 * In addition, if we're reading a saved capture file,
213894960e5delphij	 * the host byte order in the capture may not be the
213994960e5delphij	 * same as the host byte order on this machine.
214094960e5delphij	 *
214194960e5delphij	 * For DLT_LOOP, the link-layer header is a 32-bit
214294960e5delphij	 * word containing an AF_ value in *network* byte order.
214394960e5delphij	 */
214494960e5delphij	if (cstate->linktype == DLT_NULL || cstate->linktype == DLT_ENC) {
214594960e5delphij		/*
214694960e5delphij		 * The AF_ value is in host byte order, but the BPF
214794960e5delphij		 * interpreter will convert it to network byte order.
214894960e5delphij		 *
214994960e5delphij		 * If this is a save file, and it's from a machine
215094960e5delphij		 * with the opposite byte order to ours, we byte-swap
215194960e5delphij		 * the AF_ value.
215294960e5delphij		 *
215394960e5delphij		 * Then we run it through "htonl()", and generate
215494960e5delphij		 * code to compare against the result.
215594960e5delphij		 */
215694960e5delphij		if (cstate->bpf_pcap->rfile != NULL && cstate->bpf_pcap->swapped)
215794960e5delphij			proto = SWAPLONG(proto);
215894960e5delphij		proto = htonl(proto);
215994960e5delphij	}
216094960e5delphij	return (gen_cmp(cstate, OR_LINKHDR, 0, BPF_W, (bpf_int32)proto));
216194960e5delphij}
216294960e5delphij
2163d1c1ca6sam/*
2164724e1a0rpaulo * "proto" is an Ethernet type value and for IPNET, if it is not IPv4
2165724e1a0rpaulo * or IPv6 then we have an error.
2166724e1a0rpaulo */
2167724e1a0rpaulostatic struct block *
216894960e5delphijgen_ipnet_linktype(compiler_state_t *cstate, int proto)
2169724e1a0rpaulo{
2170724e1a0rpaulo	switch (proto) {
2171724e1a0rpaulo
2172724e1a0rpaulo	case ETHERTYPE_IP:
217394960e5delphij		return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B, (bpf_int32)IPH_AF_INET);
2174c2630c9philip		/*NOTREACHED*/
2175724e1a0rpaulo
2176724e1a0rpaulo	case ETHERTYPE_IPV6:
217794960e5delphij		return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
2178724e1a0rpaulo		    (bpf_int32)IPH_AF_INET6);
2179c2630c9philip		/*NOTREACHED*/
2180724e1a0rpaulo
2181724e1a0rpaulo	default:
2182724e1a0rpaulo		break;
2183724e1a0rpaulo	}
2184724e1a0rpaulo
218594960e5delphij	return gen_false(cstate);
2186724e1a0rpaulo}
2187724e1a0rpaulo
2188724e1a0rpaulo/*
2189d1c1ca6sam * Generate code to match a particular packet type.
2190d1c1ca6sam *
2191d1c1ca6sam * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
2192d1c1ca6sam * value, if <= ETHERMTU.  We use that to determine whether to
2193d1c1ca6sam * match the type field or to check the type field for the special
2194d1c1ca6sam * LINUX_SLL_P_802_2 value and then do the appropriate test.
2195d1c1ca6sam */
2196da13a5abmsstatic struct block *
219794960e5delphijgen_linux_sll_linktype(compiler_state_t *cstate, int proto)
219870f7ae4sam{
219970f7ae4sam	struct block *b0, *b1;
220070f7ae4sam
220170f7ae4sam	switch (proto) {
220270f7ae4sam
220370f7ae4sam	case LLCSAP_ISONS:
2204d1c1ca6sam	case LLCSAP_IP:
220570f7ae4sam	case LLCSAP_NETBEUI:
220670f7ae4sam		/*
2207d1c1ca6sam		 * OSI protocols and NetBEUI always use 802.2 encapsulation,
2208d1c1ca6sam		 * so we check the DSAP and SSAP.
2209d1c1ca6sam		 *
2210d1c1ca6sam		 * LLCSAP_IP checks for IP-over-802.2, rather
2211d1c1ca6sam		 * than IP-over-Ethernet or IP-over-SNAP.
2212d1c1ca6sam		 *
221370f7ae4sam		 * XXX - should we check both the DSAP and the
2214d1c1ca6sam		 * SSAP, like this, or should we check just the
2215d1c1ca6sam		 * DSAP, as we do for other types <= ETHERMTU
2216d1c1ca6sam		 * (i.e., other SAP values)?
221770f7ae4sam		 */
221894960e5delphij		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
221994960e5delphij		b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)
2220d1c1ca6sam			     ((proto << 8) | proto));
222170f7ae4sam		gen_and(b0, b1);
222270f7ae4sam		return b1;
222370f7ae4sam
222470f7ae4sam	case LLCSAP_IPX:
222570f7ae4sam		/*
222670f7ae4sam		 *	Ethernet_II frames, which are Ethernet
222770f7ae4sam		 *	frames with a frame type of ETHERTYPE_IPX;
222870f7ae4sam		 *
222970f7ae4sam		 *	Ethernet_802.3 frames, which have a frame
223070f7ae4sam		 *	type of LINUX_SLL_P_802_3;
223170f7ae4sam		 *
223270f7ae4sam		 *	Ethernet_802.2 frames, which are 802.3
223370f7ae4sam		 *	frames with an 802.2 LLC header (i.e, have
223470f7ae4sam		 *	a frame type of LINUX_SLL_P_802_2) and
223570f7ae4sam		 *	with the IPX LSAP as the DSAP in the LLC
223670f7ae4sam		 *	header;
223770f7ae4sam		 *
223870f7ae4sam		 *	Ethernet_SNAP frames, which are 802.3
223970f7ae4sam		 *	frames with an LLC header and a SNAP
224070f7ae4sam		 *	header and with an OUI of 0x000000
224170f7ae4sam		 *	(encapsulated Ethernet) and a protocol
224270f7ae4sam		 *	ID of ETHERTYPE_IPX in the SNAP header.
224370f7ae4sam		 *
224470f7ae4sam		 * First, do the checks on LINUX_SLL_P_802_2
224570f7ae4sam		 * frames; generate the check for either
224670f7ae4sam		 * Ethernet_802.2 or Ethernet_SNAP frames, and
224770f7ae4sam		 * then put a check for LINUX_SLL_P_802_2 frames
224870f7ae4sam		 * before it.
224970f7ae4sam		 */
225094960e5delphij		b0 = gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
225194960e5delphij		b1 = gen_snap(cstate, 0x000000, ETHERTYPE_IPX);
225270f7ae4sam		gen_or(b0, b1);
225394960e5delphij		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
225470f7ae4sam		gen_and(b0, b1);
225570f7ae4sam
225670f7ae4sam		/*
225770f7ae4sam		 * Now check for 802.3 frames and OR that with
225870f7ae4sam		 * the previous test.
225970f7ae4sam		 */
226094960e5delphij		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_3);
226170f7ae4sam		gen_or(b0, b1);
226270f7ae4sam
226370f7ae4sam		/*
226470f7ae4sam		 * Now add the check for Ethernet_II frames, and
226570f7ae4sam		 * do that before checking for the other frame
226670f7ae4sam		 * types.
226770f7ae4sam		 */
226894960e5delphij		b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
226970f7ae4sam		gen_or(b0, b1);
227070f7ae4sam		return b1;
227170f7ae4sam
227270f7ae4sam	case ETHERTYPE_ATALK:
227370f7ae4sam	case ETHERTYPE_AARP:
227470f7ae4sam		/*
227570f7ae4sam		 * EtherTalk (AppleTalk protocols on Ethernet link
227670f7ae4sam		 * layer) may use 802.2 encapsulation.
227770f7ae4sam		 */
227870f7ae4sam
227970f7ae4sam		/*
228070f7ae4sam		 * Check for 802.2 encapsulation (EtherTalk phase 2?);
228170f7ae4sam		 * we check for the 802.2 protocol type in the
228270f7ae4sam		 * "Ethernet type" field.
228370f7ae4sam		 */
2284