176404edcSAsim Jamshed /*#define CHASE_CHAIN*/
276404edcSAsim Jamshed /*
376404edcSAsim Jamshed  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
476404edcSAsim Jamshed  *	The Regents of the University of California.  All rights reserved.
576404edcSAsim Jamshed  *
676404edcSAsim Jamshed  * Some portions Copyright (C) 2014 Cisco and/or its affiliates. All rights reserved.
776404edcSAsim Jamshed  * Some portions Copyright (C) 2010-2013 Sourcefire, Inc.
876404edcSAsim Jamshed  *
976404edcSAsim Jamshed  * Redistribution and use in source and binary forms, with or without
1076404edcSAsim Jamshed  * modification, are permitted provided that: (1) source code distributions
1176404edcSAsim Jamshed  * retain the above copyright notice and this paragraph in its entirety, (2)
1276404edcSAsim Jamshed  * distributions including binary code include the above copyright notice and
1376404edcSAsim Jamshed  * this paragraph in its entirety in the documentation or other materials
1476404edcSAsim Jamshed  * provided with the distribution, and (3) all advertising materials mentioning
1576404edcSAsim Jamshed  * features or use of this software display the following acknowledgement:
1676404edcSAsim Jamshed  * ``This product includes software developed by the University of California,
1776404edcSAsim Jamshed  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1876404edcSAsim Jamshed  * the University nor the names of its contributors may be used to endorse
1976404edcSAsim Jamshed  * or promote products derived from this software without specific prior
2076404edcSAsim Jamshed  * written permission.
2176404edcSAsim Jamshed  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
2276404edcSAsim Jamshed  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
2376404edcSAsim Jamshed  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2476404edcSAsim Jamshed  */
2576404edcSAsim Jamshed #ifndef lint
26*8a8b63d6SAsim Jamshed static const char __attribute__ ((unused)) rcsid[] =
2776404edcSAsim Jamshed     "@(#) $Header: /usr/cvsroot/sfeng/ims/src/libraries/daq/daq/sfbpf/sf_gencode.c,v 1.6 2014/06/10 13:38:55 cwaxman Exp $ (LBL)";
2876404edcSAsim Jamshed #endif
2976404edcSAsim Jamshed 
3076404edcSAsim Jamshed #ifdef HAVE_CONFIG_H
3176404edcSAsim Jamshed #include "config.h"
3276404edcSAsim Jamshed #endif
3376404edcSAsim Jamshed 
3476404edcSAsim Jamshed #ifdef WIN32
3576404edcSAsim Jamshed #include "win32-stdinc.h"
3676404edcSAsim Jamshed #else /* WIN32 */
3776404edcSAsim Jamshed #if HAVE_INTTYPES_H
3876404edcSAsim Jamshed #include <inttypes.h>
3976404edcSAsim Jamshed #elif HAVE_STDINT_H
4076404edcSAsim Jamshed #include <stdint.h>
4176404edcSAsim Jamshed #endif
4276404edcSAsim Jamshed #ifdef HAVE_SYS_BITYPES_H
4376404edcSAsim Jamshed #include <sys/bitypes.h>
4476404edcSAsim Jamshed #endif
4576404edcSAsim Jamshed #include <sys/types.h>
4676404edcSAsim Jamshed #include <sys/socket.h>
4776404edcSAsim Jamshed #endif /* WIN32 */
4876404edcSAsim Jamshed 
4976404edcSAsim Jamshed /*
5076404edcSAsim Jamshed  * XXX - why was this included even on UNIX?
5176404edcSAsim Jamshed  */
5276404edcSAsim Jamshed #ifdef __MINGW32__
5376404edcSAsim Jamshed #include "IP6_misc.h"
5476404edcSAsim Jamshed #endif
5576404edcSAsim Jamshed 
5676404edcSAsim Jamshed #ifndef WIN32
5776404edcSAsim Jamshed 
5876404edcSAsim Jamshed #ifdef __NetBSD__
5976404edcSAsim Jamshed #include <sys/param.h>
6076404edcSAsim Jamshed #endif
6176404edcSAsim Jamshed 
6276404edcSAsim Jamshed #include <netinet/in.h>
6376404edcSAsim Jamshed #include <arpa/inet.h>
6476404edcSAsim Jamshed 
6576404edcSAsim Jamshed #endif /* WIN32 */
6676404edcSAsim Jamshed 
6776404edcSAsim Jamshed #include <stdlib.h>
6876404edcSAsim Jamshed #include <string.h>
6976404edcSAsim Jamshed #include <memory.h>
7076404edcSAsim Jamshed #include <setjmp.h>
7176404edcSAsim Jamshed #include <stdarg.h>
7276404edcSAsim Jamshed #include <stdio.h>
7376404edcSAsim Jamshed 
7476404edcSAsim Jamshed #ifdef MSDOS
7576404edcSAsim Jamshed #include "pcap-dos.h"
7676404edcSAsim Jamshed #endif
7776404edcSAsim Jamshed 
7876404edcSAsim Jamshed #include "sfbpf-int.h"
7976404edcSAsim Jamshed 
8076404edcSAsim Jamshed #include "ethertype.h"
8176404edcSAsim Jamshed #include "nlpid.h"
8276404edcSAsim Jamshed #include "llc.h"
8376404edcSAsim Jamshed #include "gencode.h"
8476404edcSAsim Jamshed #include "ieee80211.h"
8576404edcSAsim Jamshed #include "atmuni31.h"
8676404edcSAsim Jamshed #include "sunatmpos.h"
8776404edcSAsim Jamshed #include "ppp.h"
8876404edcSAsim Jamshed #include "sll.h"
8976404edcSAsim Jamshed #include "ipnet.h"
9076404edcSAsim Jamshed #include "arcnet.h"
9176404edcSAsim Jamshed #ifdef HAVE_NET_PFVAR_H
9276404edcSAsim Jamshed #include <sys/socket.h>
9376404edcSAsim Jamshed #include <net/if.h>
9476404edcSAsim Jamshed #include <net/pfvar.h>
9576404edcSAsim Jamshed #include <net/if_pflog.h>
9676404edcSAsim Jamshed #endif
9776404edcSAsim Jamshed #ifndef offsetof
9876404edcSAsim Jamshed #define offsetof(s, e) ((size_t)&((s *)0)->e)
9976404edcSAsim Jamshed #endif
10076404edcSAsim Jamshed #ifdef INET6
10176404edcSAsim Jamshed #ifndef WIN32
10276404edcSAsim Jamshed #include <netdb.h>              /* for "struct addrinfo" */
10376404edcSAsim Jamshed #endif /* WIN32 */
10476404edcSAsim Jamshed #endif /*INET6 */
10576404edcSAsim Jamshed #include "namedb.h"
10676404edcSAsim Jamshed 
10776404edcSAsim Jamshed #define ETHERMTU	1500
10876404edcSAsim Jamshed 
10976404edcSAsim Jamshed #ifndef IPPROTO_SCTP
11076404edcSAsim Jamshed #define IPPROTO_SCTP 132
11176404edcSAsim Jamshed #endif
11276404edcSAsim Jamshed 
11376404edcSAsim Jamshed #define JMP(c) ((c)|BPF_JMP|BPF_K)
11476404edcSAsim Jamshed 
11576404edcSAsim Jamshed #if defined(__GNUC__)
11676404edcSAsim Jamshed #pragma GCC diagnostic ignored "-Wunused-value"
11776404edcSAsim Jamshed #endif /* __GNUC__ */
11876404edcSAsim Jamshed 
11976404edcSAsim Jamshed /* Locals */
12076404edcSAsim Jamshed static __thread jmp_buf top_ctx;
12176404edcSAsim Jamshed static __thread char bpf_error_filter[PCAP_ERRBUF_SIZE + 1];
12276404edcSAsim Jamshed 
12376404edcSAsim Jamshed /* Hack for updating VLAN, MPLS, and PPPoE offsets. */
12476404edcSAsim Jamshed #ifdef WIN32
12576404edcSAsim Jamshed static u_int orig_linktype = (u_int) - 1, orig_nl = (u_int) - 1, label_stack_depth = (u_int) - 1;
12676404edcSAsim Jamshed #else
12776404edcSAsim Jamshed static __thread u_int orig_linktype = -1U, orig_nl = -1U, label_stack_depth = -1U;
12876404edcSAsim Jamshed #endif
12976404edcSAsim Jamshed 
13076404edcSAsim Jamshed /* XXX */
13176404edcSAsim Jamshed #ifdef PCAP_FDDIPAD
13276404edcSAsim Jamshed static int pcap_fddipad;
13376404edcSAsim Jamshed #endif
13476404edcSAsim Jamshed 
13576404edcSAsim Jamshed /* VARARGS */
bpf_error(const char * fmt,...)13676404edcSAsim Jamshed void bpf_error(const char *fmt, ...)
13776404edcSAsim Jamshed {
13876404edcSAsim Jamshed     va_list ap;
13976404edcSAsim Jamshed 
14076404edcSAsim Jamshed     va_start(ap, fmt);
14176404edcSAsim Jamshed     (void) vsnprintf(bpf_error_filter, PCAP_ERRBUF_SIZE, fmt, ap);
14276404edcSAsim Jamshed     va_end(ap);
14376404edcSAsim Jamshed     longjmp(top_ctx, 1);
14476404edcSAsim Jamshed     /* NOTREACHED */
14576404edcSAsim Jamshed }
14676404edcSAsim Jamshed 
14776404edcSAsim Jamshed static void init_linktype(int);
14876404edcSAsim Jamshed 
14976404edcSAsim Jamshed static void init_regs(void);
15076404edcSAsim Jamshed static int alloc_reg(void);
15176404edcSAsim Jamshed static void free_reg(int);
15276404edcSAsim Jamshed 
15376404edcSAsim Jamshed static __thread struct block *root;
15476404edcSAsim Jamshed 
15576404edcSAsim Jamshed /*
15676404edcSAsim Jamshed  * Value passed to gen_load_a() to indicate what the offset argument
15776404edcSAsim Jamshed  * is relative to.
15876404edcSAsim Jamshed  */
15976404edcSAsim Jamshed enum e_offrel
16076404edcSAsim Jamshed {
16176404edcSAsim Jamshed     OR_PACKET,                  /* relative to the beginning of the packet */
16276404edcSAsim Jamshed     OR_LINK,                    /* relative to the beginning of the link-layer header */
16376404edcSAsim Jamshed     OR_MACPL,                   /* relative to the end of the MAC-layer header */
16476404edcSAsim Jamshed     OR_NET,                     /* relative to the network-layer header */
16576404edcSAsim Jamshed     OR_NET_NOSNAP,              /* relative to the network-layer header, with no SNAP header at the link layer */
16676404edcSAsim Jamshed     OR_TRAN_IPV4,               /* relative to the transport-layer header, with IPv4 network layer */
16776404edcSAsim Jamshed     OR_TRAN_IPV6                /* relative to the transport-layer header, with IPv6 network layer */
16876404edcSAsim Jamshed };
16976404edcSAsim Jamshed 
17076404edcSAsim Jamshed #ifdef INET6
17176404edcSAsim Jamshed /*
17276404edcSAsim Jamshed  * As errors are handled by a longjmp, anything allocated must be freed
17376404edcSAsim Jamshed  * in the longjmp handler, so it must be reachable from that handler.
17476404edcSAsim Jamshed  * One thing that's allocated is the result of pcap_nametoaddrinfo();
17576404edcSAsim Jamshed  * it must be freed with freeaddrinfo().  This variable points to any
17676404edcSAsim Jamshed  * addrinfo structure that would need to be freed.
17776404edcSAsim Jamshed  */
17876404edcSAsim Jamshed static struct addrinfo *ai;
17976404edcSAsim Jamshed #endif
18076404edcSAsim Jamshed 
18176404edcSAsim Jamshed /*
18276404edcSAsim Jamshed  * We divy out chunks of memory rather than call malloc each time so
18376404edcSAsim Jamshed  * we don't have to worry about leaking memory.  It's probably
18476404edcSAsim Jamshed  * not a big deal if all this memory was wasted but if this ever
18576404edcSAsim Jamshed  * goes into a library that would probably not be a good idea.
18676404edcSAsim Jamshed  *
18776404edcSAsim Jamshed  * XXX - this *is* in a library....
18876404edcSAsim Jamshed  */
18976404edcSAsim Jamshed #define NCHUNKS 16
19076404edcSAsim Jamshed #define CHUNK0SIZE 1024
19176404edcSAsim Jamshed struct chunk
19276404edcSAsim Jamshed {
19376404edcSAsim Jamshed     u_int n_left;
19476404edcSAsim Jamshed     void *m;
19576404edcSAsim Jamshed };
19676404edcSAsim Jamshed 
19776404edcSAsim Jamshed static __thread struct chunk chunks[NCHUNKS];
19876404edcSAsim Jamshed static __thread int cur_chunk;
19976404edcSAsim Jamshed 
20076404edcSAsim Jamshed static void *newchunk(u_int);
20176404edcSAsim Jamshed static void freechunks(void);
20276404edcSAsim Jamshed static inline struct block *new_block(int);
20376404edcSAsim Jamshed static inline struct slist *new_stmt(int);
20476404edcSAsim Jamshed static struct block *gen_retblk(int);
20576404edcSAsim Jamshed static inline void syntax(void);
20676404edcSAsim Jamshed 
20776404edcSAsim Jamshed static void backpatch(struct block *, struct block *);
20876404edcSAsim Jamshed static void merge(struct block *, struct block *);
20976404edcSAsim Jamshed static struct block *gen_cmp(enum e_offrel, u_int, u_int, bpf_int32);
21076404edcSAsim Jamshed static struct block *gen_cmp_gt(enum e_offrel, u_int, u_int, bpf_int32);
21176404edcSAsim Jamshed static struct block *gen_cmp_ge(enum e_offrel, u_int, u_int, bpf_int32);
21276404edcSAsim Jamshed static struct block *gen_cmp_lt(enum e_offrel, u_int, u_int, bpf_int32);
21376404edcSAsim Jamshed static struct block *gen_cmp_le(enum e_offrel, u_int, u_int, bpf_int32);
21476404edcSAsim Jamshed static struct block *gen_mcmp(enum e_offrel, u_int, u_int, bpf_int32, bpf_u_int32);
21576404edcSAsim Jamshed static struct block *gen_bcmp(enum e_offrel, u_int, u_int, const u_char *);
21676404edcSAsim Jamshed static struct block *gen_ncmp(enum e_offrel, bpf_u_int32, bpf_u_int32,
21776404edcSAsim Jamshed                               bpf_u_int32, bpf_u_int32, int, bpf_int32);
21876404edcSAsim Jamshed static struct slist *gen_load_llrel(u_int, u_int);
21976404edcSAsim Jamshed static struct slist *gen_load_macplrel(u_int, u_int);
22076404edcSAsim Jamshed static struct slist *gen_load_a(enum e_offrel, u_int, u_int);
22176404edcSAsim Jamshed static struct slist *gen_loadx_iphdrlen(void);
22276404edcSAsim Jamshed static struct block *gen_uncond(int);
22376404edcSAsim Jamshed static inline struct block *gen_true(void);
22476404edcSAsim Jamshed static inline struct block *gen_false(void);
22576404edcSAsim Jamshed static struct block *gen_ether_linktype(int);
22676404edcSAsim Jamshed static struct block *gen_ipnet_linktype(int);
22776404edcSAsim Jamshed static struct block *gen_linux_sll_linktype(int);
22876404edcSAsim Jamshed static struct slist *gen_load_prism_llprefixlen(void);
22976404edcSAsim Jamshed static struct slist *gen_load_avs_llprefixlen(void);
23076404edcSAsim Jamshed static struct slist *gen_load_radiotap_llprefixlen(void);
23176404edcSAsim Jamshed static struct slist *gen_load_ppi_llprefixlen(void);
23276404edcSAsim Jamshed static void insert_compute_vloffsets(struct block *);
23376404edcSAsim Jamshed static struct slist *gen_llprefixlen(void);
23476404edcSAsim Jamshed static struct slist *gen_off_macpl(void);
23576404edcSAsim Jamshed static int ethertype_to_ppptype(int);
23676404edcSAsim Jamshed static struct block *gen_linktype(int);
23776404edcSAsim Jamshed static struct block *gen_snap(bpf_u_int32, bpf_u_int32);
23876404edcSAsim Jamshed static struct block *gen_llc_linktype(int);
23976404edcSAsim Jamshed static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int);
24076404edcSAsim Jamshed #ifdef INET6
24176404edcSAsim Jamshed static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int);
24276404edcSAsim Jamshed #endif
24376404edcSAsim Jamshed static struct block *gen_ahostop(const u_char *, int);
24476404edcSAsim Jamshed static struct block *gen_ehostop(const u_char *, int);
24576404edcSAsim Jamshed static struct block *gen_fhostop(const u_char *, int);
24676404edcSAsim Jamshed static struct block *gen_thostop(const u_char *, int);
24776404edcSAsim Jamshed static struct block *gen_wlanhostop(const u_char *, int);
24876404edcSAsim Jamshed static struct block *gen_ipfchostop(const u_char *, int);
24976404edcSAsim Jamshed static struct block *gen_dnhostop(bpf_u_int32, int);
25076404edcSAsim Jamshed static struct block *gen_mpls_linktype(int);
25176404edcSAsim Jamshed static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int, int);
25276404edcSAsim Jamshed #ifdef INET6
25376404edcSAsim Jamshed static struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int, int);
25476404edcSAsim Jamshed #endif
25576404edcSAsim Jamshed #ifndef INET6
25676404edcSAsim Jamshed static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int);
25776404edcSAsim Jamshed #endif
25876404edcSAsim Jamshed static struct block *gen_ipfrag(void);
25976404edcSAsim Jamshed static struct block *gen_portatom(int, bpf_int32);
26076404edcSAsim Jamshed static struct block *gen_portrangeatom(int, bpf_int32, bpf_int32);
26176404edcSAsim Jamshed #ifdef INET6
26276404edcSAsim Jamshed static struct block *gen_portatom6(int, bpf_int32);
26376404edcSAsim Jamshed static struct block *gen_portrangeatom6(int, bpf_int32, bpf_int32);
26476404edcSAsim Jamshed #endif
26576404edcSAsim Jamshed struct block *gen_portop(int, int, int);
26676404edcSAsim Jamshed static struct block *gen_port(int, int, int);
26776404edcSAsim Jamshed struct block *gen_portrangeop(int, int, int, int);
26876404edcSAsim Jamshed static struct block *gen_portrange(int, int, int, int);
26976404edcSAsim Jamshed #ifdef INET6
27076404edcSAsim Jamshed struct block *gen_portop6(int, int, int);
27176404edcSAsim Jamshed static struct block *gen_port6(int, int, int);
27276404edcSAsim Jamshed struct block *gen_portrangeop6(int, int, int, int);
27376404edcSAsim Jamshed static struct block *gen_portrange6(int, int, int, int);
27476404edcSAsim Jamshed #endif
27576404edcSAsim Jamshed static int lookup_proto(const char *, int);
27676404edcSAsim Jamshed static struct block *gen_protochain(int, int, int);
27776404edcSAsim Jamshed static struct block *gen_proto(int, int, int);
27876404edcSAsim Jamshed static struct slist *xfer_to_x(struct arth *);
27976404edcSAsim Jamshed static struct slist *xfer_to_a(struct arth *);
28076404edcSAsim Jamshed static struct block *gen_mac_multicast(int);
28176404edcSAsim Jamshed static struct block *gen_len(int, int);
28276404edcSAsim Jamshed static struct block *gen_check_802_11_data_frame(void);
28376404edcSAsim Jamshed 
28476404edcSAsim Jamshed static struct block *gen_ppi_dlt_check(void);
28576404edcSAsim Jamshed static struct block *gen_msg_abbrev(int type);
28676404edcSAsim Jamshed 
newchunk(n)28776404edcSAsim Jamshed static void *newchunk(n)
28876404edcSAsim Jamshed      u_int n;
28976404edcSAsim Jamshed {
29076404edcSAsim Jamshed     struct chunk *cp;
29176404edcSAsim Jamshed     int k;
29276404edcSAsim Jamshed     size_t size;
29376404edcSAsim Jamshed 
29476404edcSAsim Jamshed #ifndef __NetBSD__
29576404edcSAsim Jamshed     /* XXX Round up to nearest long. */
29676404edcSAsim Jamshed     n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);
29776404edcSAsim Jamshed #else
29876404edcSAsim Jamshed     /* XXX Round up to structure boundary. */
29976404edcSAsim Jamshed     n = ALIGN(n);
30076404edcSAsim Jamshed #endif
30176404edcSAsim Jamshed 
30276404edcSAsim Jamshed     cp = &chunks[cur_chunk];
30376404edcSAsim Jamshed     if (n > cp->n_left)
30476404edcSAsim Jamshed     {
30576404edcSAsim Jamshed         ++cp, k = ++cur_chunk;
30676404edcSAsim Jamshed         if (k >= NCHUNKS)
30776404edcSAsim Jamshed             bpf_error("out of memory");
30876404edcSAsim Jamshed         size = CHUNK0SIZE << k;
30976404edcSAsim Jamshed         cp->m = (void *) malloc(size);
31076404edcSAsim Jamshed         if (cp->m == NULL)
31176404edcSAsim Jamshed             bpf_error("out of memory");
31276404edcSAsim Jamshed         memset((char *) cp->m, 0, size);
31376404edcSAsim Jamshed         cp->n_left = size;
31476404edcSAsim Jamshed         if (n > size)
31576404edcSAsim Jamshed             bpf_error("out of memory");
31676404edcSAsim Jamshed     }
31776404edcSAsim Jamshed     cp->n_left -= n;
31876404edcSAsim Jamshed     return (void *) ((char *) cp->m + cp->n_left);
31976404edcSAsim Jamshed }
32076404edcSAsim Jamshed 
freechunks()32176404edcSAsim Jamshed static void freechunks()
32276404edcSAsim Jamshed {
32376404edcSAsim Jamshed     int i;
32476404edcSAsim Jamshed 
32576404edcSAsim Jamshed     cur_chunk = 0;
32676404edcSAsim Jamshed     for (i = 0; i < NCHUNKS; ++i)
32776404edcSAsim Jamshed         if (chunks[i].m != NULL)
32876404edcSAsim Jamshed         {
32976404edcSAsim Jamshed             free(chunks[i].m);
33076404edcSAsim Jamshed             chunks[i].m = NULL;
33176404edcSAsim Jamshed         }
33276404edcSAsim Jamshed }
33376404edcSAsim Jamshed 
33476404edcSAsim Jamshed /*
33576404edcSAsim Jamshed  * A strdup whose allocations are freed after code generation is over.
33676404edcSAsim Jamshed  */
sdup(s)33776404edcSAsim Jamshed char *sdup(s)
33876404edcSAsim Jamshed      register const char *s;
33976404edcSAsim Jamshed {
34076404edcSAsim Jamshed     int n = strlen(s) + 1;
34176404edcSAsim Jamshed     char *cp = newchunk(n);
34276404edcSAsim Jamshed 
34376404edcSAsim Jamshed     strlcpy(cp, s, n);
34476404edcSAsim Jamshed     return (cp);
34576404edcSAsim Jamshed }
34676404edcSAsim Jamshed 
new_block(code)34776404edcSAsim Jamshed static inline struct block *new_block(code)
34876404edcSAsim Jamshed      int code;
34976404edcSAsim Jamshed {
35076404edcSAsim Jamshed     struct block *p;
35176404edcSAsim Jamshed 
35276404edcSAsim Jamshed     p = (struct block *) newchunk(sizeof(*p));
35376404edcSAsim Jamshed     p->s.code = code;
35476404edcSAsim Jamshed     p->head = p;
35576404edcSAsim Jamshed 
35676404edcSAsim Jamshed     return p;
35776404edcSAsim Jamshed }
35876404edcSAsim Jamshed 
new_stmt(code)35976404edcSAsim Jamshed static inline struct slist *new_stmt(code)
36076404edcSAsim Jamshed      int code;
36176404edcSAsim Jamshed {
36276404edcSAsim Jamshed     struct slist *p;
36376404edcSAsim Jamshed 
36476404edcSAsim Jamshed     p = (struct slist *) newchunk(sizeof(*p));
36576404edcSAsim Jamshed     p->s.code = code;
36676404edcSAsim Jamshed 
36776404edcSAsim Jamshed     return p;
36876404edcSAsim Jamshed }
36976404edcSAsim Jamshed 
gen_retblk(v)37076404edcSAsim Jamshed static struct block *gen_retblk(v)
37176404edcSAsim Jamshed      int v;
37276404edcSAsim Jamshed {
37376404edcSAsim Jamshed     struct block *b = new_block(BPF_RET | BPF_K);
37476404edcSAsim Jamshed 
37576404edcSAsim Jamshed     b->s.k = v;
37676404edcSAsim Jamshed     return b;
37776404edcSAsim Jamshed }
37876404edcSAsim Jamshed 
syntax()37976404edcSAsim Jamshed static inline void syntax()
38076404edcSAsim Jamshed {
38176404edcSAsim Jamshed     bpf_error("syntax error in filter expression");
38276404edcSAsim Jamshed }
38376404edcSAsim Jamshed 
38476404edcSAsim Jamshed static __thread bpf_u_int32 netmask;
38576404edcSAsim Jamshed static __thread int snaplen;
38676404edcSAsim Jamshed __thread int no_optimize;
38776404edcSAsim Jamshed 
pcap_compile(int snaplen_arg,int linktype_arg,struct bpf_program * program,const char * buf,int optimize,bpf_u_int32 mask)38876404edcSAsim Jamshed DAQ_SO_PUBLIC int pcap_compile(int snaplen_arg, int linktype_arg, struct bpf_program *program, const char *buf, int optimize, bpf_u_int32 mask)
38976404edcSAsim Jamshed {
39076404edcSAsim Jamshed     extern __thread int n_errors;
39176404edcSAsim Jamshed     const char *volatile xbuf = buf;
39276404edcSAsim Jamshed     int len;
39376404edcSAsim Jamshed 
39476404edcSAsim Jamshed     no_optimize = 0;
39576404edcSAsim Jamshed     n_errors = 0;
39676404edcSAsim Jamshed     root = NULL;
39776404edcSAsim Jamshed     init_regs();
39876404edcSAsim Jamshed     if (setjmp(top_ctx))
39976404edcSAsim Jamshed     {
40076404edcSAsim Jamshed #ifdef INET6
40176404edcSAsim Jamshed         if (ai != NULL)
40276404edcSAsim Jamshed         {
40376404edcSAsim Jamshed             freeaddrinfo(ai);
40476404edcSAsim Jamshed             ai = NULL;
40576404edcSAsim Jamshed         }
40676404edcSAsim Jamshed #endif
40776404edcSAsim Jamshed         lex_cleanup();
40876404edcSAsim Jamshed         freechunks();
40976404edcSAsim Jamshed         return (-1);
41076404edcSAsim Jamshed     }
41176404edcSAsim Jamshed 
41276404edcSAsim Jamshed     netmask = mask;
41376404edcSAsim Jamshed 
41476404edcSAsim Jamshed     snaplen = snaplen_arg;
41576404edcSAsim Jamshed     if (snaplen == 0)
41676404edcSAsim Jamshed     {
41776404edcSAsim Jamshed         snprintf(bpf_error_filter, PCAP_ERRBUF_SIZE, "snaplen of 0 rejects all packets");
41876404edcSAsim Jamshed         return -1;
41976404edcSAsim Jamshed     }
42076404edcSAsim Jamshed 
42176404edcSAsim Jamshed     lex_init(xbuf ? xbuf : "");
42276404edcSAsim Jamshed     init_linktype(linktype_arg);
42376404edcSAsim Jamshed     (void) pcap_parse();
42476404edcSAsim Jamshed 
42576404edcSAsim Jamshed     if (n_errors)
42676404edcSAsim Jamshed         syntax();
42776404edcSAsim Jamshed 
42876404edcSAsim Jamshed     if (root == NULL)
42976404edcSAsim Jamshed         root = gen_retblk(snaplen);
43076404edcSAsim Jamshed 
43176404edcSAsim Jamshed     if (optimize && !no_optimize)
43276404edcSAsim Jamshed     {
43376404edcSAsim Jamshed         bpf_optimize(&root);
43476404edcSAsim Jamshed         if (root == NULL || (root->s.code == (BPF_RET | BPF_K) && root->s.k == 0))
43576404edcSAsim Jamshed             bpf_error("expression rejects all packets");
43676404edcSAsim Jamshed     }
43776404edcSAsim Jamshed     program->bf_insns = icode_to_fcode(root, &len);
43876404edcSAsim Jamshed     program->bf_len = len;
43976404edcSAsim Jamshed 
44076404edcSAsim Jamshed     lex_cleanup();
44176404edcSAsim Jamshed     freechunks();
44276404edcSAsim Jamshed     return (0);
44376404edcSAsim Jamshed }
44476404edcSAsim Jamshed 
44576404edcSAsim Jamshed /*
44676404edcSAsim Jamshed  * Clean up a "struct bpf_program" by freeing all the memory allocated
44776404edcSAsim Jamshed  * in it.
44876404edcSAsim Jamshed  */
pcap_freecode(struct bpf_program * program)44976404edcSAsim Jamshed DAQ_SO_PUBLIC void pcap_freecode(struct bpf_program *program)
45076404edcSAsim Jamshed {
45176404edcSAsim Jamshed     program->bf_len = 0;
45276404edcSAsim Jamshed     if (program->bf_insns != NULL)
45376404edcSAsim Jamshed     {
45476404edcSAsim Jamshed         free((char *) program->bf_insns);
45576404edcSAsim Jamshed         program->bf_insns = NULL;
45676404edcSAsim Jamshed     }
45776404edcSAsim Jamshed }
45876404edcSAsim Jamshed 
45976404edcSAsim Jamshed /*
46076404edcSAsim Jamshed  * Backpatch the blocks in 'list' to 'target'.  The 'sense' field indicates
46176404edcSAsim Jamshed  * which of the jt and jf fields has been resolved and which is a pointer
46276404edcSAsim Jamshed  * back to another unresolved block (or nil).  At least one of the fields
46376404edcSAsim Jamshed  * in each block is already resolved.
46476404edcSAsim Jamshed  */
backpatch(list,target)46576404edcSAsim Jamshed static void backpatch(list, target)
46676404edcSAsim Jamshed      struct block *list, *target;
46776404edcSAsim Jamshed {
46876404edcSAsim Jamshed     struct block *next;
46976404edcSAsim Jamshed 
47076404edcSAsim Jamshed     while (list)
47176404edcSAsim Jamshed     {
47276404edcSAsim Jamshed         if (!list->sense)
47376404edcSAsim Jamshed         {
47476404edcSAsim Jamshed             next = JT(list);
47576404edcSAsim Jamshed             JT(list) = target;
47676404edcSAsim Jamshed         }
47776404edcSAsim Jamshed         else
47876404edcSAsim Jamshed         {
47976404edcSAsim Jamshed             next = JF(list);
48076404edcSAsim Jamshed             JF(list) = target;
48176404edcSAsim Jamshed         }
48276404edcSAsim Jamshed         list = next;
48376404edcSAsim Jamshed     }
48476404edcSAsim Jamshed }
48576404edcSAsim Jamshed 
48676404edcSAsim Jamshed /*
48776404edcSAsim Jamshed  * Merge the lists in b0 and b1, using the 'sense' field to indicate
48876404edcSAsim Jamshed  * which of jt and jf is the link.
48976404edcSAsim Jamshed  */
merge(b0,b1)49076404edcSAsim Jamshed static void merge(b0, b1)
49176404edcSAsim Jamshed      struct block *b0, *b1;
49276404edcSAsim Jamshed {
49376404edcSAsim Jamshed     register struct block **p = &b0;
49476404edcSAsim Jamshed 
49576404edcSAsim Jamshed     /* Find end of list. */
49676404edcSAsim Jamshed     while (*p)
49776404edcSAsim Jamshed         p = !((*p)->sense) ? &JT(*p) : &JF(*p);
49876404edcSAsim Jamshed 
49976404edcSAsim Jamshed     /* Concatenate the lists. */
50076404edcSAsim Jamshed     *p = b1;
50176404edcSAsim Jamshed }
50276404edcSAsim Jamshed 
finish_parse(p)50376404edcSAsim Jamshed void finish_parse(p)
50476404edcSAsim Jamshed      struct block *p;
50576404edcSAsim Jamshed {
50676404edcSAsim Jamshed     struct block *ppi_dlt_check;
50776404edcSAsim Jamshed 
50876404edcSAsim Jamshed     /*
50976404edcSAsim Jamshed      * Insert before the statements of the first (root) block any
51076404edcSAsim Jamshed      * statements needed to load the lengths of any variable-length
51176404edcSAsim Jamshed      * headers into registers.
51276404edcSAsim Jamshed      *
51376404edcSAsim Jamshed      * XXX - a fancier strategy would be to insert those before the
51476404edcSAsim Jamshed      * statements of all blocks that use those lengths and that
51576404edcSAsim Jamshed      * have no predecessors that use them, so that we only compute
51676404edcSAsim Jamshed      * the lengths if we need them.  There might be even better
51776404edcSAsim Jamshed      * approaches than that.
51876404edcSAsim Jamshed      *
51976404edcSAsim Jamshed      * However, those strategies would be more complicated, and
52076404edcSAsim Jamshed      * as we don't generate code to compute a length if the
52176404edcSAsim Jamshed      * program has no tests that use the length, and as most
52276404edcSAsim Jamshed      * tests will probably use those lengths, we would just
52376404edcSAsim Jamshed      * postpone computing the lengths so that it's not done
52476404edcSAsim Jamshed      * for tests that fail early, and it's not clear that's
52576404edcSAsim Jamshed      * worth the effort.
52676404edcSAsim Jamshed      */
52776404edcSAsim Jamshed     insert_compute_vloffsets(p->head);
52876404edcSAsim Jamshed 
52976404edcSAsim Jamshed     /*
53076404edcSAsim Jamshed      * For DLT_PPI captures, generate a check of the per-packet
53176404edcSAsim Jamshed      * DLT value to make sure it's DLT_IEEE802_11.
53276404edcSAsim Jamshed      */
53376404edcSAsim Jamshed     ppi_dlt_check = gen_ppi_dlt_check();
53476404edcSAsim Jamshed     if (ppi_dlt_check != NULL)
53576404edcSAsim Jamshed         gen_and(ppi_dlt_check, p);
53676404edcSAsim Jamshed 
53776404edcSAsim Jamshed     backpatch(p, gen_retblk(snaplen));
53876404edcSAsim Jamshed     p->sense = !p->sense;
53976404edcSAsim Jamshed     backpatch(p, gen_retblk(0));
54076404edcSAsim Jamshed     root = p->head;
54176404edcSAsim Jamshed }
54276404edcSAsim Jamshed 
gen_and(b0,b1)54376404edcSAsim Jamshed void gen_and(b0, b1)
54476404edcSAsim Jamshed      struct block *b0, *b1;
54576404edcSAsim Jamshed {
54676404edcSAsim Jamshed     backpatch(b0, b1->head);
54776404edcSAsim Jamshed     b0->sense = !b0->sense;
54876404edcSAsim Jamshed     b1->sense = !b1->sense;
54976404edcSAsim Jamshed     merge(b1, b0);
55076404edcSAsim Jamshed     b1->sense = !b1->sense;
55176404edcSAsim Jamshed     b1->head = b0->head;
55276404edcSAsim Jamshed }
55376404edcSAsim Jamshed 
gen_or(b0,b1)55476404edcSAsim Jamshed void gen_or(b0, b1)
55576404edcSAsim Jamshed      struct block *b0, *b1;
55676404edcSAsim Jamshed {
55776404edcSAsim Jamshed     b0->sense = !b0->sense;
55876404edcSAsim Jamshed     backpatch(b0, b1->head);
55976404edcSAsim Jamshed     b0->sense = !b0->sense;
56076404edcSAsim Jamshed     merge(b1, b0);
56176404edcSAsim Jamshed     b1->head = b0->head;
56276404edcSAsim Jamshed }
56376404edcSAsim Jamshed 
gen_not(b)56476404edcSAsim Jamshed void gen_not(b)
56576404edcSAsim Jamshed      struct block *b;
56676404edcSAsim Jamshed {
56776404edcSAsim Jamshed     b->sense = !b->sense;
56876404edcSAsim Jamshed }
56976404edcSAsim Jamshed 
gen_cmp(offrel,offset,size,v)57076404edcSAsim Jamshed static struct block *gen_cmp(offrel, offset, size, v)
57176404edcSAsim Jamshed      enum e_offrel offrel;
57276404edcSAsim Jamshed      u_int offset, size;
57376404edcSAsim Jamshed      bpf_int32 v;
57476404edcSAsim Jamshed {
57576404edcSAsim Jamshed     return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v);
57676404edcSAsim Jamshed }
57776404edcSAsim Jamshed 
gen_cmp_gt(offrel,offset,size,v)57876404edcSAsim Jamshed static struct block *gen_cmp_gt(offrel, offset, size, v)
57976404edcSAsim Jamshed      enum e_offrel offrel;
58076404edcSAsim Jamshed      u_int offset, size;
58176404edcSAsim Jamshed      bpf_int32 v;
58276404edcSAsim Jamshed {
58376404edcSAsim Jamshed     return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 0, v);
58476404edcSAsim Jamshed }
58576404edcSAsim Jamshed 
gen_cmp_ge(offrel,offset,size,v)58676404edcSAsim Jamshed static struct block *gen_cmp_ge(offrel, offset, size, v)
58776404edcSAsim Jamshed      enum e_offrel offrel;
58876404edcSAsim Jamshed      u_int offset, size;
58976404edcSAsim Jamshed      bpf_int32 v;
59076404edcSAsim Jamshed {
59176404edcSAsim Jamshed     return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 0, v);
59276404edcSAsim Jamshed }
59376404edcSAsim Jamshed 
gen_cmp_lt(offrel,offset,size,v)59476404edcSAsim Jamshed static struct block *gen_cmp_lt(offrel, offset, size, v)
59576404edcSAsim Jamshed      enum e_offrel offrel;
59676404edcSAsim Jamshed      u_int offset, size;
59776404edcSAsim Jamshed      bpf_int32 v;
59876404edcSAsim Jamshed {
59976404edcSAsim Jamshed     return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGE, 1, v);
60076404edcSAsim Jamshed }
60176404edcSAsim Jamshed 
gen_cmp_le(offrel,offset,size,v)60276404edcSAsim Jamshed static struct block *gen_cmp_le(offrel, offset, size, v)
60376404edcSAsim Jamshed      enum e_offrel offrel;
60476404edcSAsim Jamshed      u_int offset, size;
60576404edcSAsim Jamshed      bpf_int32 v;
60676404edcSAsim Jamshed {
60776404edcSAsim Jamshed     return gen_ncmp(offrel, offset, size, 0xffffffff, BPF_JGT, 1, v);
60876404edcSAsim Jamshed }
60976404edcSAsim Jamshed 
gen_mcmp(offrel,offset,size,v,mask)61076404edcSAsim Jamshed static struct block *gen_mcmp(offrel, offset, size, v, mask)
61176404edcSAsim Jamshed      enum e_offrel offrel;
61276404edcSAsim Jamshed      u_int offset, size;
61376404edcSAsim Jamshed      bpf_int32 v;
61476404edcSAsim Jamshed      bpf_u_int32 mask;
61576404edcSAsim Jamshed {
61676404edcSAsim Jamshed     return gen_ncmp(offrel, offset, size, mask, BPF_JEQ, 0, v);
61776404edcSAsim Jamshed }
61876404edcSAsim Jamshed 
gen_bcmp(offrel,offset,size,v)61976404edcSAsim Jamshed static struct block *gen_bcmp(offrel, offset, size, v)
62076404edcSAsim Jamshed      enum e_offrel offrel;
62176404edcSAsim Jamshed      register u_int offset, size;
62276404edcSAsim Jamshed      register const u_char *v;
62376404edcSAsim Jamshed {
62476404edcSAsim Jamshed     register struct block *b, *tmp;
62576404edcSAsim Jamshed 
62676404edcSAsim Jamshed     b = NULL;
62776404edcSAsim Jamshed     while (size >= 4)
62876404edcSAsim Jamshed     {
62976404edcSAsim Jamshed         register const u_char *p = &v[size - 4];
63076404edcSAsim Jamshed         bpf_int32 w = ((bpf_int32) p[0] << 24) | ((bpf_int32) p[1] << 16) | ((bpf_int32) p[2] << 8) | p[3];
63176404edcSAsim Jamshed 
63276404edcSAsim Jamshed         tmp = gen_cmp(offrel, offset + size - 4, BPF_W, w);
63376404edcSAsim Jamshed         if (b != NULL)
63476404edcSAsim Jamshed             gen_and(b, tmp);
63576404edcSAsim Jamshed         b = tmp;
63676404edcSAsim Jamshed         size -= 4;
63776404edcSAsim Jamshed     }
63876404edcSAsim Jamshed     while (size >= 2)
63976404edcSAsim Jamshed     {
64076404edcSAsim Jamshed         register const u_char *p = &v[size - 2];
64176404edcSAsim Jamshed         bpf_int32 w = ((bpf_int32) p[0] << 8) | p[1];
64276404edcSAsim Jamshed 
64376404edcSAsim Jamshed         tmp = gen_cmp(offrel, offset + size - 2, BPF_H, w);
64476404edcSAsim Jamshed         if (b != NULL)
64576404edcSAsim Jamshed             gen_and(b, tmp);
64676404edcSAsim Jamshed         b = tmp;
64776404edcSAsim Jamshed         size -= 2;
64876404edcSAsim Jamshed     }
64976404edcSAsim Jamshed     if (size > 0)
65076404edcSAsim Jamshed     {
65176404edcSAsim Jamshed         tmp = gen_cmp(offrel, offset, BPF_B, (bpf_int32) v[0]);
65276404edcSAsim Jamshed         if (b != NULL)
65376404edcSAsim Jamshed             gen_and(b, tmp);
65476404edcSAsim Jamshed         b = tmp;
65576404edcSAsim Jamshed     }
65676404edcSAsim Jamshed     return b;
65776404edcSAsim Jamshed }
65876404edcSAsim Jamshed 
65976404edcSAsim Jamshed /*
66076404edcSAsim Jamshed  * AND the field of size "size" at offset "offset" relative to the header
66176404edcSAsim Jamshed  * specified by "offrel" with "mask", and compare it with the value "v"
66276404edcSAsim Jamshed  * with the test specified by "jtype"; if "reverse" is true, the test
66376404edcSAsim Jamshed  * should test the opposite of "jtype".
66476404edcSAsim Jamshed  */
gen_ncmp(offrel,offset,size,mask,jtype,reverse,v)66576404edcSAsim Jamshed static struct block *gen_ncmp(offrel, offset, size, mask, jtype, reverse, v)
66676404edcSAsim Jamshed      enum e_offrel offrel;
66776404edcSAsim Jamshed      bpf_int32 v;
66876404edcSAsim Jamshed      bpf_u_int32 offset, size, mask, jtype;
66976404edcSAsim Jamshed      int reverse;
67076404edcSAsim Jamshed {
67176404edcSAsim Jamshed     struct slist *s, *s2;
67276404edcSAsim Jamshed     struct block *b;
67376404edcSAsim Jamshed 
67476404edcSAsim Jamshed     s = gen_load_a(offrel, offset, size);
67576404edcSAsim Jamshed 
67676404edcSAsim Jamshed     if (mask != 0xffffffff)
67776404edcSAsim Jamshed     {
67876404edcSAsim Jamshed         s2 = new_stmt(BPF_ALU | BPF_AND | BPF_K);
67976404edcSAsim Jamshed         s2->s.k = mask;
68076404edcSAsim Jamshed         sappend(s, s2);
68176404edcSAsim Jamshed     }
68276404edcSAsim Jamshed 
68376404edcSAsim Jamshed     b = new_block(JMP(jtype));
68476404edcSAsim Jamshed     b->stmts = s;
68576404edcSAsim Jamshed     b->s.k = v;
68676404edcSAsim Jamshed     if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE))
68776404edcSAsim Jamshed         gen_not(b);
68876404edcSAsim Jamshed     return b;
68976404edcSAsim Jamshed }
69076404edcSAsim Jamshed 
69176404edcSAsim Jamshed /*
69276404edcSAsim Jamshed  * Various code constructs need to know the layout of the data link
69376404edcSAsim Jamshed  * layer.  These variables give the necessary offsets from the beginning
69476404edcSAsim Jamshed  * of the packet data.
69576404edcSAsim Jamshed  */
69676404edcSAsim Jamshed 
69776404edcSAsim Jamshed /*
69876404edcSAsim Jamshed  * This is the offset of the beginning of the link-layer header from
69976404edcSAsim Jamshed  * the beginning of the raw packet data.
70076404edcSAsim Jamshed  *
70176404edcSAsim Jamshed  * It's usually 0, except for 802.11 with a fixed-length radio header.
70276404edcSAsim Jamshed  * (For 802.11 with a variable-length radio header, we have to generate
70376404edcSAsim Jamshed  * code to compute that offset; off_ll is 0 in that case.)
70476404edcSAsim Jamshed  */
70576404edcSAsim Jamshed static __thread u_int off_ll;
70676404edcSAsim Jamshed 
70776404edcSAsim Jamshed /*
70876404edcSAsim Jamshed  * If there's a variable-length header preceding the link-layer header,
70976404edcSAsim Jamshed  * "reg_off_ll" is the register number for a register containing the
71076404edcSAsim Jamshed  * length of that header, and therefore the offset of the link-layer
71176404edcSAsim Jamshed  * header from the beginning of the raw packet data.  Otherwise,
71276404edcSAsim Jamshed  * "reg_off_ll" is -1.
71376404edcSAsim Jamshed  */
71476404edcSAsim Jamshed static __thread int reg_off_ll;
71576404edcSAsim Jamshed 
71676404edcSAsim Jamshed /*
71776404edcSAsim Jamshed  * This is the offset of the beginning of the MAC-layer header from
71876404edcSAsim Jamshed  * the beginning of the link-layer header.
71976404edcSAsim Jamshed  * It's usually 0, except for ATM LANE, where it's the offset, relative
72076404edcSAsim Jamshed  * to the beginning of the raw packet data, of the Ethernet header.
72176404edcSAsim Jamshed  */
72276404edcSAsim Jamshed static __thread u_int off_mac;
72376404edcSAsim Jamshed 
72476404edcSAsim Jamshed /*
72576404edcSAsim Jamshed  * This is the offset of the beginning of the MAC-layer payload,
72676404edcSAsim Jamshed  * from the beginning of the raw packet data.
72776404edcSAsim Jamshed  *
72876404edcSAsim Jamshed  * I.e., it's the sum of the length of the link-layer header (without,
72976404edcSAsim Jamshed  * for example, any 802.2 LLC header, so it's the MAC-layer
73076404edcSAsim Jamshed  * portion of that header), plus any prefix preceding the
73176404edcSAsim Jamshed  * link-layer header.
73276404edcSAsim Jamshed  */
73376404edcSAsim Jamshed static __thread u_int off_macpl;
73476404edcSAsim Jamshed 
73576404edcSAsim Jamshed /*
73676404edcSAsim Jamshed  * This is 1 if the offset of the beginning of the MAC-layer payload
73776404edcSAsim Jamshed  * from the beginning of the link-layer header is variable-length.
73876404edcSAsim Jamshed  */
73976404edcSAsim Jamshed static __thread int off_macpl_is_variable;
74076404edcSAsim Jamshed 
74176404edcSAsim Jamshed /*
74276404edcSAsim Jamshed  * If the link layer has variable_length headers, "reg_off_macpl"
74376404edcSAsim Jamshed  * is the register number for a register containing the length of the
74476404edcSAsim Jamshed  * link-layer header plus the length of any variable-length header
74576404edcSAsim Jamshed  * preceding the link-layer header.  Otherwise, "reg_off_macpl"
74676404edcSAsim Jamshed  * is -1.
74776404edcSAsim Jamshed  */
74876404edcSAsim Jamshed static __thread int reg_off_macpl;
74976404edcSAsim Jamshed 
75076404edcSAsim Jamshed /*
75176404edcSAsim Jamshed  * "off_linktype" is the offset to information in the link-layer header
75276404edcSAsim Jamshed  * giving the packet type.  This offset is relative to the beginning
75376404edcSAsim Jamshed  * of the link-layer header (i.e., it doesn't include off_ll).
75476404edcSAsim Jamshed  *
75576404edcSAsim Jamshed  * For Ethernet, it's the offset of the Ethernet type field.
75676404edcSAsim Jamshed  *
75776404edcSAsim Jamshed  * For link-layer types that always use 802.2 headers, it's the
75876404edcSAsim Jamshed  * offset of the LLC header.
75976404edcSAsim Jamshed  *
76076404edcSAsim Jamshed  * For PPP, it's the offset of the PPP type field.
76176404edcSAsim Jamshed  *
76276404edcSAsim Jamshed  * For Cisco HDLC, it's the offset of the CHDLC type field.
76376404edcSAsim Jamshed  *
76476404edcSAsim Jamshed  * For BSD loopback, it's the offset of the AF_ value.
76576404edcSAsim Jamshed  *
76676404edcSAsim Jamshed  * For Linux cooked sockets, it's the offset of the type field.
76776404edcSAsim Jamshed  *
76876404edcSAsim Jamshed  * It's set to -1 for no encapsulation, in which case, IP is assumed.
76976404edcSAsim Jamshed  */
77076404edcSAsim Jamshed static __thread u_int off_linktype;
77176404edcSAsim Jamshed 
77276404edcSAsim Jamshed /*
77376404edcSAsim Jamshed  * TRUE if "pppoes" appeared in the filter; it causes link-layer type
77476404edcSAsim Jamshed  * checks to check the PPP header, assumed to follow a LAN-style link-
77576404edcSAsim Jamshed  * layer header and a PPPoE session header.
77676404edcSAsim Jamshed  */
77776404edcSAsim Jamshed static __thread int is_pppoes = 0;
77876404edcSAsim Jamshed 
77976404edcSAsim Jamshed /*
78076404edcSAsim Jamshed  * TRUE if the link layer includes an ATM pseudo-header.
78176404edcSAsim Jamshed  */
78276404edcSAsim Jamshed static __thread int is_atm = 0;
78376404edcSAsim Jamshed 
78476404edcSAsim Jamshed /*
78576404edcSAsim Jamshed  * TRUE if "lane" appeared in the filter; it causes us to generate
78676404edcSAsim Jamshed  * code that assumes LANE rather than LLC-encapsulated traffic in SunATM.
78776404edcSAsim Jamshed  */
78876404edcSAsim Jamshed static __thread int is_lane = 0;
78976404edcSAsim Jamshed 
79076404edcSAsim Jamshed /*
79176404edcSAsim Jamshed  * These are offsets for the ATM pseudo-header.
79276404edcSAsim Jamshed  */
79376404edcSAsim Jamshed static __thread u_int off_vpi;
79476404edcSAsim Jamshed static __thread u_int off_vci;
79576404edcSAsim Jamshed static __thread u_int off_proto;
79676404edcSAsim Jamshed 
79776404edcSAsim Jamshed /*
79876404edcSAsim Jamshed  * These are offsets for the MTP2 fields.
79976404edcSAsim Jamshed  */
80076404edcSAsim Jamshed static __thread u_int off_li;
80176404edcSAsim Jamshed 
80276404edcSAsim Jamshed /*
80376404edcSAsim Jamshed  * These are offsets for the MTP3 fields.
80476404edcSAsim Jamshed  */
80576404edcSAsim Jamshed static __thread u_int off_sio;
80676404edcSAsim Jamshed static __thread u_int off_opc;
80776404edcSAsim Jamshed static __thread u_int off_dpc;
80876404edcSAsim Jamshed static __thread u_int off_sls;
80976404edcSAsim Jamshed 
81076404edcSAsim Jamshed /*
81176404edcSAsim Jamshed  * This is the offset of the first byte after the ATM pseudo_header,
81276404edcSAsim Jamshed  * or -1 if there is no ATM pseudo-header.
81376404edcSAsim Jamshed  */
81476404edcSAsim Jamshed static __thread u_int off_payload;
81576404edcSAsim Jamshed 
81676404edcSAsim Jamshed /*
81776404edcSAsim Jamshed  * These are offsets to the beginning of the network-layer header.
81876404edcSAsim Jamshed  * They are relative to the beginning of the MAC-layer payload (i.e.,
81976404edcSAsim Jamshed  * they don't include off_ll or off_macpl).
82076404edcSAsim Jamshed  *
82176404edcSAsim Jamshed  * If the link layer never uses 802.2 LLC:
82276404edcSAsim Jamshed  *
82376404edcSAsim Jamshed  *	"off_nl" and "off_nl_nosnap" are the same.
82476404edcSAsim Jamshed  *
82576404edcSAsim Jamshed  * If the link layer always uses 802.2 LLC:
82676404edcSAsim Jamshed  *
82776404edcSAsim Jamshed  *	"off_nl" is the offset if there's a SNAP header following
82876404edcSAsim Jamshed  *	the 802.2 header;
82976404edcSAsim Jamshed  *
83076404edcSAsim Jamshed  *	"off_nl_nosnap" is the offset if there's no SNAP header.
83176404edcSAsim Jamshed  *
83276404edcSAsim Jamshed  * If the link layer is Ethernet:
83376404edcSAsim Jamshed  *
83476404edcSAsim Jamshed  *	"off_nl" is the offset if the packet is an Ethernet II packet
83576404edcSAsim Jamshed  *	(we assume no 802.3+802.2+SNAP);
83676404edcSAsim Jamshed  *
83776404edcSAsim Jamshed  *	"off_nl_nosnap" is the offset if the packet is an 802.3 packet
83876404edcSAsim Jamshed  *	with an 802.2 header following it.
83976404edcSAsim Jamshed  */
84076404edcSAsim Jamshed static __thread u_int off_nl;
84176404edcSAsim Jamshed static __thread u_int off_nl_nosnap;
84276404edcSAsim Jamshed 
84376404edcSAsim Jamshed static __thread int linktype;
84476404edcSAsim Jamshed 
init_linktype(type)84576404edcSAsim Jamshed static void init_linktype(type)
84676404edcSAsim Jamshed      int type;
84776404edcSAsim Jamshed {
84876404edcSAsim Jamshed     linktype = type;
84976404edcSAsim Jamshed #ifdef PCAP_FDDIPAD
85076404edcSAsim Jamshed     pcap_fddipad = p->fddipad;
85176404edcSAsim Jamshed #endif
85276404edcSAsim Jamshed 
85376404edcSAsim Jamshed     /*
85476404edcSAsim Jamshed      * Assume it's not raw ATM with a pseudo-header, for now.
85576404edcSAsim Jamshed      */
85676404edcSAsim Jamshed     off_mac = 0;
85776404edcSAsim Jamshed     is_atm = 0;
85876404edcSAsim Jamshed     is_lane = 0;
85976404edcSAsim Jamshed     off_vpi = -1;
86076404edcSAsim Jamshed     off_vci = -1;
86176404edcSAsim Jamshed     off_proto = -1;
86276404edcSAsim Jamshed     off_payload = -1;
86376404edcSAsim Jamshed 
86476404edcSAsim Jamshed     /*
86576404edcSAsim Jamshed      * And that we're not doing PPPoE.
86676404edcSAsim Jamshed      */
86776404edcSAsim Jamshed     is_pppoes = 0;
86876404edcSAsim Jamshed 
86976404edcSAsim Jamshed     /*
87076404edcSAsim Jamshed      * And assume we're not doing SS7.
87176404edcSAsim Jamshed      */
87276404edcSAsim Jamshed     off_li = -1;
87376404edcSAsim Jamshed     off_sio = -1;
87476404edcSAsim Jamshed     off_opc = -1;
87576404edcSAsim Jamshed     off_dpc = -1;
87676404edcSAsim Jamshed     off_sls = -1;
87776404edcSAsim Jamshed 
87876404edcSAsim Jamshed     /*
87976404edcSAsim Jamshed      * Also assume it's not 802.11.
88076404edcSAsim Jamshed      */
88176404edcSAsim Jamshed     off_ll = 0;
88276404edcSAsim Jamshed     off_macpl = 0;
88376404edcSAsim Jamshed     off_macpl_is_variable = 0;
88476404edcSAsim Jamshed 
88576404edcSAsim Jamshed     orig_linktype = -1;
88676404edcSAsim Jamshed     orig_nl = -1;
88776404edcSAsim Jamshed     label_stack_depth = 0;
88876404edcSAsim Jamshed 
88976404edcSAsim Jamshed     reg_off_ll = -1;
89076404edcSAsim Jamshed     reg_off_macpl = -1;
89176404edcSAsim Jamshed 
89276404edcSAsim Jamshed     switch (linktype)
89376404edcSAsim Jamshed     {
89476404edcSAsim Jamshed 
89576404edcSAsim Jamshed         case DLT_ARCNET:
89676404edcSAsim Jamshed             off_linktype = 2;
89776404edcSAsim Jamshed             off_macpl = 6;
89876404edcSAsim Jamshed             off_nl = 0;         /* XXX in reality, variable! */
89976404edcSAsim Jamshed             off_nl_nosnap = 0;  /* no 802.2 LLC */
90076404edcSAsim Jamshed             return;
90176404edcSAsim Jamshed 
90276404edcSAsim Jamshed         case DLT_ARCNET_LINUX:
90376404edcSAsim Jamshed             off_linktype = 4;
90476404edcSAsim Jamshed             off_macpl = 8;
90576404edcSAsim Jamshed             off_nl = 0;         /* XXX in reality, variable! */
90676404edcSAsim Jamshed             off_nl_nosnap = 0;  /* no 802.2 LLC */
90776404edcSAsim Jamshed             return;
90876404edcSAsim Jamshed 
90976404edcSAsim Jamshed         case DLT_EN10MB:
91076404edcSAsim Jamshed             off_linktype = 12;
91176404edcSAsim Jamshed             off_macpl = 14;     /* Ethernet header length */
91276404edcSAsim Jamshed             off_nl = 0;         /* Ethernet II */
91376404edcSAsim Jamshed             off_nl_nosnap = 3;  /* 802.3+802.2 */
91476404edcSAsim Jamshed             return;
91576404edcSAsim Jamshed 
91676404edcSAsim Jamshed         case DLT_SLIP:
91776404edcSAsim Jamshed             /*
91876404edcSAsim Jamshed              * SLIP doesn't have a link level type.  The 16 byte
91976404edcSAsim Jamshed              * header is hacked into our SLIP driver.
92076404edcSAsim Jamshed              */
92176404edcSAsim Jamshed             off_linktype = -1;
92276404edcSAsim Jamshed             off_macpl = 16;
92376404edcSAsim Jamshed             off_nl = 0;
92476404edcSAsim Jamshed             off_nl_nosnap = 0;  /* no 802.2 LLC */
92576404edcSAsim Jamshed             return;
92676404edcSAsim Jamshed 
92776404edcSAsim Jamshed         case DLT_SLIP_BSDOS:
92876404edcSAsim Jamshed             /* XXX this may be the same as the DLT_PPP_BSDOS case */
92976404edcSAsim Jamshed             off_linktype = -1;
93076404edcSAsim Jamshed             /* XXX end */
93176404edcSAsim Jamshed             off_macpl = 24;
93276404edcSAsim Jamshed             off_nl = 0;
93376404edcSAsim Jamshed             off_nl_nosnap = 0;  /* no 802.2 LLC */
93476404edcSAsim Jamshed             return;
93576404edcSAsim Jamshed 
93676404edcSAsim Jamshed         case DLT_NULL:
93776404edcSAsim Jamshed         case DLT_LOOP:
93876404edcSAsim Jamshed             off_linktype = 0;
93976404edcSAsim Jamshed             off_macpl = 4;
94076404edcSAsim Jamshed             off_nl = 0;
94176404edcSAsim Jamshed             off_nl_nosnap = 0;  /* no 802.2 LLC */
94276404edcSAsim Jamshed             return;
94376404edcSAsim Jamshed 
94476404edcSAsim Jamshed         case DLT_ENC:
94576404edcSAsim Jamshed             off_linktype = 0;
94676404edcSAsim Jamshed             off_macpl = 12;
94776404edcSAsim Jamshed             off_nl = 0;
94876404edcSAsim Jamshed             off_nl_nosnap = 0;  /* no 802.2 LLC */
94976404edcSAsim Jamshed             return;
95076404edcSAsim Jamshed 
95176404edcSAsim Jamshed         case DLT_PPP:
95276404edcSAsim Jamshed         case DLT_PPP_PPPD:
95376404edcSAsim Jamshed         case DLT_C_HDLC:       /* BSD/OS Cisco HDLC */
95476404edcSAsim Jamshed         case DLT_PPP_SERIAL:   /* NetBSD sync/async serial PPP */
95576404edcSAsim Jamshed             off_linktype = 2;
95676404edcSAsim Jamshed             off_macpl = 4;
95776404edcSAsim Jamshed             off_nl = 0;
95876404edcSAsim Jamshed             off_nl_nosnap = 0;  /* no 802.2 LLC */
95976404edcSAsim Jamshed             return;
96076404edcSAsim Jamshed 
96176404edcSAsim Jamshed         case DLT_PPP_ETHER:
96276404edcSAsim Jamshed             /*
96376404edcSAsim Jamshed              * This does no include the Ethernet header, and
96476404edcSAsim Jamshed              * only covers session state.
96576404edcSAsim Jamshed              */
96676404edcSAsim Jamshed             off_linktype = 6;
96776404edcSAsim Jamshed             off_macpl = 8;
96876404edcSAsim Jamshed             off_nl = 0;
96976404edcSAsim Jamshed             off_nl_nosnap = 0;  /* no 802.2 LLC */
97076404edcSAsim Jamshed             return;
97176404edcSAsim Jamshed 
97276404edcSAsim Jamshed         case DLT_PPP_BSDOS:
97376404edcSAsim Jamshed             off_linktype = 5;
97476404edcSAsim Jamshed             off_macpl = 24;
97576404edcSAsim Jamshed             off_nl = 0;
97676404edcSAsim Jamshed             off_nl_nosnap = 0;  /* no 802.2 LLC */
97776404edcSAsim Jamshed             return;
97876404edcSAsim Jamshed 
97976404edcSAsim Jamshed         case DLT_FDDI:
98076404edcSAsim Jamshed             /*
98176404edcSAsim Jamshed              * FDDI doesn't really have a link-level type field.
98276404edcSAsim Jamshed              * We set "off_linktype" to the offset of the LLC header.
98376404edcSAsim Jamshed              *
98476404edcSAsim Jamshed              * To check for Ethernet types, we assume that SSAP = SNAP
98576404edcSAsim Jamshed              * is being used and pick out the encapsulated Ethernet type.
98676404edcSAsim Jamshed              * XXX - should we generate code to check for SNAP?
98776404edcSAsim Jamshed              */
98876404edcSAsim Jamshed             off_linktype = 13;
98976404edcSAsim Jamshed #ifdef PCAP_FDDIPAD
99076404edcSAsim Jamshed             off_linktype += pcap_fddipad;
99176404edcSAsim Jamshed #endif
99276404edcSAsim Jamshed             off_macpl = 13;     /* FDDI MAC header length */
99376404edcSAsim Jamshed #ifdef PCAP_FDDIPAD
99476404edcSAsim Jamshed             off_macpl += pcap_fddipad;
99576404edcSAsim Jamshed #endif
99676404edcSAsim Jamshed             off_nl = 8;         /* 802.2+SNAP */
99776404edcSAsim Jamshed             off_nl_nosnap = 3;  /* 802.2 */
99876404edcSAsim Jamshed             return;
99976404edcSAsim Jamshed 
100076404edcSAsim Jamshed         case DLT_IEEE802:
100176404edcSAsim Jamshed             /*
100276404edcSAsim Jamshed              * Token Ring doesn't really have a link-level type field.
100376404edcSAsim Jamshed              * We set "off_linktype" to the offset of the LLC header.
100476404edcSAsim Jamshed              *
100576404edcSAsim Jamshed              * To check for Ethernet types, we assume that SSAP = SNAP
100676404edcSAsim Jamshed              * is being used and pick out the encapsulated Ethernet type.
100776404edcSAsim Jamshed              * XXX - should we generate code to check for SNAP?
100876404edcSAsim Jamshed              *
100976404edcSAsim Jamshed              * XXX - the header is actually variable-length.
101076404edcSAsim Jamshed              * Some various Linux patched versions gave 38
101176404edcSAsim Jamshed              * as "off_linktype" and 40 as "off_nl"; however,
101276404edcSAsim Jamshed              * if a token ring packet has *no* routing
101376404edcSAsim Jamshed              * information, i.e. is not source-routed, the correct
101476404edcSAsim Jamshed              * values are 20 and 22, as they are in the vanilla code.
101576404edcSAsim Jamshed              *
101676404edcSAsim Jamshed              * A packet is source-routed iff the uppermost bit
101776404edcSAsim Jamshed              * of the first byte of the source address, at an
101876404edcSAsim Jamshed              * offset of 8, has the uppermost bit set.  If the
101976404edcSAsim Jamshed              * packet is source-routed, the total number of bytes
102076404edcSAsim Jamshed              * of routing information is 2 plus bits 0x1F00 of
102176404edcSAsim Jamshed              * the 16-bit value at an offset of 14 (shifted right
102276404edcSAsim Jamshed              * 8 - figure out which byte that is).
102376404edcSAsim Jamshed              */
102476404edcSAsim Jamshed             off_linktype = 14;
102576404edcSAsim Jamshed             off_macpl = 14;     /* Token Ring MAC header length */
102676404edcSAsim Jamshed             off_nl = 8;         /* 802.2+SNAP */
102776404edcSAsim Jamshed             off_nl_nosnap = 3;  /* 802.2 */
102876404edcSAsim Jamshed             return;
102976404edcSAsim Jamshed 
103076404edcSAsim Jamshed         case DLT_IEEE802_11:
103176404edcSAsim Jamshed         case DLT_PRISM_HEADER:
103276404edcSAsim Jamshed         case DLT_IEEE802_11_RADIO_AVS:
103376404edcSAsim Jamshed         case DLT_IEEE802_11_RADIO:
103476404edcSAsim Jamshed             /*
103576404edcSAsim Jamshed              * 802.11 doesn't really have a link-level type field.
103676404edcSAsim Jamshed              * We set "off_linktype" to the offset of the LLC header.
103776404edcSAsim Jamshed              *
103876404edcSAsim Jamshed              * To check for Ethernet types, we assume that SSAP = SNAP
103976404edcSAsim Jamshed              * is being used and pick out the encapsulated Ethernet type.
104076404edcSAsim Jamshed              * XXX - should we generate code to check for SNAP?
104176404edcSAsim Jamshed              *
104276404edcSAsim Jamshed              * We also handle variable-length radio headers here.
104376404edcSAsim Jamshed              * The Prism header is in theory variable-length, but in
104476404edcSAsim Jamshed              * practice it's always 144 bytes long.  However, some
104576404edcSAsim Jamshed              * drivers on Linux use ARPHRD_IEEE80211_PRISM, but
104676404edcSAsim Jamshed              * sometimes or always supply an AVS header, so we
104776404edcSAsim Jamshed              * have to check whether the radio header is a Prism
104876404edcSAsim Jamshed              * header or an AVS header, so, in practice, it's
104976404edcSAsim Jamshed              * variable-length.
105076404edcSAsim Jamshed              */
105176404edcSAsim Jamshed             off_linktype = 24;
105276404edcSAsim Jamshed             off_macpl = 0;      /* link-layer header is variable-length */
105376404edcSAsim Jamshed             off_macpl_is_variable = 1;
105476404edcSAsim Jamshed             off_nl = 8;         /* 802.2+SNAP */
105576404edcSAsim Jamshed             off_nl_nosnap = 3;  /* 802.2 */
105676404edcSAsim Jamshed             return;
105776404edcSAsim Jamshed 
105876404edcSAsim Jamshed         case DLT_PPI:
105976404edcSAsim Jamshed             /*
106076404edcSAsim Jamshed              * At the moment we treat PPI the same way that we treat
106176404edcSAsim Jamshed              * normal Radiotap encoded packets. The difference is in
106276404edcSAsim Jamshed              * the function that generates the code at the beginning
106376404edcSAsim Jamshed              * to compute the header length.  Since this code generator
106476404edcSAsim Jamshed              * of PPI supports bare 802.11 encapsulation only (i.e.
106576404edcSAsim Jamshed              * the encapsulated DLT should be DLT_IEEE802_11) we
106676404edcSAsim Jamshed              * generate code to check for this too.
106776404edcSAsim Jamshed              */
106876404edcSAsim Jamshed             off_linktype = 24;
106976404edcSAsim Jamshed             off_macpl = 0;      /* link-layer header is variable-length */
107076404edcSAsim Jamshed             off_macpl_is_variable = 1;
107176404edcSAsim Jamshed             off_nl = 8;         /* 802.2+SNAP */
107276404edcSAsim Jamshed             off_nl_nosnap = 3;  /* 802.2 */
107376404edcSAsim Jamshed             return;
107476404edcSAsim Jamshed 
107576404edcSAsim Jamshed         case DLT_ATM_RFC1483:
107676404edcSAsim Jamshed         case DLT_ATM_CLIP:     /* Linux ATM defines this */
107776404edcSAsim Jamshed             /*
107876404edcSAsim Jamshed              * assume routed, non-ISO PDUs
107976404edcSAsim Jamshed              * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00)
108076404edcSAsim Jamshed              *
108176404edcSAsim Jamshed              * XXX - what about ISO PDUs, e.g. CLNP, ISIS, ESIS,
108276404edcSAsim Jamshed              * or PPP with the PPP NLPID (e.g., PPPoA)?  The
108376404edcSAsim Jamshed              * latter would presumably be treated the way PPPoE
108476404edcSAsim Jamshed              * should be, so you can do "pppoe and udp port 2049"
108576404edcSAsim Jamshed              * or "pppoa and tcp port 80" and have it check for
108676404edcSAsim Jamshed              * PPPo{A,E} and a PPP protocol of IP and....
108776404edcSAsim Jamshed              */
108876404edcSAsim Jamshed             off_linktype = 0;
108976404edcSAsim Jamshed             off_macpl = 0;      /* packet begins with LLC header */
109076404edcSAsim Jamshed             off_nl = 8;         /* 802.2+SNAP */
109176404edcSAsim Jamshed             off_nl_nosnap = 3;  /* 802.2 */
109276404edcSAsim Jamshed             return;
109376404edcSAsim Jamshed 
109476404edcSAsim Jamshed         case DLT_SUNATM:
109576404edcSAsim Jamshed             /*
109676404edcSAsim Jamshed              * Full Frontal ATM; you get AALn PDUs with an ATM
109776404edcSAsim Jamshed              * pseudo-header.
109876404edcSAsim Jamshed              */
109976404edcSAsim Jamshed             is_atm = 1;
110076404edcSAsim Jamshed             off_vpi = SUNATM_VPI_POS;
110176404edcSAsim Jamshed             off_vci = SUNATM_VCI_POS;
110276404edcSAsim Jamshed             off_proto = PROTO_POS;
110376404edcSAsim Jamshed             off_mac = -1;       /* assume LLC-encapsulated, so no MAC-layer header */
110476404edcSAsim Jamshed             off_payload = SUNATM_PKT_BEGIN_POS;
110576404edcSAsim Jamshed             off_linktype = off_payload;
110676404edcSAsim Jamshed             off_macpl = off_payload;    /* if LLC-encapsulated */
110776404edcSAsim Jamshed             off_nl = 8;         /* 802.2+SNAP */
110876404edcSAsim Jamshed             off_nl_nosnap = 3;  /* 802.2 */
110976404edcSAsim Jamshed             return;
111076404edcSAsim Jamshed 
111176404edcSAsim Jamshed         case DLT_RAW:
111276404edcSAsim Jamshed         case DLT_IPV4:
111376404edcSAsim Jamshed         case DLT_IPV6:
111476404edcSAsim Jamshed             off_linktype = -1;
111576404edcSAsim Jamshed             off_macpl = 0;
111676404edcSAsim Jamshed             off_nl = 0;
111776404edcSAsim Jamshed             off_nl_nosnap = 0;  /* no 802.2 LLC */
111876404edcSAsim Jamshed             return;
111976404edcSAsim Jamshed 
112076404edcSAsim Jamshed         case DLT_LINUX_SLL:    /* fake header for Linux cooked socket */
112176404edcSAsim Jamshed             off_linktype = 14;
112276404edcSAsim Jamshed             off_macpl = 16;
112376404edcSAsim Jamshed             off_nl = 0;
112476404edcSAsim Jamshed             off_nl_nosnap = 0;  /* no 802.2 LLC */
112576404edcSAsim Jamshed             return;
112676404edcSAsim Jamshed 
112776404edcSAsim Jamshed         case DLT_LTALK:
112876404edcSAsim Jamshed             /*
112976404edcSAsim Jamshed              * LocalTalk does have a 1-byte type field in the LLAP header,
113076404edcSAsim Jamshed              * but really it just indicates whether there is a "short" or
113176404edcSAsim Jamshed              * "long" DDP packet following.
113276404edcSAsim Jamshed              */
113376404edcSAsim Jamshed             off_linktype = -1;
113476404edcSAsim Jamshed             off_macpl = 0;
113576404edcSAsim Jamshed             off_nl = 0;
113676404edcSAsim Jamshed             off_nl_nosnap = 0;  /* no 802.2 LLC */
113776404edcSAsim Jamshed             return;
113876404edcSAsim Jamshed 
113976404edcSAsim Jamshed         case DLT_IP_OVER_FC:
114076404edcSAsim Jamshed             /*
114176404edcSAsim Jamshed              * RFC 2625 IP-over-Fibre-Channel doesn't really have a
114276404edcSAsim Jamshed              * link-level type field.  We set "off_linktype" to the
114376404edcSAsim Jamshed              * offset of the LLC header.
114476404edcSAsim Jamshed              *
114576404edcSAsim Jamshed              * To check for Ethernet types, we assume that SSAP = SNAP
114676404edcSAsim Jamshed              * is being used and pick out the encapsulated Ethernet type.
114776404edcSAsim Jamshed              * XXX - should we generate code to check for SNAP? RFC
114876404edcSAsim Jamshed              * 2625 says SNAP should be used.
114976404edcSAsim Jamshed              */
115076404edcSAsim Jamshed             off_linktype = 16;
115176404edcSAsim Jamshed             off_macpl = 16;
115276404edcSAsim Jamshed             off_nl = 8;         /* 802.2+SNAP */
115376404edcSAsim Jamshed             off_nl_nosnap = 3;  /* 802.2 */
115476404edcSAsim Jamshed             return;
115576404edcSAsim Jamshed 
115676404edcSAsim Jamshed         case DLT_FRELAY:
115776404edcSAsim Jamshed             /*
115876404edcSAsim Jamshed              * XXX - we should set this to handle SNAP-encapsulated
115976404edcSAsim Jamshed              * frames (NLPID of 0x80).
116076404edcSAsim Jamshed              */
116176404edcSAsim Jamshed             off_linktype = -1;
116276404edcSAsim Jamshed             off_macpl = 0;
116376404edcSAsim Jamshed             off_nl = 0;
116476404edcSAsim Jamshed             off_nl_nosnap = 0;  /* no 802.2 LLC */
116576404edcSAsim Jamshed             return;
116676404edcSAsim Jamshed 
116776404edcSAsim Jamshed             /*
116876404edcSAsim Jamshed              * the only BPF-interesting FRF.16 frames are non-control frames;
116976404edcSAsim Jamshed              * Frame Relay has a variable length link-layer
117076404edcSAsim Jamshed              * so lets start with offset 4 for now and increments later on (FIXME);
117176404edcSAsim Jamshed              */
117276404edcSAsim Jamshed         case DLT_MFR:
117376404edcSAsim Jamshed             off_linktype = -1;
117476404edcSAsim Jamshed             off_macpl = 0;
117576404edcSAsim Jamshed             off_nl = 4;
117676404edcSAsim Jamshed             off_nl_nosnap = 0;  /* XXX - for now -> no 802.2 LLC */
117776404edcSAsim Jamshed             return;
117876404edcSAsim Jamshed 
117976404edcSAsim Jamshed         case DLT_APPLE_IP_OVER_IEEE1394:
118076404edcSAsim Jamshed             off_linktype = 16;
118176404edcSAsim Jamshed             off_macpl = 18;
118276404edcSAsim Jamshed             off_nl = 0;
118376404edcSAsim Jamshed             off_nl_nosnap = 0;  /* no 802.2 LLC */
118476404edcSAsim Jamshed             return;
118576404edcSAsim Jamshed 
118676404edcSAsim Jamshed         case DLT_LINUX_IRDA:
118776404edcSAsim Jamshed             /*
118876404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
118976404edcSAsim Jamshed              */
119076404edcSAsim Jamshed             off_linktype = -1;
119176404edcSAsim Jamshed             off_macpl = -1;
119276404edcSAsim Jamshed             off_nl = -1;
119376404edcSAsim Jamshed             off_nl_nosnap = -1;
119476404edcSAsim Jamshed             return;
119576404edcSAsim Jamshed 
119676404edcSAsim Jamshed         case DLT_DOCSIS:
119776404edcSAsim Jamshed             /*
119876404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
119976404edcSAsim Jamshed              */
120076404edcSAsim Jamshed             off_linktype = -1;
120176404edcSAsim Jamshed             off_macpl = -1;
120276404edcSAsim Jamshed             off_nl = -1;
120376404edcSAsim Jamshed             off_nl_nosnap = -1;
120476404edcSAsim Jamshed             return;
120576404edcSAsim Jamshed 
120676404edcSAsim Jamshed         case DLT_SYMANTEC_FIREWALL:
120776404edcSAsim Jamshed             off_linktype = 6;
120876404edcSAsim Jamshed             off_macpl = 44;
120976404edcSAsim Jamshed             off_nl = 0;         /* Ethernet II */
121076404edcSAsim Jamshed             off_nl_nosnap = 0;  /* XXX - what does it do with 802.3 packets? */
121176404edcSAsim Jamshed             return;
121276404edcSAsim Jamshed 
121376404edcSAsim Jamshed #ifdef HAVE_NET_PFVAR_H
121476404edcSAsim Jamshed         case DLT_PFLOG:
121576404edcSAsim Jamshed             off_linktype = 0;
121676404edcSAsim Jamshed             off_macpl = PFLOG_HDRLEN;
121776404edcSAsim Jamshed             off_nl = 0;
121876404edcSAsim Jamshed             off_nl_nosnap = 0;  /* no 802.2 LLC */
121976404edcSAsim Jamshed             return;
122076404edcSAsim Jamshed #endif
122176404edcSAsim Jamshed 
122276404edcSAsim Jamshed         case DLT_JUNIPER_MFR:
122376404edcSAsim Jamshed         case DLT_JUNIPER_MLFR:
122476404edcSAsim Jamshed         case DLT_JUNIPER_MLPPP:
122576404edcSAsim Jamshed         case DLT_JUNIPER_PPP:
122676404edcSAsim Jamshed         case DLT_JUNIPER_CHDLC:
122776404edcSAsim Jamshed         case DLT_JUNIPER_FRELAY:
122876404edcSAsim Jamshed             off_linktype = 4;
122976404edcSAsim Jamshed             off_macpl = 4;
123076404edcSAsim Jamshed             off_nl = 0;
123176404edcSAsim Jamshed             off_nl_nosnap = -1; /* no 802.2 LLC */
123276404edcSAsim Jamshed             return;
123376404edcSAsim Jamshed 
123476404edcSAsim Jamshed         case DLT_JUNIPER_ATM1:
123576404edcSAsim Jamshed             off_linktype = 4;   /* in reality variable between 4-8 */
123676404edcSAsim Jamshed             off_macpl = 4;      /* in reality variable between 4-8 */
123776404edcSAsim Jamshed             off_nl = 0;
123876404edcSAsim Jamshed             off_nl_nosnap = 10;
123976404edcSAsim Jamshed             return;
124076404edcSAsim Jamshed 
124176404edcSAsim Jamshed         case DLT_JUNIPER_ATM2:
124276404edcSAsim Jamshed             off_linktype = 8;   /* in reality variable between 8-12 */
124376404edcSAsim Jamshed             off_macpl = 8;      /* in reality variable between 8-12 */
124476404edcSAsim Jamshed             off_nl = 0;
124576404edcSAsim Jamshed             off_nl_nosnap = 10;
124676404edcSAsim Jamshed             return;
124776404edcSAsim Jamshed 
124876404edcSAsim Jamshed             /* frames captured on a Juniper PPPoE service PIC
124976404edcSAsim Jamshed              * contain raw ethernet frames */
125076404edcSAsim Jamshed         case DLT_JUNIPER_PPPOE:
125176404edcSAsim Jamshed         case DLT_JUNIPER_ETHER:
125276404edcSAsim Jamshed             off_macpl = 14;
125376404edcSAsim Jamshed             off_linktype = 16;
125476404edcSAsim Jamshed             off_nl = 18;        /* Ethernet II */
125576404edcSAsim Jamshed             off_nl_nosnap = 21; /* 802.3+802.2 */
125676404edcSAsim Jamshed             return;
125776404edcSAsim Jamshed 
125876404edcSAsim Jamshed         case DLT_JUNIPER_PPPOE_ATM:
125976404edcSAsim Jamshed             off_linktype = 4;
126076404edcSAsim Jamshed             off_macpl = 6;
126176404edcSAsim Jamshed             off_nl = 0;
126276404edcSAsim Jamshed             off_nl_nosnap = -1; /* no 802.2 LLC */
126376404edcSAsim Jamshed             return;
126476404edcSAsim Jamshed 
126576404edcSAsim Jamshed         case DLT_JUNIPER_GGSN:
126676404edcSAsim Jamshed             off_linktype = 6;
126776404edcSAsim Jamshed             off_macpl = 12;
126876404edcSAsim Jamshed             off_nl = 0;
126976404edcSAsim Jamshed             off_nl_nosnap = -1; /* no 802.2 LLC */
127076404edcSAsim Jamshed             return;
127176404edcSAsim Jamshed 
127276404edcSAsim Jamshed         case DLT_JUNIPER_ES:
127376404edcSAsim Jamshed             off_linktype = 6;
127476404edcSAsim Jamshed             off_macpl = -1;     /* not really a network layer but raw IP addresses */
127576404edcSAsim Jamshed             off_nl = -1;        /* not really a network layer but raw IP addresses */
127676404edcSAsim Jamshed             off_nl_nosnap = -1; /* no 802.2 LLC */
127776404edcSAsim Jamshed             return;
127876404edcSAsim Jamshed 
127976404edcSAsim Jamshed         case DLT_JUNIPER_MONITOR:
128076404edcSAsim Jamshed             off_linktype = 12;
128176404edcSAsim Jamshed             off_macpl = 12;
128276404edcSAsim Jamshed             off_nl = 0;         /* raw IP/IP6 header */
128376404edcSAsim Jamshed             off_nl_nosnap = -1; /* no 802.2 LLC */
128476404edcSAsim Jamshed             return;
128576404edcSAsim Jamshed 
128676404edcSAsim Jamshed         case DLT_JUNIPER_SERVICES:
128776404edcSAsim Jamshed             off_linktype = 12;
128876404edcSAsim Jamshed             off_macpl = -1;     /* L3 proto location dep. on cookie type */
128976404edcSAsim Jamshed             off_nl = -1;        /* L3 proto location dep. on cookie type */
129076404edcSAsim Jamshed             off_nl_nosnap = -1; /* no 802.2 LLC */
129176404edcSAsim Jamshed             return;
129276404edcSAsim Jamshed 
129376404edcSAsim Jamshed         case DLT_JUNIPER_VP:
129476404edcSAsim Jamshed             off_linktype = 18;
129576404edcSAsim Jamshed             off_macpl = -1;
129676404edcSAsim Jamshed             off_nl = -1;
129776404edcSAsim Jamshed             off_nl_nosnap = -1;
129876404edcSAsim Jamshed             return;
129976404edcSAsim Jamshed 
130076404edcSAsim Jamshed         case DLT_JUNIPER_ST:
130176404edcSAsim Jamshed             off_linktype = 18;
130276404edcSAsim Jamshed             off_macpl = -1;
130376404edcSAsim Jamshed             off_nl = -1;
130476404edcSAsim Jamshed             off_nl_nosnap = -1;
130576404edcSAsim Jamshed             return;
130676404edcSAsim Jamshed 
130776404edcSAsim Jamshed         case DLT_JUNIPER_ISM:
130876404edcSAsim Jamshed             off_linktype = 8;
130976404edcSAsim Jamshed             off_macpl = -1;
131076404edcSAsim Jamshed             off_nl = -1;
131176404edcSAsim Jamshed             off_nl_nosnap = -1;
131276404edcSAsim Jamshed             return;
131376404edcSAsim Jamshed 
131476404edcSAsim Jamshed         case DLT_MTP2:
131576404edcSAsim Jamshed             off_li = 2;
131676404edcSAsim Jamshed             off_sio = 3;
131776404edcSAsim Jamshed             off_opc = 4;
131876404edcSAsim Jamshed             off_dpc = 4;
131976404edcSAsim Jamshed             off_sls = 7;
132076404edcSAsim Jamshed             off_linktype = -1;
132176404edcSAsim Jamshed             off_macpl = -1;
132276404edcSAsim Jamshed             off_nl = -1;
132376404edcSAsim Jamshed             off_nl_nosnap = -1;
132476404edcSAsim Jamshed             return;
132576404edcSAsim Jamshed 
132676404edcSAsim Jamshed         case DLT_MTP2_WITH_PHDR:
132776404edcSAsim Jamshed             off_li = 6;
132876404edcSAsim Jamshed             off_sio = 7;
132976404edcSAsim Jamshed             off_opc = 8;
133076404edcSAsim Jamshed             off_dpc = 8;
133176404edcSAsim Jamshed             off_sls = 11;
133276404edcSAsim Jamshed             off_linktype = -1;
133376404edcSAsim Jamshed             off_macpl = -1;
133476404edcSAsim Jamshed             off_nl = -1;
133576404edcSAsim Jamshed             off_nl_nosnap = -1;
133676404edcSAsim Jamshed             return;
133776404edcSAsim Jamshed 
133876404edcSAsim Jamshed         case DLT_ERF:
133976404edcSAsim Jamshed             off_li = 22;
134076404edcSAsim Jamshed             off_sio = 23;
134176404edcSAsim Jamshed             off_opc = 24;
134276404edcSAsim Jamshed             off_dpc = 24;
134376404edcSAsim Jamshed             off_sls = 27;
134476404edcSAsim Jamshed             off_linktype = -1;
134576404edcSAsim Jamshed             off_macpl = -1;
134676404edcSAsim Jamshed             off_nl = -1;
134776404edcSAsim Jamshed             off_nl_nosnap = -1;
134876404edcSAsim Jamshed             return;
134976404edcSAsim Jamshed 
135076404edcSAsim Jamshed #ifdef DLT_PFSYNC
135176404edcSAsim Jamshed         case DLT_PFSYNC:
135276404edcSAsim Jamshed             off_linktype = -1;
135376404edcSAsim Jamshed             off_macpl = 4;
135476404edcSAsim Jamshed             off_nl = 0;
135576404edcSAsim Jamshed             off_nl_nosnap = 0;
135676404edcSAsim Jamshed             return;
135776404edcSAsim Jamshed #endif
135876404edcSAsim Jamshed 
135976404edcSAsim Jamshed         case DLT_LINUX_LAPD:
136076404edcSAsim Jamshed             /*
136176404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
136276404edcSAsim Jamshed              */
136376404edcSAsim Jamshed             off_linktype = -1;
136476404edcSAsim Jamshed             off_macpl = -1;
136576404edcSAsim Jamshed             off_nl = -1;
136676404edcSAsim Jamshed             off_nl_nosnap = -1;
136776404edcSAsim Jamshed             return;
136876404edcSAsim Jamshed 
136976404edcSAsim Jamshed         case DLT_USB:
137076404edcSAsim Jamshed             /*
137176404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
137276404edcSAsim Jamshed              */
137376404edcSAsim Jamshed             off_linktype = -1;
137476404edcSAsim Jamshed             off_macpl = -1;
137576404edcSAsim Jamshed             off_nl = -1;
137676404edcSAsim Jamshed             off_nl_nosnap = -1;
137776404edcSAsim Jamshed             return;
137876404edcSAsim Jamshed 
137976404edcSAsim Jamshed         case DLT_BLUETOOTH_HCI_H4:
138076404edcSAsim Jamshed             /*
138176404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
138276404edcSAsim Jamshed              */
138376404edcSAsim Jamshed             off_linktype = -1;
138476404edcSAsim Jamshed             off_macpl = -1;
138576404edcSAsim Jamshed             off_nl = -1;
138676404edcSAsim Jamshed             off_nl_nosnap = -1;
138776404edcSAsim Jamshed             return;
138876404edcSAsim Jamshed 
138976404edcSAsim Jamshed         case DLT_USB_LINUX:
139076404edcSAsim Jamshed             /*
139176404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
139276404edcSAsim Jamshed              */
139376404edcSAsim Jamshed             off_linktype = -1;
139476404edcSAsim Jamshed             off_macpl = -1;
139576404edcSAsim Jamshed             off_nl = -1;
139676404edcSAsim Jamshed             off_nl_nosnap = -1;
139776404edcSAsim Jamshed             return;
139876404edcSAsim Jamshed 
139976404edcSAsim Jamshed         case DLT_CAN20B:
140076404edcSAsim Jamshed             /*
140176404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
140276404edcSAsim Jamshed              */
140376404edcSAsim Jamshed             off_linktype = -1;
140476404edcSAsim Jamshed             off_macpl = -1;
140576404edcSAsim Jamshed             off_nl = -1;
140676404edcSAsim Jamshed             off_nl_nosnap = -1;
140776404edcSAsim Jamshed             return;
140876404edcSAsim Jamshed 
140976404edcSAsim Jamshed         case DLT_IEEE802_15_4_LINUX:
141076404edcSAsim Jamshed             /*
141176404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
141276404edcSAsim Jamshed              */
141376404edcSAsim Jamshed             off_linktype = -1;
141476404edcSAsim Jamshed             off_macpl = -1;
141576404edcSAsim Jamshed             off_nl = -1;
141676404edcSAsim Jamshed             off_nl_nosnap = -1;
141776404edcSAsim Jamshed             return;
141876404edcSAsim Jamshed 
141976404edcSAsim Jamshed         case DLT_IEEE802_16_MAC_CPS_RADIO:
142076404edcSAsim Jamshed             /*
142176404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
142276404edcSAsim Jamshed              */
142376404edcSAsim Jamshed             off_linktype = -1;
142476404edcSAsim Jamshed             off_macpl = -1;
142576404edcSAsim Jamshed             off_nl = -1;
142676404edcSAsim Jamshed             off_nl_nosnap = -1;
142776404edcSAsim Jamshed             return;
142876404edcSAsim Jamshed 
142976404edcSAsim Jamshed         case DLT_IEEE802_15_4:
143076404edcSAsim Jamshed             /*
143176404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
143276404edcSAsim Jamshed              */
143376404edcSAsim Jamshed             off_linktype = -1;
143476404edcSAsim Jamshed             off_macpl = -1;
143576404edcSAsim Jamshed             off_nl = -1;
143676404edcSAsim Jamshed             off_nl_nosnap = -1;
143776404edcSAsim Jamshed             return;
143876404edcSAsim Jamshed 
143976404edcSAsim Jamshed         case DLT_SITA:
144076404edcSAsim Jamshed             /*
144176404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
144276404edcSAsim Jamshed              */
144376404edcSAsim Jamshed             off_linktype = -1;
144476404edcSAsim Jamshed             off_macpl = -1;
144576404edcSAsim Jamshed             off_nl = -1;
144676404edcSAsim Jamshed             off_nl_nosnap = -1;
144776404edcSAsim Jamshed             return;
144876404edcSAsim Jamshed 
144976404edcSAsim Jamshed         case DLT_RAIF1:
145076404edcSAsim Jamshed             /*
145176404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
145276404edcSAsim Jamshed              */
145376404edcSAsim Jamshed             off_linktype = -1;
145476404edcSAsim Jamshed             off_macpl = -1;
145576404edcSAsim Jamshed             off_nl = -1;
145676404edcSAsim Jamshed             off_nl_nosnap = -1;
145776404edcSAsim Jamshed             return;
145876404edcSAsim Jamshed 
145976404edcSAsim Jamshed         case DLT_IPMB:
146076404edcSAsim Jamshed             /*
146176404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
146276404edcSAsim Jamshed              */
146376404edcSAsim Jamshed             off_linktype = -1;
146476404edcSAsim Jamshed             off_macpl = -1;
146576404edcSAsim Jamshed             off_nl = -1;
146676404edcSAsim Jamshed             off_nl_nosnap = -1;
146776404edcSAsim Jamshed             return;
146876404edcSAsim Jamshed 
146976404edcSAsim Jamshed         case DLT_BLUETOOTH_HCI_H4_WITH_PHDR:
147076404edcSAsim Jamshed             /*
147176404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
147276404edcSAsim Jamshed              */
147376404edcSAsim Jamshed             off_linktype = -1;
147476404edcSAsim Jamshed             off_macpl = -1;
147576404edcSAsim Jamshed             off_nl = -1;
147676404edcSAsim Jamshed             off_nl_nosnap = -1;
147776404edcSAsim Jamshed             return;
147876404edcSAsim Jamshed 
147976404edcSAsim Jamshed         case DLT_AX25_KISS:
148076404edcSAsim Jamshed             /*
148176404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
148276404edcSAsim Jamshed              */
148376404edcSAsim Jamshed             off_linktype = -1;  /* variable, min 15, max 71 steps of 7 */
148476404edcSAsim Jamshed             off_macpl = -1;
148576404edcSAsim Jamshed             off_nl = -1;        /* variable, min 16, max 71 steps of 7 */
148676404edcSAsim Jamshed             off_nl_nosnap = -1; /* no 802.2 LLC */
148776404edcSAsim Jamshed             off_mac = 1;        /* step over the kiss length byte */
148876404edcSAsim Jamshed             return;
148976404edcSAsim Jamshed 
149076404edcSAsim Jamshed         case DLT_IEEE802_15_4_NONASK_PHY:
149176404edcSAsim Jamshed             /*
149276404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
149376404edcSAsim Jamshed              */
149476404edcSAsim Jamshed             off_linktype = -1;
149576404edcSAsim Jamshed             off_macpl = -1;
149676404edcSAsim Jamshed             off_nl = -1;
149776404edcSAsim Jamshed             off_nl_nosnap = -1;
149876404edcSAsim Jamshed             return;
149976404edcSAsim Jamshed 
150076404edcSAsim Jamshed         case DLT_MPLS:
150176404edcSAsim Jamshed             /*
150276404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
150376404edcSAsim Jamshed              */
150476404edcSAsim Jamshed             off_linktype = -1;
150576404edcSAsim Jamshed             off_macpl = -1;
150676404edcSAsim Jamshed             off_nl = -1;
150776404edcSAsim Jamshed             off_nl_nosnap = -1;
150876404edcSAsim Jamshed             return;
150976404edcSAsim Jamshed 
151076404edcSAsim Jamshed         case DLT_USB_LINUX_MMAPPED:
151176404edcSAsim Jamshed             /*
151276404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
151376404edcSAsim Jamshed              */
151476404edcSAsim Jamshed             off_linktype = -1;
151576404edcSAsim Jamshed             off_macpl = -1;
151676404edcSAsim Jamshed             off_nl = -1;
151776404edcSAsim Jamshed             off_nl_nosnap = -1;
151876404edcSAsim Jamshed             return;
151976404edcSAsim Jamshed 
152076404edcSAsim Jamshed         case DLT_CAN_SOCKETCAN:
152176404edcSAsim Jamshed             /*
152276404edcSAsim Jamshed              * Currently, only raw "link[N:M]" filtering is supported.
152376404edcSAsim Jamshed              */
152476404edcSAsim Jamshed             off_linktype = -1;
152576404edcSAsim Jamshed             off_macpl = -1;
152676404edcSAsim Jamshed             off_nl = -1;
152776404edcSAsim Jamshed             off_nl_nosnap = -1;
152876404edcSAsim Jamshed             return;
152976404edcSAsim Jamshed 
153076404edcSAsim Jamshed         case DLT_IPNET:
153176404edcSAsim Jamshed             off_linktype = 1;
153276404edcSAsim Jamshed             off_macpl = 24;     /* ipnet header length */
153376404edcSAsim Jamshed             off_nl = 0;
153476404edcSAsim Jamshed             off_nl_nosnap = -1;
153576404edcSAsim Jamshed             return;
153676404edcSAsim Jamshed     }
153776404edcSAsim Jamshed     bpf_error("unknown data link type %d", linktype);
153876404edcSAsim Jamshed     /* NOTREACHED */
153976404edcSAsim Jamshed }
154076404edcSAsim Jamshed 
154176404edcSAsim Jamshed /*
154276404edcSAsim Jamshed  * Load a value relative to the beginning of the link-layer header.
154376404edcSAsim Jamshed  * The link-layer header doesn't necessarily begin at the beginning
154476404edcSAsim Jamshed  * of the packet data; there might be a variable-length prefix containing
154576404edcSAsim Jamshed  * radio information.
154676404edcSAsim Jamshed  */
gen_load_llrel(offset,size)154776404edcSAsim Jamshed static struct slist *gen_load_llrel(offset, size)
154876404edcSAsim Jamshed      u_int offset, size;
154976404edcSAsim Jamshed {
155076404edcSAsim Jamshed     struct slist *s, *s2;
155176404edcSAsim Jamshed 
155276404edcSAsim Jamshed     s = gen_llprefixlen();
155376404edcSAsim Jamshed 
155476404edcSAsim Jamshed     /*
155576404edcSAsim Jamshed      * If "s" is non-null, it has code to arrange that the X register
155676404edcSAsim Jamshed      * contains the length of the prefix preceding the link-layer
155776404edcSAsim Jamshed      * header.
155876404edcSAsim Jamshed      *
155976404edcSAsim Jamshed      * Otherwise, the length of the prefix preceding the link-layer
156076404edcSAsim Jamshed      * header is "off_ll".
156176404edcSAsim Jamshed      */
156276404edcSAsim Jamshed     if (s != NULL)
156376404edcSAsim Jamshed     {
156476404edcSAsim Jamshed         /*
156576404edcSAsim Jamshed          * There's a variable-length prefix preceding the
156676404edcSAsim Jamshed          * link-layer header.  "s" points to a list of statements
156776404edcSAsim Jamshed          * that put the length of that prefix into the X register.
156876404edcSAsim Jamshed          * do an indirect load, to use the X register as an offset.
156976404edcSAsim Jamshed          */
157076404edcSAsim Jamshed         s2 = new_stmt(BPF_LD | BPF_IND | size);
157176404edcSAsim Jamshed         s2->s.k = offset;
157276404edcSAsim Jamshed         sappend(s, s2);
157376404edcSAsim Jamshed     }
157476404edcSAsim Jamshed     else
157576404edcSAsim Jamshed     {
157676404edcSAsim Jamshed         /*
157776404edcSAsim Jamshed          * There is no variable-length header preceding the
157876404edcSAsim Jamshed          * link-layer header; add in off_ll, which, if there's
157976404edcSAsim Jamshed          * a fixed-length header preceding the link-layer header,
158076404edcSAsim Jamshed          * is the length of that header.
158176404edcSAsim Jamshed          */
158276404edcSAsim Jamshed         s = new_stmt(BPF_LD | BPF_ABS | size);
158376404edcSAsim Jamshed         s->s.k = offset + off_ll;
158476404edcSAsim Jamshed     }
158576404edcSAsim Jamshed     return s;
158676404edcSAsim Jamshed }
158776404edcSAsim Jamshed 
158876404edcSAsim Jamshed /*
158976404edcSAsim Jamshed  * Load a value relative to the beginning of the MAC-layer payload.
159076404edcSAsim Jamshed  */
gen_load_macplrel(offset,size)159176404edcSAsim Jamshed static struct slist *gen_load_macplrel(offset, size)
159276404edcSAsim Jamshed      u_int offset, size;
159376404edcSAsim Jamshed {
159476404edcSAsim Jamshed     struct slist *s, *s2;
159576404edcSAsim Jamshed 
159676404edcSAsim Jamshed     s = gen_off_macpl();
159776404edcSAsim Jamshed 
159876404edcSAsim Jamshed     /*
159976404edcSAsim Jamshed      * If s is non-null, the offset of the MAC-layer payload is
160076404edcSAsim Jamshed      * variable, and s points to a list of instructions that
160176404edcSAsim Jamshed      * arrange that the X register contains that offset.
160276404edcSAsim Jamshed      *
160376404edcSAsim Jamshed      * Otherwise, the offset of the MAC-layer payload is constant,
160476404edcSAsim Jamshed      * and is in off_macpl.
160576404edcSAsim Jamshed      */
160676404edcSAsim Jamshed     if (s != NULL)
160776404edcSAsim Jamshed     {
160876404edcSAsim Jamshed         /*
160976404edcSAsim Jamshed          * The offset of the MAC-layer payload is in the X
161076404edcSAsim Jamshed          * register.  Do an indirect load, to use the X register
161176404edcSAsim Jamshed          * as an offset.
161276404edcSAsim Jamshed          */
161376404edcSAsim Jamshed         s2 = new_stmt(BPF_LD | BPF_IND | size);
161476404edcSAsim Jamshed         s2->s.k = offset;
161576404edcSAsim Jamshed         sappend(s, s2);
161676404edcSAsim Jamshed     }
161776404edcSAsim Jamshed     else
161876404edcSAsim Jamshed     {
161976404edcSAsim Jamshed         /*
162076404edcSAsim Jamshed          * The offset of the MAC-layer payload is constant,
162176404edcSAsim Jamshed          * and is in off_macpl; load the value at that offset
162276404edcSAsim Jamshed          * plus the specified offset.
162376404edcSAsim Jamshed          */
162476404edcSAsim Jamshed         s = new_stmt(BPF_LD | BPF_ABS | size);
162576404edcSAsim Jamshed         s->s.k = off_macpl + offset;
162676404edcSAsim Jamshed     }
162776404edcSAsim Jamshed     return s;
162876404edcSAsim Jamshed }
162976404edcSAsim Jamshed 
163076404edcSAsim Jamshed /*
163176404edcSAsim Jamshed  * Load a value relative to the beginning of the specified header.
163276404edcSAsim Jamshed  */
gen_load_a(offrel,offset,size)163376404edcSAsim Jamshed static struct slist *gen_load_a(offrel, offset, size)
163476404edcSAsim Jamshed      enum e_offrel offrel;
163576404edcSAsim Jamshed      u_int offset, size;
163676404edcSAsim Jamshed {
163776404edcSAsim Jamshed     struct slist *s, *s2;
163876404edcSAsim Jamshed 
163976404edcSAsim Jamshed     switch (offrel)
164076404edcSAsim Jamshed     {
164176404edcSAsim Jamshed 
164276404edcSAsim Jamshed         case OR_PACKET:
164376404edcSAsim Jamshed             s = new_stmt(BPF_LD | BPF_ABS | size);
164476404edcSAsim Jamshed             s->s.k = offset;
164576404edcSAsim Jamshed             break;
164676404edcSAsim Jamshed 
164776404edcSAsim Jamshed         case OR_LINK:
164876404edcSAsim Jamshed             s = gen_load_llrel(offset, size);
164976404edcSAsim Jamshed             break;
165076404edcSAsim Jamshed 
165176404edcSAsim Jamshed         case OR_MACPL:
165276404edcSAsim Jamshed             s = gen_load_macplrel(offset, size);
165376404edcSAsim Jamshed             break;
165476404edcSAsim Jamshed 
165576404edcSAsim Jamshed         case OR_NET:
165676404edcSAsim Jamshed             s = gen_load_macplrel(off_nl + offset, size);
165776404edcSAsim Jamshed             break;
165876404edcSAsim Jamshed 
165976404edcSAsim Jamshed         case OR_NET_NOSNAP:
166076404edcSAsim Jamshed             s = gen_load_macplrel(off_nl_nosnap + offset, size);
166176404edcSAsim Jamshed             break;
166276404edcSAsim Jamshed 
166376404edcSAsim Jamshed         case OR_TRAN_IPV4:
166476404edcSAsim Jamshed             /*
166576404edcSAsim Jamshed              * Load the X register with the length of the IPv4 header
166676404edcSAsim Jamshed              * (plus the offset of the link-layer header, if it's
166776404edcSAsim Jamshed              * preceded by a variable-length header such as a radio
166876404edcSAsim Jamshed              * header), in bytes.
166976404edcSAsim Jamshed              */
167076404edcSAsim Jamshed             s = gen_loadx_iphdrlen();
167176404edcSAsim Jamshed 
167276404edcSAsim Jamshed             /*
167376404edcSAsim Jamshed              * Load the item at {offset of the MAC-layer payload} +
167476404edcSAsim Jamshed              * {offset, relative to the start of the MAC-layer
167576404edcSAsim Jamshed              * paylod, of the IPv4 header} + {length of the IPv4 header} +
167676404edcSAsim Jamshed              * {specified offset}.
167776404edcSAsim Jamshed              *
167876404edcSAsim Jamshed              * (If the offset of the MAC-layer payload is variable,
167976404edcSAsim Jamshed              * it's included in the value in the X register, and
168076404edcSAsim Jamshed              * off_macpl is 0.)
168176404edcSAsim Jamshed              */
168276404edcSAsim Jamshed             s2 = new_stmt(BPF_LD | BPF_IND | size);
168376404edcSAsim Jamshed             s2->s.k = off_macpl + off_nl + offset;
168476404edcSAsim Jamshed             sappend(s, s2);
168576404edcSAsim Jamshed             break;
168676404edcSAsim Jamshed 
168776404edcSAsim Jamshed         case OR_TRAN_IPV6:
168876404edcSAsim Jamshed             s = gen_load_macplrel(off_nl + 40 + offset, size);
168976404edcSAsim Jamshed             break;
169076404edcSAsim Jamshed 
169176404edcSAsim Jamshed         default:
169276404edcSAsim Jamshed             abort();
169376404edcSAsim Jamshed             return NULL;
169476404edcSAsim Jamshed     }
169576404edcSAsim Jamshed     return s;
169676404edcSAsim Jamshed }
169776404edcSAsim Jamshed 
169876404edcSAsim Jamshed /*
169976404edcSAsim Jamshed  * Generate code to load into the X register the sum of the length of
170076404edcSAsim Jamshed  * the IPv4 header and any variable-length header preceding the link-layer
170176404edcSAsim Jamshed  * header.
170276404edcSAsim Jamshed  */
gen_loadx_iphdrlen()170376404edcSAsim Jamshed static struct slist *gen_loadx_iphdrlen()
170476404edcSAsim Jamshed {
170576404edcSAsim Jamshed     struct slist *s, *s2;
170676404edcSAsim Jamshed 
170776404edcSAsim Jamshed     s = gen_off_macpl();
170876404edcSAsim Jamshed     if (s != NULL)
170976404edcSAsim Jamshed     {
171076404edcSAsim Jamshed         /*
171176404edcSAsim Jamshed          * There's a variable-length prefix preceding the
171276404edcSAsim Jamshed          * link-layer header, or the link-layer header is itself
171376404edcSAsim Jamshed          * variable-length.  "s" points to a list of statements
171476404edcSAsim Jamshed          * that put the offset of the MAC-layer payload into
171576404edcSAsim Jamshed          * the X register.
171676404edcSAsim Jamshed          *
171776404edcSAsim Jamshed          * The 4*([k]&0xf) addressing mode can't be used, as we
171876404edcSAsim Jamshed          * don't have a constant offset, so we have to load the
171976404edcSAsim Jamshed          * value in question into the A register and add to it
172076404edcSAsim Jamshed          * the value from the X register.
172176404edcSAsim Jamshed          */
172276404edcSAsim Jamshed         s2 = new_stmt(BPF_LD | BPF_IND | BPF_B);
172376404edcSAsim Jamshed         s2->s.k = off_nl;
172476404edcSAsim Jamshed         sappend(s, s2);
172576404edcSAsim Jamshed         s2 = new_stmt(BPF_ALU | BPF_AND | BPF_K);
172676404edcSAsim Jamshed         s2->s.k = 0xf;
172776404edcSAsim Jamshed         sappend(s, s2);
172876404edcSAsim Jamshed         s2 = new_stmt(BPF_ALU | BPF_LSH | BPF_K);
172976404edcSAsim Jamshed         s2->s.k = 2;
173076404edcSAsim Jamshed         sappend(s, s2);
173176404edcSAsim Jamshed 
173276404edcSAsim Jamshed         /*
173376404edcSAsim Jamshed          * The A register now contains the length of the
173476404edcSAsim Jamshed          * IP header.  We need to add to it the offset of
173576404edcSAsim Jamshed          * the MAC-layer payload, which is still in the X
173676404edcSAsim Jamshed          * register, and move the result into the X register.
173776404edcSAsim Jamshed          */
173876404edcSAsim Jamshed         sappend(s, new_stmt(BPF_ALU | BPF_ADD | BPF_X));
173976404edcSAsim Jamshed         sappend(s, new_stmt(BPF_MISC | BPF_TAX));
174076404edcSAsim Jamshed     }
174176404edcSAsim Jamshed     else
174276404edcSAsim Jamshed     {
174376404edcSAsim Jamshed         /*
174476404edcSAsim Jamshed          * There is no variable-length header preceding the
174576404edcSAsim Jamshed          * link-layer header, and the link-layer header is
174676404edcSAsim Jamshed          * fixed-length; load the length of the IPv4 header,
174776404edcSAsim Jamshed          * which is at an offset of off_nl from the beginning
174876404edcSAsim Jamshed          * of the MAC-layer payload, and thus at an offset
174976404edcSAsim Jamshed          * of off_mac_pl + off_nl from the beginning of the
175076404edcSAsim Jamshed          * raw packet data.
175176404edcSAsim Jamshed          */
175276404edcSAsim Jamshed         s = new_stmt(BPF_LDX | BPF_MSH | BPF_B);
175376404edcSAsim Jamshed         s->s.k = off_macpl + off_nl;
175476404edcSAsim Jamshed     }
175576404edcSAsim Jamshed     return s;
175676404edcSAsim Jamshed }
175776404edcSAsim Jamshed 
gen_uncond(rsense)175876404edcSAsim Jamshed static struct block *gen_uncond(rsense)
175976404edcSAsim Jamshed      int rsense;
176076404edcSAsim Jamshed {
176176404edcSAsim Jamshed     struct block *b;
176276404edcSAsim Jamshed     struct slist *s;
176376404edcSAsim Jamshed 
176476404edcSAsim Jamshed     s = new_stmt(BPF_LD | BPF_IMM);
176576404edcSAsim Jamshed     s->s.k = !rsense;
176676404edcSAsim Jamshed     b = new_block(JMP(BPF_JEQ));
176776404edcSAsim Jamshed     b->stmts = s;
176876404edcSAsim Jamshed 
176976404edcSAsim Jamshed     return b;
177076404edcSAsim Jamshed }
177176404edcSAsim Jamshed 
gen_true()177276404edcSAsim Jamshed static inline struct block *gen_true()
177376404edcSAsim Jamshed {
177476404edcSAsim Jamshed     return gen_uncond(1);
177576404edcSAsim Jamshed }
177676404edcSAsim Jamshed 
gen_false()177776404edcSAsim Jamshed static inline struct block *gen_false()
177876404edcSAsim Jamshed {
177976404edcSAsim Jamshed     return gen_uncond(0);
178076404edcSAsim Jamshed }
178176404edcSAsim Jamshed 
178276404edcSAsim Jamshed /*
178376404edcSAsim Jamshed  * Byte-swap a 32-bit number.
178476404edcSAsim Jamshed  * ("htonl()" or "ntohl()" won't work - we want to byte-swap even on
178576404edcSAsim Jamshed  * big-endian platforms.)
178676404edcSAsim Jamshed  */
178776404edcSAsim Jamshed #define	SWAPLONG(y) \
178876404edcSAsim Jamshed ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
178976404edcSAsim Jamshed 
179076404edcSAsim Jamshed /*
179176404edcSAsim Jamshed  * Generate code to match a particular packet type.
179276404edcSAsim Jamshed  *
179376404edcSAsim Jamshed  * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
179476404edcSAsim Jamshed  * value, if <= ETHERMTU.  We use that to determine whether to
179576404edcSAsim Jamshed  * match the type/length field or to check the type/length field for
179676404edcSAsim Jamshed  * a value <= ETHERMTU to see whether it's a type field and then do
179776404edcSAsim Jamshed  * the appropriate test.
179876404edcSAsim Jamshed  */
gen_ether_linktype(proto)179976404edcSAsim Jamshed static struct block *gen_ether_linktype(proto)
180076404edcSAsim Jamshed      register int proto;
180176404edcSAsim Jamshed {
180276404edcSAsim Jamshed     struct block *b0, *b1;
180376404edcSAsim Jamshed 
180476404edcSAsim Jamshed     switch (proto)
180576404edcSAsim Jamshed     {
180676404edcSAsim Jamshed 
180776404edcSAsim Jamshed         case LLCSAP_ISONS:
180876404edcSAsim Jamshed         case LLCSAP_IP:
180976404edcSAsim Jamshed         case LLCSAP_NETBEUI:
181076404edcSAsim Jamshed             /*
181176404edcSAsim Jamshed              * OSI protocols and NetBEUI always use 802.2 encapsulation,
181276404edcSAsim Jamshed              * so we check the DSAP and SSAP.
181376404edcSAsim Jamshed              *
181476404edcSAsim Jamshed              * LLCSAP_IP checks for IP-over-802.2, rather
181576404edcSAsim Jamshed              * than IP-over-Ethernet or IP-over-SNAP.
181676404edcSAsim Jamshed              *
181776404edcSAsim Jamshed              * XXX - should we check both the DSAP and the
181876404edcSAsim Jamshed              * SSAP, like this, or should we check just the
181976404edcSAsim Jamshed              * DSAP, as we do for other types <= ETHERMTU
182076404edcSAsim Jamshed              * (i.e., other SAP values)?
182176404edcSAsim Jamshed              */
182276404edcSAsim Jamshed             b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
182376404edcSAsim Jamshed             gen_not(b0);
182476404edcSAsim Jamshed             b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32) ((proto << 8) | proto));
182576404edcSAsim Jamshed             gen_and(b0, b1);
182676404edcSAsim Jamshed             return b1;
182776404edcSAsim Jamshed 
182876404edcSAsim Jamshed         case LLCSAP_IPX:
182976404edcSAsim Jamshed             /*
183076404edcSAsim Jamshed              * Check for;
183176404edcSAsim Jamshed              *
183276404edcSAsim Jamshed              *  Ethernet_II frames, which are Ethernet
183376404edcSAsim Jamshed              *  frames with a frame type of ETHERTYPE_IPX;
183476404edcSAsim Jamshed              *
183576404edcSAsim Jamshed              *  Ethernet_802.3 frames, which are 802.3
183676404edcSAsim Jamshed              *  frames (i.e., the type/length field is
183776404edcSAsim Jamshed              *  a length field, <= ETHERMTU, rather than
183876404edcSAsim Jamshed              *  a type field) with the first two bytes
183976404edcSAsim Jamshed              *  after the Ethernet/802.3 header being
184076404edcSAsim Jamshed              *  0xFFFF;
184176404edcSAsim Jamshed              *
184276404edcSAsim Jamshed              *  Ethernet_802.2 frames, which are 802.3
184376404edcSAsim Jamshed              *  frames with an 802.2 LLC header and
184476404edcSAsim Jamshed              *  with the IPX LSAP as the DSAP in the LLC
184576404edcSAsim Jamshed              *  header;
184676404edcSAsim Jamshed              *
184776404edcSAsim Jamshed              *  Ethernet_SNAP frames, which are 802.3
184876404edcSAsim Jamshed              *  frames with an LLC header and a SNAP
184976404edcSAsim Jamshed              *  header and with an OUI of 0x000000
185076404edcSAsim Jamshed              *  (encapsulated Ethernet) and a protocol
185176404edcSAsim Jamshed              *  ID of ETHERTYPE_IPX in the SNAP header.
185276404edcSAsim Jamshed              *
185376404edcSAsim Jamshed              * XXX - should we generate the same code both
185476404edcSAsim Jamshed              * for tests for LLCSAP_IPX and for ETHERTYPE_IPX?
185576404edcSAsim Jamshed              */
185676404edcSAsim Jamshed 
185776404edcSAsim Jamshed             /*
185876404edcSAsim Jamshed              * This generates code to check both for the
185976404edcSAsim Jamshed              * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3.
186076404edcSAsim Jamshed              */
186176404edcSAsim Jamshed             b0 = gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32) LLCSAP_IPX);
186276404edcSAsim Jamshed             b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32) 0xFFFF);
186376404edcSAsim Jamshed             gen_or(b0, b1);
186476404edcSAsim Jamshed 
186576404edcSAsim Jamshed             /*
186676404edcSAsim Jamshed              * Now we add code to check for SNAP frames with
186776404edcSAsim Jamshed              * ETHERTYPE_IPX, i.e. Ethernet_SNAP.
186876404edcSAsim Jamshed              */
186976404edcSAsim Jamshed             b0 = gen_snap(0x000000, ETHERTYPE_IPX);
187076404edcSAsim Jamshed             gen_or(b0, b1);
187176404edcSAsim Jamshed 
187276404edcSAsim Jamshed             /*
187376404edcSAsim Jamshed              * Now we generate code to check for 802.3
187476404edcSAsim Jamshed              * frames in general.
187576404edcSAsim Jamshed              */
187676404edcSAsim Jamshed             b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
187776404edcSAsim Jamshed             gen_not(b0);
187876404edcSAsim Jamshed 
187976404edcSAsim Jamshed             /*
188076404edcSAsim Jamshed              * Now add the check for 802.3 frames before the
188176404edcSAsim Jamshed              * check for Ethernet_802.2 and Ethernet_802.3,
188276404edcSAsim Jamshed              * as those checks should only be done on 802.3
188376404edcSAsim Jamshed              * frames, not on Ethernet frames.
188476404edcSAsim Jamshed              */
188576404edcSAsim Jamshed             gen_and(b0, b1);
188676404edcSAsim Jamshed 
188776404edcSAsim Jamshed             /*
188876404edcSAsim Jamshed              * Now add the check for Ethernet_II frames, and
188976404edcSAsim Jamshed              * do that before checking for the other frame
189076404edcSAsim Jamshed              * types.
189176404edcSAsim Jamshed              */
189276404edcSAsim Jamshed             b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32) ETHERTYPE_IPX);
189376404edcSAsim Jamshed             gen_or(b0, b1);
189476404edcSAsim Jamshed             return b1;
189576404edcSAsim Jamshed 
189676404edcSAsim Jamshed         case ETHERTYPE_ATALK:
189776404edcSAsim Jamshed         case ETHERTYPE_AARP:
189876404edcSAsim Jamshed             /*
189976404edcSAsim Jamshed              * EtherTalk (AppleTalk protocols on Ethernet link
190076404edcSAsim Jamshed              * layer) may use 802.2 encapsulation.
190176404edcSAsim Jamshed              */
190276404edcSAsim Jamshed 
190376404edcSAsim Jamshed             /*
190476404edcSAsim Jamshed              * Check for 802.2 encapsulation (EtherTalk phase 2?);
190576404edcSAsim Jamshed              * we check for an Ethernet type field less than
190676404edcSAsim Jamshed              * 1500, which means it's an 802.3 length field.
190776404edcSAsim Jamshed              */
190876404edcSAsim Jamshed             b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
190976404edcSAsim Jamshed             gen_not(b0);
191076404edcSAsim Jamshed 
191176404edcSAsim Jamshed             /*
191276404edcSAsim Jamshed              * 802.2-encapsulated ETHERTYPE_ATALK packets are
191376404edcSAsim Jamshed              * SNAP packets with an organization code of
191476404edcSAsim Jamshed              * 0x080007 (Apple, for Appletalk) and a protocol
191576404edcSAsim Jamshed              * type of ETHERTYPE_ATALK (Appletalk).
191676404edcSAsim Jamshed              *
191776404edcSAsim Jamshed              * 802.2-encapsulated ETHERTYPE_AARP packets are
191876404edcSAsim Jamshed              * SNAP packets with an organization code of
191976404edcSAsim Jamshed              * 0x000000 (encapsulated Ethernet) and a protocol
192076404edcSAsim Jamshed              * type of ETHERTYPE_AARP (Appletalk ARP).
192176404edcSAsim Jamshed              */
192276404edcSAsim Jamshed             if (proto == ETHERTYPE_ATALK)
192376404edcSAsim Jamshed                 b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
192476404edcSAsim Jamshed             else                /* proto == ETHERTYPE_AARP */
192576404edcSAsim Jamshed                 b1 = gen_snap(0x000000, ETHERTYPE_AARP);
192676404edcSAsim Jamshed             gen_and(b0, b1);
192776404edcSAsim Jamshed 
192876404edcSAsim Jamshed             /*
192976404edcSAsim Jamshed              * Check for Ethernet encapsulation (Ethertalk
193076404edcSAsim Jamshed              * phase 1?); we just check for the Ethernet
193176404edcSAsim Jamshed              * protocol type.
193276404edcSAsim Jamshed              */
193376404edcSAsim Jamshed             b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32) proto);
193476404edcSAsim Jamshed 
193576404edcSAsim Jamshed             gen_or(b0, b1);
193676404edcSAsim Jamshed             return b1;
193776404edcSAsim Jamshed 
193876404edcSAsim Jamshed         default:
193976404edcSAsim Jamshed             if (proto <= ETHERMTU)
194076404edcSAsim Jamshed             {
194176404edcSAsim Jamshed                 /*
194276404edcSAsim Jamshed                  * This is an LLC SAP value, so the frames
194376404edcSAsim Jamshed                  * that match would be 802.2 frames.
194476404edcSAsim Jamshed                  * Check that the frame is an 802.2 frame
194576404edcSAsim Jamshed                  * (i.e., that the length/type field is
194676404edcSAsim Jamshed                  * a length field, <= ETHERMTU) and
194776404edcSAsim Jamshed                  * then check the DSAP.
194876404edcSAsim Jamshed                  */
194976404edcSAsim Jamshed                 b0 = gen_cmp_gt(OR_LINK, off_linktype, BPF_H, ETHERMTU);
195076404edcSAsim Jamshed                 gen_not(b0);
195176404edcSAsim Jamshed                 b1 = gen_cmp(OR_LINK, off_linktype + 2, BPF_B, (bpf_int32) proto);
195276404edcSAsim Jamshed                 gen_and(b0, b1);
195376404edcSAsim Jamshed                 return b1;
195476404edcSAsim Jamshed             }
195576404edcSAsim Jamshed             else
195676404edcSAsim Jamshed             {
195776404edcSAsim Jamshed                 /*
195876404edcSAsim Jamshed                  * This is an Ethernet type, so compare
195976404edcSAsim Jamshed                  * the length/type field with it (if
196076404edcSAsim Jamshed                  * the frame is an 802.2 frame, the length
196176404edcSAsim Jamshed                  * field will be <= ETHERMTU, and, as
196276404edcSAsim Jamshed                  * "proto" is > ETHERMTU, this test
196376404edcSAsim Jamshed                  * will fail and the frame won't match,
196476404edcSAsim Jamshed                  * which is what we want).
196576404edcSAsim Jamshed                  */
196676404edcSAsim Jamshed                 return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32) proto);
196776404edcSAsim Jamshed             }
196876404edcSAsim Jamshed     }
196976404edcSAsim Jamshed }
197076404edcSAsim Jamshed 
197176404edcSAsim Jamshed /*
197276404edcSAsim Jamshed  * "proto" is an Ethernet type value and for IPNET, if it is not IPv4
197376404edcSAsim Jamshed  * or IPv6 then we have an error.
197476404edcSAsim Jamshed  */
gen_ipnet_linktype(proto)197576404edcSAsim Jamshed static struct block *gen_ipnet_linktype(proto)
197676404edcSAsim Jamshed      register int proto;
197776404edcSAsim Jamshed {
197876404edcSAsim Jamshed     switch (proto)
197976404edcSAsim Jamshed     {
198076404edcSAsim Jamshed 
198176404edcSAsim Jamshed         case ETHERTYPE_IP:
198276404edcSAsim Jamshed             return gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32) IPH_AF_INET);
198376404edcSAsim Jamshed             /* NOTREACHED */
198476404edcSAsim Jamshed 
198576404edcSAsim Jamshed         case ETHERTYPE_IPV6:
198676404edcSAsim Jamshed             return gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32) IPH_AF_INET6);
198776404edcSAsim Jamshed             /* NOTREACHED */
198876404edcSAsim Jamshed 
198976404edcSAsim Jamshed         default:
199076404edcSAsim Jamshed             break;
199176404edcSAsim Jamshed     }
199276404edcSAsim Jamshed 
199376404edcSAsim Jamshed     return gen_false();
199476404edcSAsim Jamshed }
199576404edcSAsim Jamshed 
199676404edcSAsim Jamshed /*
199776404edcSAsim Jamshed  * Generate code to match a particular packet type.
199876404edcSAsim Jamshed  *
199976404edcSAsim Jamshed  * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
200076404edcSAsim Jamshed  * value, if <= ETHERMTU.  We use that to determine whether to
200176404edcSAsim Jamshed  * match the type field or to check the type field for the special
200276404edcSAsim Jamshed  * LINUX_SLL_P_802_2 value and then do the appropriate test.
200376404edcSAsim Jamshed  */
gen_linux_sll_linktype(proto)200476404edcSAsim Jamshed static struct block *gen_linux_sll_linktype(proto)
200576404edcSAsim Jamshed      register int proto;
200676404edcSAsim Jamshed {
200776404edcSAsim Jamshed     struct block *b0, *b1;
200876404edcSAsim Jamshed 
200976404edcSAsim Jamshed     switch (proto)
201076404edcSAsim Jamshed     {
201176404edcSAsim Jamshed 
201276404edcSAsim Jamshed         case LLCSAP_ISONS:
201376404edcSAsim Jamshed         case LLCSAP_IP:
201476404edcSAsim Jamshed         case LLCSAP_NETBEUI:
201576404edcSAsim Jamshed             /*
201676404edcSAsim Jamshed              * OSI protocols and NetBEUI always use 802.2 encapsulation,
201776404edcSAsim Jamshed              * so we check the DSAP and SSAP.
201876404edcSAsim Jamshed              *
201976404edcSAsim Jamshed              * LLCSAP_IP checks for IP-over-802.2, rather
202076404edcSAsim Jamshed              * than IP-over-Ethernet or IP-over-SNAP.
202176404edcSAsim Jamshed              *
202276404edcSAsim Jamshed              * XXX - should we check both the DSAP and the
202376404edcSAsim Jamshed              * SSAP, like this, or should we check just the
202476404edcSAsim Jamshed              * DSAP, as we do for other types <= ETHERMTU
202576404edcSAsim Jamshed              * (i.e., other SAP values)?
202676404edcSAsim Jamshed              */
202776404edcSAsim Jamshed             b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
202876404edcSAsim Jamshed             b1 = gen_cmp(OR_MACPL, 0, BPF_H, (bpf_int32) ((proto << 8) | proto));
202976404edcSAsim Jamshed             gen_and(b0, b1);
203076404edcSAsim Jamshed             return b1;
203176404edcSAsim Jamshed 
203276404edcSAsim Jamshed         case LLCSAP_IPX:
203376404edcSAsim Jamshed             /*
203476404edcSAsim Jamshed              *  Ethernet_II frames, which are Ethernet
203576404edcSAsim Jamshed              *  frames with a frame type of ETHERTYPE_IPX;
203676404edcSAsim Jamshed              *
203776404edcSAsim Jamshed              *  Ethernet_802.3 frames, which have a frame
203876404edcSAsim Jamshed              *  type of LINUX_SLL_P_802_3;
203976404edcSAsim Jamshed              *
204076404edcSAsim Jamshed              *  Ethernet_802.2 frames, which are 802.3
204176404edcSAsim Jamshed              *  frames with an 802.2 LLC header (i.e, have
204276404edcSAsim Jamshed              *  a frame type of LINUX_SLL_P_802_2) and
204376404edcSAsim Jamshed              *  with the IPX LSAP as the DSAP in the LLC
204476404edcSAsim Jamshed              *  header;
204576404edcSAsim Jamshed              *
204676404edcSAsim Jamshed              *  Ethernet_SNAP frames, which are 802.3
204776404edcSAsim Jamshed              *  frames with an LLC header and a SNAP
204876404edcSAsim Jamshed              *  header and with an OUI of 0x000000
204976404edcSAsim Jamshed              *  (encapsulated Ethernet) and a protocol
205076404edcSAsim Jamshed              *  ID of ETHERTYPE_IPX in the SNAP header.
205176404edcSAsim Jamshed              *
205276404edcSAsim Jamshed              * First, do the checks on LINUX_SLL_P_802_2
205376404edcSAsim Jamshed              * frames; generate the check for either
205476404edcSAsim Jamshed              * Ethernet_802.2 or Ethernet_SNAP frames, and
205576404edcSAsim Jamshed              * then put a check for LINUX_SLL_P_802_2 frames
205676404edcSAsim Jamshed              * before it.
205776404edcSAsim Jamshed              */
205876404edcSAsim Jamshed             b0 = gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32) LLCSAP_IPX);
205976404edcSAsim Jamshed             b1 = gen_snap(0x000000, ETHERTYPE_IPX);
206076404edcSAsim Jamshed             gen_or(b0, b1);
206176404edcSAsim Jamshed             b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
206276404edcSAsim Jamshed             gen_and(b0, b1);
206376404edcSAsim Jamshed 
206476404edcSAsim Jamshed             /*
206576404edcSAsim Jamshed              * Now check for 802.3 frames and OR that with
206676404edcSAsim Jamshed              * the previous test.
206776404edcSAsim Jamshed              */
206876404edcSAsim Jamshed             b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_3);
206976404edcSAsim Jamshed             gen_or(b0, b1);
207076404edcSAsim Jamshed 
207176404edcSAsim Jamshed             /*
207276404edcSAsim Jamshed              * Now add the check for Ethernet_II frames, and
207376404edcSAsim Jamshed              * do that before checking for the other frame
207476404edcSAsim Jamshed              * types.
207576404edcSAsim Jamshed              */
207676404edcSAsim Jamshed             b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32) ETHERTYPE_IPX);
207776404edcSAsim Jamshed             gen_or(b0, b1);
207876404edcSAsim Jamshed             return b1;
207976404edcSAsim Jamshed 
208076404edcSAsim Jamshed         case ETHERTYPE_ATALK:
208176404edcSAsim Jamshed         case ETHERTYPE_AARP:
208276404edcSAsim Jamshed             /*
208376404edcSAsim Jamshed              * EtherTalk (AppleTalk protocols on Ethernet link
208476404edcSAsim Jamshed              * layer) may use 802.2 encapsulation.
208576404edcSAsim Jamshed              */
208676404edcSAsim Jamshed 
208776404edcSAsim Jamshed             /*
208876404edcSAsim Jamshed              * Check for 802.2 encapsulation (EtherTalk phase 2?);
208976404edcSAsim Jamshed              * we check for the 802.2 protocol type in the
209076404edcSAsim Jamshed              * "Ethernet type" field.
209176404edcSAsim Jamshed              */
209276404edcSAsim Jamshed             b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
209376404edcSAsim Jamshed 
209476404edcSAsim Jamshed             /*
209576404edcSAsim Jamshed              * 802.2-encapsulated ETHERTYPE_ATALK packets are
209676404edcSAsim Jamshed              * SNAP packets with an organization code of
209776404edcSAsim Jamshed              * 0x080007 (Apple, for Appletalk) and a protocol
209876404edcSAsim Jamshed              * type of ETHERTYPE_ATALK (Appletalk).
209976404edcSAsim Jamshed              *
210076404edcSAsim Jamshed              * 802.2-encapsulated ETHERTYPE_AARP packets are
210176404edcSAsim Jamshed              * SNAP packets with an organization code of
210276404edcSAsim Jamshed              * 0x000000 (encapsulated Ethernet) and a protocol
210376404edcSAsim Jamshed              * type of ETHERTYPE_AARP (Appletalk ARP).
210476404edcSAsim Jamshed              */
210576404edcSAsim Jamshed             if (proto == ETHERTYPE_ATALK)
210676404edcSAsim Jamshed                 b1 = gen_snap(0x080007, ETHERTYPE_ATALK);
210776404edcSAsim Jamshed             else                /* proto == ETHERTYPE_AARP */
210876404edcSAsim Jamshed                 b1 = gen_snap(0x000000, ETHERTYPE_AARP);
210976404edcSAsim Jamshed             gen_and(b0, b1);
211076404edcSAsim Jamshed 
211176404edcSAsim Jamshed             /*
211276404edcSAsim Jamshed              * Check for Ethernet encapsulation (Ethertalk
211376404edcSAsim Jamshed              * phase 1?); we just check for the Ethernet
211476404edcSAsim Jamshed              * protocol type.
211576404edcSAsim Jamshed              */
211676404edcSAsim Jamshed             b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32) proto);
211776404edcSAsim Jamshed 
211876404edcSAsim Jamshed             gen_or(b0, b1);
211976404edcSAsim Jamshed             return b1;
212076404edcSAsim Jamshed 
212176404edcSAsim Jamshed         default:
212276404edcSAsim Jamshed             if (proto <= ETHERMTU)
212376404edcSAsim Jamshed             {
212476404edcSAsim Jamshed                 /*
212576404edcSAsim Jamshed                  * This is an LLC SAP value, so the frames
212676404edcSAsim Jamshed                  * that match would be 802.2 frames.
212776404edcSAsim Jamshed                  * Check for the 802.2 protocol type
212876404edcSAsim Jamshed                  * in the "Ethernet type" field, and
212976404edcSAsim Jamshed                  * then check the DSAP.
213076404edcSAsim Jamshed                  */
213176404edcSAsim Jamshed                 b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, LINUX_SLL_P_802_2);
213276404edcSAsim Jamshed                 b1 = gen_cmp(OR_LINK, off_macpl, BPF_B, (bpf_int32) proto);
213376404edcSAsim Jamshed                 gen_and(b0, b1);
213476404edcSAsim Jamshed                 return b1;
213576404edcSAsim Jamshed             }
213676404edcSAsim Jamshed             else
213776404edcSAsim Jamshed             {
213876404edcSAsim Jamshed                 /*
213976404edcSAsim Jamshed                  * This is an Ethernet type, so compare
214076404edcSAsim Jamshed                  * the length/type field with it (if
214176404edcSAsim Jamshed                  * the frame is an 802.2 frame, the length
214276404edcSAsim Jamshed                  * field will be <= ETHERMTU, and, as
214376404edcSAsim Jamshed                  * "proto" is > ETHERMTU, this test
214476404edcSAsim Jamshed                  * will fail and the frame won't match,
214576404edcSAsim Jamshed                  * which is what we want).
214676404edcSAsim Jamshed                  */
214776404edcSAsim Jamshed                 return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32) proto);
214876404edcSAsim Jamshed             }
214976404edcSAsim Jamshed     }
215076404edcSAsim Jamshed }
215176404edcSAsim Jamshed 
gen_load_prism_llprefixlen()215276404edcSAsim Jamshed static struct slist *gen_load_prism_llprefixlen()
215376404edcSAsim Jamshed {
215476404edcSAsim Jamshed     struct slist *s1, *s2;
215576404edcSAsim Jamshed     struct slist *sjeq_avs_cookie;
215676404edcSAsim Jamshed     struct slist *sjcommon;
215776404edcSAsim Jamshed 
215876404edcSAsim Jamshed     /*
215976404edcSAsim Jamshed      * This code is not compatible with the optimizer, as
216076404edcSAsim Jamshed      * we are generating jmp instructions within a normal
216176404edcSAsim Jamshed      * slist of instructions
216276404edcSAsim Jamshed      */
216376404edcSAsim Jamshed     no_optimize = 1;
216476404edcSAsim Jamshed 
216576404edcSAsim Jamshed     /*
216676404edcSAsim Jamshed      * Generate code to load the length of the radio header into
216776404edcSAsim Jamshed      * the register assigned to hold that length, if one has been
216876404edcSAsim Jamshed      * assigned.  (If one hasn't been assigned, no code we've
216976404edcSAsim Jamshed      * generated uses that prefix, so we don't need to generate any
217076404edcSAsim Jamshed      * code to load it.)
217176404edcSAsim Jamshed      *
217276404edcSAsim Jamshed      * Some Linux drivers use ARPHRD_IEEE80211_PRISM but sometimes
217376404edcSAsim Jamshed      * or always use the AVS header rather than the Prism header.
217476404edcSAsim Jamshed      * We load a 4-byte big-endian value at the beginning of the
217576404edcSAsim Jamshed      * raw packet data, and see whether, when masked with 0xFFFFF000,
217676404edcSAsim Jamshed      * it's equal to 0x80211000.  If so, that indicates that it's
217776404edcSAsim Jamshed      * an AVS header (the masked-out bits are the version number).
217876404edcSAsim Jamshed      * Otherwise, it's a Prism header.
217976404edcSAsim Jamshed      *
218076404edcSAsim Jamshed      * XXX - the Prism header is also, in theory, variable-length,
218176404edcSAsim Jamshed      * but no known software generates headers that aren't 144
218276404edcSAsim Jamshed      * bytes long.
218376404edcSAsim Jamshed      */
218476404edcSAsim Jamshed     if (reg_off_ll != -1)
218576404edcSAsim Jamshed     {
218676404edcSAsim Jamshed         /*
218776404edcSAsim Jamshed          * Load the cookie.
218876404edcSAsim Jamshed          */
218976404edcSAsim Jamshed         s1 = new_stmt(BPF_LD | BPF_W | BPF_ABS);
219076404edcSAsim Jamshed         s1->s.k = 0;
219176404edcSAsim Jamshed 
219276404edcSAsim Jamshed         /*
219376404edcSAsim Jamshed          * AND it with 0xFFFFF000.
219476404edcSAsim Jamshed          */
219576404edcSAsim Jamshed         s2 = new_stmt(BPF_ALU | BPF_AND | BPF_K);
219676404edcSAsim Jamshed         s2->s.k = 0xFFFFF000;
219776404edcSAsim Jamshed         sappend(s1, s2);
219876404edcSAsim Jamshed 
219976404edcSAsim Jamshed         /*
220076404edcSAsim Jamshed          * Compare with 0x80211000.
220176404edcSAsim Jamshed          */
220276404edcSAsim Jamshed         sjeq_avs_cookie = new_stmt(JMP(BPF_JEQ));
220376404edcSAsim Jamshed         sjeq_avs_cookie->s.k = 0x80211000;
220476404edcSAsim Jamshed         sappend(s1, sjeq_avs_cookie);
220576404edcSAsim Jamshed 
220676404edcSAsim Jamshed         /*
220776404edcSAsim Jamshed          * If it's AVS:
220876404edcSAsim Jamshed          *
220976404edcSAsim Jamshed          * The 4 bytes at an offset of 4 from the beginning of
221076404edcSAsim Jamshed          * the AVS header are the length of the AVS header.
221176404edcSAsim Jamshed          * That field is big-endian.
221276404edcSAsim Jamshed          */
221376404edcSAsim Jamshed         s2 = new_stmt(BPF_LD | BPF_W | BPF_ABS);
221476404edcSAsim Jamshed         s2->s.k = 4;
221576404edcSAsim Jamshed         sappend(s1, s2);
221676404edcSAsim Jamshed         sjeq_avs_cookie->s.jt = s2;
221776404edcSAsim Jamshed 
221876404edcSAsim Jamshed         /*
221976404edcSAsim Jamshed          * Now jump to the code to allocate a register
222076404edcSAsim Jamshed          * into which to save the header length and
222176404edcSAsim Jamshed          * store the length there.  (The "jump always"
222276404edcSAsim Jamshed          * instruction needs to have the k field set;
222376404edcSAsim Jamshed          * it's added to the PC, so, as we're jumping
222476404edcSAsim Jamshed          * over a single instruction, it should be 1.)
222576404edcSAsim Jamshed          */
222676404edcSAsim Jamshed         sjcommon = new_stmt(JMP(BPF_JA));
222776404edcSAsim Jamshed         sjcommon->s.k = 1;
222876404edcSAsim Jamshed         sappend(s1, sjcommon);
222976404edcSAsim Jamshed 
223076404edcSAsim Jamshed         /*
223176404edcSAsim Jamshed          * Now for the code that handles the Prism header.
223276404edcSAsim Jamshed          * Just load the length of the Prism header (144)
223376404edcSAsim Jamshed          * into the A register.  Have the test for an AVS
223476404edcSAsim Jamshed          * header branch here if we don't have an AVS header.
223576404edcSAsim Jamshed          */
223676404edcSAsim Jamshed         s2 = new_stmt(BPF_LD | BPF_W | BPF_IMM);
223776404edcSAsim Jamshed         s2->s.k = 144;
223876404edcSAsim Jamshed         sappend(s1, s2);
223976404edcSAsim Jamshed         sjeq_avs_cookie->s.jf = s2;
224076404edcSAsim Jamshed 
224176404edcSAsim Jamshed         /*
224276404edcSAsim Jamshed          * Now allocate a register to hold that value and store
224376404edcSAsim Jamshed          * it.  The code for the AVS header will jump here after
224476404edcSAsim Jamshed          * loading the length of the AVS header.
224576404edcSAsim Jamshed          */
224676404edcSAsim Jamshed         s2 = new_stmt(BPF_ST);
224776404edcSAsim Jamshed         s2->s.k = reg_off_ll;
224876404edcSAsim Jamshed         sappend(s1, s2);
224976404edcSAsim Jamshed         sjcommon->s.jf = s2;
225076404edcSAsim Jamshed 
225176404edcSAsim Jamshed         /*
225276404edcSAsim Jamshed          * Now move it into the X register.
225376404edcSAsim Jamshed          */
225476404edcSAsim Jamshed         s2 = new_stmt(BPF_MISC | BPF_TAX);
225576404edcSAsim Jamshed         sappend(s1, s2);
225676404edcSAsim Jamshed 
225776404edcSAsim Jamshed         return (s1);
225876404edcSAsim Jamshed     }
225976404edcSAsim Jamshed     else
226076404edcSAsim Jamshed         return (NULL);
226176404edcSAsim Jamshed }
226276404edcSAsim Jamshed 
gen_load_avs_llprefixlen()226376404edcSAsim Jamshed static struct slist *gen_load_avs_llprefixlen()
226476404edcSAsim Jamshed {
226576404edcSAsim Jamshed     struct slist *s1, *s2;
226676404edcSAsim Jamshed 
226776404edcSAsim Jamshed     /*
226876404edcSAsim Jamshed      * Generate code to load the length of the AVS header into
226976404edcSAsim Jamshed      * the register assigned to hold that length, if one has been
227076404edcSAsim Jamshed      * assigned.  (If one hasn't been assigned, no code we've
227176404edcSAsim Jamshed      * generated uses that prefix, so we don't need to generate any
227276404edcSAsim Jamshed      * code to load it.)
227376404edcSAsim Jamshed      */
227476404edcSAsim Jamshed     if (reg_off_ll != -1)
227576404edcSAsim Jamshed     {
227676404edcSAsim Jamshed         /*
227776404edcSAsim Jamshed          * The 4 bytes at an offset of 4 from the beginning of
227876404edcSAsim Jamshed          * the AVS header are the length of the AVS header.
227976404edcSAsim Jamshed          * That field is big-endian.
228076404edcSAsim Jamshed          */
228176404edcSAsim Jamshed         s1 = new_stmt(BPF_LD | BPF_W | BPF_ABS);
228276404edcSAsim Jamshed         s1->s.k = 4;
228376404edcSAsim Jamshed 
228476404edcSAsim Jamshed         /*
228576404edcSAsim Jamshed          * Now allocate a register to hold that value and store
228676404edcSAsim Jamshed          * it.
228776404edcSAsim Jamshed          */
228876404edcSAsim Jamshed         s2 = new_stmt(BPF_ST);
228976404edcSAsim Jamshed         s2->s.k = reg_off_ll;
229076404edcSAsim Jamshed         sappend(s1, s2);
229176404edcSAsim Jamshed 
229276404edcSAsim Jamshed         /*
229376404edcSAsim Jamshed          * Now move it into the X register.
229476404edcSAsim Jamshed          */
229576404edcSAsim Jamshed         s2 = new_stmt(BPF_MISC | BPF_TAX);
229676404edcSAsim Jamshed         sappend(s1, s2);
229776404edcSAsim Jamshed 
229876404edcSAsim Jamshed         return (s1);
229976404edcSAsim Jamshed     }
230076404edcSAsim Jamshed     else
230176404edcSAsim Jamshed         return (NULL);
230276404edcSAsim Jamshed }
230376404edcSAsim Jamshed 
gen_load_radiotap_llprefixlen()230476404edcSAsim Jamshed static struct slist *gen_load_radiotap_llprefixlen()
230576404edcSAsim Jamshed {
230676404edcSAsim Jamshed     struct slist *s1, *s2;
230776404edcSAsim Jamshed 
230876404edcSAsim Jamshed     /*
230976404edcSAsim Jamshed      * Generate code to load the length of the radiotap header into
231076404edcSAsim Jamshed      * the register assigned to hold that length, if one has been
231176404edcSAsim Jamshed      * assigned.  (If one hasn't been assigned, no code we've
231276404edcSAsim Jamshed      * generated uses that prefix, so we don't need to generate any
231376404edcSAsim Jamshed      * code to load it.)
231476404edcSAsim Jamshed      */
231576404edcSAsim Jamshed     if (reg_off_ll != -1)
231676404edcSAsim Jamshed     {
231776404edcSAsim Jamshed         /*
231876404edcSAsim Jamshed          * The 2 bytes at offsets of 2 and 3 from the beginning
231976404edcSAsim Jamshed          * of the radiotap header are the length of the radiotap
232076404edcSAsim Jamshed          * header; unfortunately, it's little-endian, so we have
232176404edcSAsim Jamshed          * to load it a byte at a time and construct the value.
232276404edcSAsim Jamshed          */
232376404edcSAsim Jamshed 
232476404edcSAsim Jamshed         /*
232576404edcSAsim Jamshed          * Load the high-order byte, at an offset of 3, shift it
232676404edcSAsim Jamshed          * left a byte, and put the result in the X register.
232776404edcSAsim Jamshed          */
232876404edcSAsim Jamshed         s1 = new_stmt(BPF_LD | BPF_B | BPF_ABS);
232976404edcSAsim Jamshed         s1->s.k = 3;
233076404edcSAsim Jamshed         s2 = new_stmt(BPF_ALU | BPF_LSH | BPF_K);
233176404edcSAsim Jamshed         sappend(s1, s2);
233276404edcSAsim Jamshed         s2->s.k = 8;
233376404edcSAsim Jamshed         s2 = new_stmt(BPF_MISC | BPF_TAX);
233476404edcSAsim Jamshed         sappend(s1, s2);
233576404edcSAsim Jamshed 
233676404edcSAsim Jamshed         /*
233776404edcSAsim Jamshed          * Load the next byte, at an offset of 2, and OR the
233876404edcSAsim Jamshed          * value from the X register into it.
233976404edcSAsim Jamshed          */
234076404edcSAsim Jamshed         s2 = new_stmt(BPF_LD | BPF_B | BPF_ABS);
234176404edcSAsim Jamshed         sappend(s1, s2);
234276404edcSAsim Jamshed         s2->s.k = 2;
234376404edcSAsim Jamshed         s2 = new_stmt(BPF_ALU | BPF_OR | BPF_X);
234476404edcSAsim Jamshed         sappend(s1, s2);
234576404edcSAsim Jamshed 
234676404edcSAsim Jamshed         /*
234776404edcSAsim Jamshed          * Now allocate a register to hold that value and store
234876404edcSAsim Jamshed          * it.
234976404edcSAsim Jamshed          */
235076404edcSAsim Jamshed         s2 = new_stmt(BPF_ST);
235176404edcSAsim Jamshed         s2->s.k = reg_off_ll;
235276404edcSAsim Jamshed         sappend(s1, s2);
235376404edcSAsim Jamshed 
235476404edcSAsim Jamshed         /*
235576404edcSAsim Jamshed          * Now move it into the X register.
235676404edcSAsim Jamshed          */
235776404edcSAsim Jamshed         s2 = new_stmt(BPF_MISC | BPF_TAX);
235876404edcSAsim Jamshed         sappend(s1, s2);
235976404edcSAsim Jamshed 
236076404edcSAsim Jamshed         return (s1);
236176404edcSAsim Jamshed     }
236276404edcSAsim Jamshed     else
236376404edcSAsim Jamshed         return (NULL);
236476404edcSAsim Jamshed }
236576404edcSAsim Jamshed 
236676404edcSAsim Jamshed /*
236776404edcSAsim Jamshed  * At the moment we treat PPI as normal Radiotap encoded
236876404edcSAsim Jamshed  * packets. The difference is in the function that generates
236976404edcSAsim Jamshed  * the code at the beginning to compute the header length.
237076404edcSAsim Jamshed  * Since this code generator of PPI supports bare 802.11
237176404edcSAsim Jamshed  * encapsulation only (i.e. the encapsulated DLT should be
237276404edcSAsim Jamshed  * DLT_IEEE802_11) we generate code to check for this too;
237376404edcSAsim Jamshed  * that's done in finish_parse().
237476404edcSAsim Jamshed  */
gen_load_ppi_llprefixlen()237576404edcSAsim Jamshed static struct slist *gen_load_ppi_llprefixlen()
237676404edcSAsim Jamshed {
237776404edcSAsim Jamshed     struct slist *s1, *s2;
237876404edcSAsim Jamshed 
237976404edcSAsim Jamshed     /*
238076404edcSAsim Jamshed      * Generate code to load the length of the radiotap header
238176404edcSAsim Jamshed      * into the register assigned to hold that length, if one has
238276404edcSAsim Jamshed      * been assigned.
238376404edcSAsim Jamshed      */
238476404edcSAsim Jamshed     if (reg_off_ll != -1)
238576404edcSAsim Jamshed     {
238676404edcSAsim Jamshed         /*
238776404edcSAsim Jamshed          * The 2 bytes at offsets of 2 and 3 from the beginning
238876404edcSAsim Jamshed          * of the radiotap header are the length of the radiotap
238976404edcSAsim Jamshed          * header; unfortunately, it's little-endian, so we have
239076404edcSAsim Jamshed          * to load it a byte at a time and construct the value.
239176404edcSAsim Jamshed          */
239276404edcSAsim Jamshed 
239376404edcSAsim Jamshed         /*
239476404edcSAsim Jamshed          * Load the high-order byte, at an offset of 3, shift it
239576404edcSAsim Jamshed          * left a byte, and put the result in the X register.
239676404edcSAsim Jamshed          */
239776404edcSAsim Jamshed         s1 = new_stmt(BPF_LD | BPF_B | BPF_ABS);
239876404edcSAsim Jamshed         s1->s.k = 3;
239976404edcSAsim Jamshed         s2 = new_stmt(BPF_ALU | BPF_LSH | BPF_K);
240076404edcSAsim Jamshed         sappend(s1, s2);
240176404edcSAsim Jamshed         s2->s.k = 8;
240276404edcSAsim Jamshed         s2 = new_stmt(BPF_MISC | BPF_TAX);
240376404edcSAsim Jamshed         sappend(s1, s2);
240476404edcSAsim Jamshed 
240576404edcSAsim Jamshed         /*
240676404edcSAsim Jamshed          * Load the next byte, at an offset of 2, and OR the
240776404edcSAsim Jamshed          * value from the X register into it.
240876404edcSAsim Jamshed          */
240976404edcSAsim Jamshed         s2 = new_stmt(BPF_LD | BPF_B | BPF_ABS);
241076404edcSAsim Jamshed         sappend(s1, s2);
241176404edcSAsim Jamshed         s2->s.k = 2;
241276404edcSAsim Jamshed         s2 = new_stmt(BPF_ALU | BPF_OR | BPF_X);
241376404edcSAsim Jamshed         sappend(s1, s2);
241476404edcSAsim Jamshed 
241576404edcSAsim Jamshed         /*
241676404edcSAsim Jamshed          * Now allocate a register to hold that value and store
241776404edcSAsim Jamshed          * it.
241876404edcSAsim Jamshed          */
241976404edcSAsim Jamshed         s2 = new_stmt(BPF_ST);
242076404edcSAsim Jamshed         s2->s.k = reg_off_ll;
242176404edcSAsim Jamshed         sappend(s1, s2);
242276404edcSAsim Jamshed 
242376404edcSAsim Jamshed         /*
242476404edcSAsim Jamshed          * Now move it into the X register.
242576404edcSAsim Jamshed          */
242676404edcSAsim Jamshed         s2 = new_stmt(BPF_MISC | BPF_TAX);
242776404edcSAsim Jamshed         sappend(s1, s2);
242876404edcSAsim Jamshed 
242976404edcSAsim Jamshed         return (s1);
243076404edcSAsim Jamshed     }
243176404edcSAsim Jamshed     else
243276404edcSAsim Jamshed         return (NULL);
243376404edcSAsim Jamshed }
243476404edcSAsim Jamshed 
243576404edcSAsim Jamshed /*
243676404edcSAsim Jamshed  * Load a value relative to the beginning of the link-layer header after the 802.11
243776404edcSAsim Jamshed  * header, i.e. LLC_SNAP.
243876404edcSAsim Jamshed  * The link-layer header doesn't necessarily begin at the beginning
243976404edcSAsim Jamshed  * of the packet data; there might be a variable-length prefix containing
244076404edcSAsim Jamshed  * radio information.
244176404edcSAsim Jamshed  */
gen_load_802_11_header_len(struct slist * s,struct slist * snext)244276404edcSAsim Jamshed static struct slist *gen_load_802_11_header_len(struct slist *s, struct slist *snext)
244376404edcSAsim Jamshed {
244476404edcSAsim Jamshed     struct slist *s2;
244576404edcSAsim Jamshed     struct slist *sjset_data_frame_1;
244676404edcSAsim Jamshed     struct slist *sjset_data_frame_2;
244776404edcSAsim Jamshed     struct slist *sjset_qos;
244876404edcSAsim Jamshed     struct slist *sjset_radiotap_flags;
244976404edcSAsim Jamshed     struct slist *sjset_radiotap_tsft;
245076404edcSAsim Jamshed     struct slist *sjset_tsft_datapad, *sjset_notsft_datapad;
245176404edcSAsim Jamshed     struct slist *s_roundup;
245276404edcSAsim Jamshed 
245376404edcSAsim Jamshed     if (reg_off_macpl == -1)
245476404edcSAsim Jamshed     {
245576404edcSAsim Jamshed         /*
245676404edcSAsim Jamshed          * No register has been assigned to the offset of
245776404edcSAsim Jamshed          * the MAC-layer payload, which means nobody needs
245876404edcSAsim Jamshed          * it; don't bother computing it - just return
245976404edcSAsim Jamshed          * what we already have.
246076404edcSAsim Jamshed          */
246176404edcSAsim Jamshed         return (s);
246276404edcSAsim Jamshed     }
246376404edcSAsim Jamshed 
246476404edcSAsim Jamshed     /*
246576404edcSAsim Jamshed      * This code is not compatible with the optimizer, as
246676404edcSAsim Jamshed      * we are generating jmp instructions within a normal
246776404edcSAsim Jamshed      * slist of instructions
246876404edcSAsim Jamshed      */
246976404edcSAsim Jamshed     no_optimize = 1;
247076404edcSAsim Jamshed 
247176404edcSAsim Jamshed     /*
247276404edcSAsim Jamshed      * If "s" is non-null, it has code to arrange that the X register
247376404edcSAsim Jamshed      * contains the length of the prefix preceding the link-layer
247476404edcSAsim Jamshed      * header.
247576404edcSAsim Jamshed      *
247676404edcSAsim Jamshed      * Otherwise, the length of the prefix preceding the link-layer
247776404edcSAsim Jamshed      * header is "off_ll".
247876404edcSAsim Jamshed      */
247976404edcSAsim Jamshed     if (s == NULL)
248076404edcSAsim Jamshed     {
248176404edcSAsim Jamshed         /*
248276404edcSAsim Jamshed          * There is no variable-length header preceding the
248376404edcSAsim Jamshed          * link-layer header.
248476404edcSAsim Jamshed          *
248576404edcSAsim Jamshed          * Load the length of the fixed-length prefix preceding
248676404edcSAsim Jamshed          * the link-layer header (if any) into the X register,
248776404edcSAsim Jamshed          * and store it in the reg_off_macpl register.
248876404edcSAsim Jamshed          * That length is off_ll.
248976404edcSAsim Jamshed          */
249076404edcSAsim Jamshed         s = new_stmt(BPF_LDX | BPF_IMM);
249176404edcSAsim Jamshed         s->s.k = off_ll;
249276404edcSAsim Jamshed     }
249376404edcSAsim Jamshed 
249476404edcSAsim Jamshed     /*
249576404edcSAsim Jamshed      * The X register contains the offset of the beginning of the
249676404edcSAsim Jamshed      * link-layer header; add 24, which is the minimum length
249776404edcSAsim Jamshed      * of the MAC header for a data frame, to that, and store it
249876404edcSAsim Jamshed      * in reg_off_macpl, and then load the Frame Control field,
249976404edcSAsim Jamshed      * which is at the offset in the X register, with an indexed load.
250076404edcSAsim Jamshed      */
250176404edcSAsim Jamshed     s2 = new_stmt(BPF_MISC | BPF_TXA);
250276404edcSAsim Jamshed     sappend(s, s2);
250376404edcSAsim Jamshed     s2 = new_stmt(BPF_ALU | BPF_ADD | BPF_K);
250476404edcSAsim Jamshed     s2->s.k = 24;
250576404edcSAsim Jamshed     sappend(s, s2);
250676404edcSAsim Jamshed     s2 = new_stmt(BPF_ST);
250776404edcSAsim Jamshed     s2->s.k = reg_off_macpl;
250876404edcSAsim Jamshed     sappend(s, s2);
250976404edcSAsim Jamshed 
251076404edcSAsim Jamshed     s2 = new_stmt(BPF_LD | BPF_IND | BPF_B);
251176404edcSAsim Jamshed     s2->s.k = 0;
251276404edcSAsim Jamshed     sappend(s, s2);
251376404edcSAsim Jamshed 
251476404edcSAsim Jamshed     /*
251576404edcSAsim Jamshed      * Check the Frame Control field to see if this is a data frame;
251676404edcSAsim Jamshed      * a data frame has the 0x08 bit (b3) in that field set and the
251776404edcSAsim Jamshed      * 0x04 bit (b2) clear.
251876404edcSAsim Jamshed      */
251976404edcSAsim Jamshed     sjset_data_frame_1 = new_stmt(JMP(BPF_JSET));
252076404edcSAsim Jamshed     sjset_data_frame_1->s.k = 0x08;
252176404edcSAsim Jamshed     sappend(s, sjset_data_frame_1);
252276404edcSAsim Jamshed 
252376404edcSAsim Jamshed     /*
252476404edcSAsim Jamshed      * If b3 is set, test b2, otherwise go to the first statement of
252576404edcSAsim Jamshed      * the rest of the program.
252676404edcSAsim Jamshed      */
252776404edcSAsim Jamshed     sjset_data_frame_1->s.jt = sjset_data_frame_2 = new_stmt(JMP(BPF_JSET));
252876404edcSAsim Jamshed     sjset_data_frame_2->s.k = 0x04;
252976404edcSAsim Jamshed     sappend(s, sjset_data_frame_2);
253076404edcSAsim Jamshed     sjset_data_frame_1->s.jf = snext;
253176404edcSAsim Jamshed 
253276404edcSAsim Jamshed     /*
253376404edcSAsim Jamshed      * If b2 is not set, this is a data frame; test the QoS bit.
253476404edcSAsim Jamshed      * Otherwise, go to the first statement of the rest of the
253576404edcSAsim Jamshed      * program.
253676404edcSAsim Jamshed      */
253776404edcSAsim Jamshed     sjset_data_frame_2->s.jt = snext;
253876404edcSAsim Jamshed     sjset_data_frame_2->s.jf = sjset_qos = new_stmt(JMP(BPF_JSET));
253976404edcSAsim Jamshed     sjset_qos->s.k = 0x80;      /* QoS bit */
254076404edcSAsim Jamshed     sappend(s, sjset_qos);
254176404edcSAsim Jamshed 
254276404edcSAsim Jamshed     /*
254376404edcSAsim Jamshed      * If it's set, add 2 to reg_off_macpl, to skip the QoS
254476404edcSAsim Jamshed      * field.
254576404edcSAsim Jamshed      * Otherwise, go to the first statement of the rest of the
254676404edcSAsim Jamshed      * program.
254776404edcSAsim Jamshed      */
254876404edcSAsim Jamshed     sjset_qos->s.jt = s2 = new_stmt(BPF_LD | BPF_MEM);
254976404edcSAsim Jamshed     s2->s.k = reg_off_macpl;
255076404edcSAsim Jamshed     sappend(s, s2);
255176404edcSAsim Jamshed     s2 = new_stmt(BPF_ALU | BPF_ADD | BPF_IMM);
255276404edcSAsim Jamshed     s2->s.k = 2;
255376404edcSAsim Jamshed     sappend(s, s2);
255476404edcSAsim Jamshed     s2 = new_stmt(BPF_ST);
255576404edcSAsim Jamshed     s2->s.k = reg_off_macpl;
255676404edcSAsim Jamshed     sappend(s, s2);
255776404edcSAsim Jamshed 
255876404edcSAsim Jamshed     /*
255976404edcSAsim Jamshed      * If we have a radiotap header, look at it to see whether
256076404edcSAsim Jamshed      * there's Atheros padding between the MAC-layer header
256176404edcSAsim Jamshed      * and the payload.
256276404edcSAsim Jamshed      *
256376404edcSAsim Jamshed      * Note: all of the fields in the radiotap header are
256476404edcSAsim Jamshed      * little-endian, so we byte-swap all of the values
256576404edcSAsim Jamshed      * we test against, as they will be loaded as big-endian
256676404edcSAsim Jamshed      * values.
256776404edcSAsim Jamshed      */
256876404edcSAsim Jamshed     if (linktype == DLT_IEEE802_11_RADIO)
256976404edcSAsim Jamshed     {
257076404edcSAsim Jamshed         /*
257176404edcSAsim Jamshed          * Is the IEEE80211_RADIOTAP_FLAGS bit (0x0000002) set
257276404edcSAsim Jamshed          * in the presence flag?
257376404edcSAsim Jamshed          */
257476404edcSAsim Jamshed         sjset_qos->s.jf = s2 = new_stmt(BPF_LD | BPF_ABS | BPF_W);
257576404edcSAsim Jamshed         s2->s.k = 4;
257676404edcSAsim Jamshed         sappend(s, s2);
257776404edcSAsim Jamshed 
257876404edcSAsim Jamshed         sjset_radiotap_flags = new_stmt(JMP(BPF_JSET));
257976404edcSAsim Jamshed         sjset_radiotap_flags->s.k = SWAPLONG(0x00000002);
258076404edcSAsim Jamshed         sappend(s, sjset_radiotap_flags);
258176404edcSAsim Jamshed 
258276404edcSAsim Jamshed         /*
258376404edcSAsim Jamshed          * If not, skip all of this.
258476404edcSAsim Jamshed          */
258576404edcSAsim Jamshed         sjset_radiotap_flags->s.jf = snext;
258676404edcSAsim Jamshed 
258776404edcSAsim Jamshed         /*
258876404edcSAsim Jamshed          * Otherwise, is the IEEE80211_RADIOTAP_TSFT bit set?
258976404edcSAsim Jamshed          */
259076404edcSAsim Jamshed         sjset_radiotap_tsft = sjset_radiotap_flags->s.jt = new_stmt(JMP(BPF_JSET));
259176404edcSAsim Jamshed         sjset_radiotap_tsft->s.k = SWAPLONG(0x00000001);
259276404edcSAsim Jamshed         sappend(s, sjset_radiotap_tsft);
259376404edcSAsim Jamshed 
259476404edcSAsim Jamshed         /*
259576404edcSAsim Jamshed          * If IEEE80211_RADIOTAP_TSFT is set, the flags field is
259676404edcSAsim Jamshed          * at an offset of 16 from the beginning of the raw packet
259776404edcSAsim Jamshed          * data (8 bytes for the radiotap header and 8 bytes for
259876404edcSAsim Jamshed          * the TSFT field).
259976404edcSAsim Jamshed          *
260076404edcSAsim Jamshed          * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
260176404edcSAsim Jamshed          * is set.
260276404edcSAsim Jamshed          */
260376404edcSAsim Jamshed         sjset_radiotap_tsft->s.jt = s2 = new_stmt(BPF_LD | BPF_ABS | BPF_B);
260476404edcSAsim Jamshed         s2->s.k = 16;
260576404edcSAsim Jamshed         sappend(s, s2);
260676404edcSAsim Jamshed 
260776404edcSAsim Jamshed         sjset_tsft_datapad = new_stmt(JMP(BPF_JSET));
260876404edcSAsim Jamshed         sjset_tsft_datapad->s.k = 0x20;
260976404edcSAsim Jamshed         sappend(s, sjset_tsft_datapad);
261076404edcSAsim Jamshed 
261176404edcSAsim Jamshed         /*
261276404edcSAsim Jamshed          * If IEEE80211_RADIOTAP_TSFT is not set, the flags field is
261376404edcSAsim Jamshed          * at an offset of 8 from the beginning of the raw packet
261476404edcSAsim Jamshed          * data (8 bytes for the radiotap header).
261576404edcSAsim Jamshed          *
261676404edcSAsim Jamshed          * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
261776404edcSAsim Jamshed          * is set.
261876404edcSAsim Jamshed          */
261976404edcSAsim Jamshed         sjset_radiotap_tsft->s.jf = s2 = new_stmt(BPF_LD | BPF_ABS | BPF_B);
262076404edcSAsim Jamshed         s2->s.k = 8;
262176404edcSAsim Jamshed         sappend(s, s2);
262276404edcSAsim Jamshed 
262376404edcSAsim Jamshed         sjset_notsft_datapad = new_stmt(JMP(BPF_JSET));
262476404edcSAsim Jamshed         sjset_notsft_datapad->s.k = 0x20;
262576404edcSAsim Jamshed         sappend(s, sjset_notsft_datapad);
262676404edcSAsim Jamshed 
262776404edcSAsim Jamshed         /*
262876404edcSAsim Jamshed          * In either case, if IEEE80211_RADIOTAP_F_DATAPAD is
262976404edcSAsim Jamshed          * set, round the length of the 802.11 header to
263076404edcSAsim Jamshed          * a multiple of 4.  Do that by adding 3 and then
263176404edcSAsim Jamshed          * dividing by and multiplying by 4, which we do by
263276404edcSAsim Jamshed          * ANDing with ~3.
263376404edcSAsim Jamshed          */
263476404edcSAsim Jamshed         s_roundup = new_stmt(BPF_LD | BPF_MEM);
263576404edcSAsim Jamshed         s_roundup->s.k = reg_off_macpl;
263676404edcSAsim Jamshed         sappend(s, s_roundup);
263776404edcSAsim Jamshed         s2 = new_stmt(BPF_ALU | BPF_ADD | BPF_IMM);
263876404edcSAsim Jamshed         s2->s.k = 3;
263976404edcSAsim Jamshed         sappend(s, s2);
264076404edcSAsim Jamshed         s2 = new_stmt(BPF_ALU | BPF_AND | BPF_IMM);
264176404edcSAsim Jamshed         s2->s.k = ~3;
264276404edcSAsim Jamshed         sappend(s, s2);
264376404edcSAsim Jamshed         s2 = new_stmt(BPF_ST);
264476404edcSAsim Jamshed         s2->s.k = reg_off_macpl;
264576404edcSAsim Jamshed         sappend(s, s2);
264676404edcSAsim Jamshed 
264776404edcSAsim Jamshed         sjset_tsft_datapad->s.jt = s_roundup;
264876404edcSAsim Jamshed         sjset_tsft_datapad->s.jf = snext;
264976404edcSAsim Jamshed         sjset_notsft_datapad->s.jt = s_roundup;
265076404edcSAsim Jamshed         sjset_notsft_datapad->s.jf = snext;
265176404edcSAsim Jamshed     }
265276404edcSAsim Jamshed     else
265376404edcSAsim Jamshed         sjset_qos->s.jf = snext;
265476404edcSAsim Jamshed 
265576404edcSAsim Jamshed     return s;
265676404edcSAsim Jamshed }
265776404edcSAsim Jamshed 
insert_compute_vloffsets(b)265876404edcSAsim Jamshed static void insert_compute_vloffsets(b)
265976404edcSAsim Jamshed      struct block *b;
266076404edcSAsim Jamshed {
266176404edcSAsim Jamshed     struct slist *s;
266276404edcSAsim Jamshed 
266376404edcSAsim Jamshed     /*
266476404edcSAsim Jamshed      * For link-layer types that have a variable-length header
266576404edcSAsim Jamshed      * preceding the link-layer header, generate code to load
266676404edcSAsim Jamshed      * the offset of the link-layer header into the register
266776404edcSAsim Jamshed      * assigned to that offset, if any.
266876404edcSAsim Jamshed      */
266976404edcSAsim Jamshed     switch (linktype)
267076404edcSAsim Jamshed     {
267176404edcSAsim Jamshed 
267276404edcSAsim Jamshed         case DLT_PRISM_HEADER:
267376404edcSAsim Jamshed             s = gen_load_prism_llprefixlen();
267476404edcSAsim Jamshed             break;
267576404edcSAsim Jamshed 
267676404edcSAsim Jamshed         case DLT_IEEE802_11_RADIO_AVS:
267776404edcSAsim Jamshed             s = gen_load_avs_llprefixlen();
267876404edcSAsim Jamshed             break;
267976404edcSAsim Jamshed 
268076404edcSAsim Jamshed         case DLT_IEEE802_11_RADIO:
268176404edcSAsim Jamshed             s = gen_load_radiotap_llprefixlen();
268276404edcSAsim Jamshed             break;
268376404edcSAsim Jamshed 
268476404edcSAsim Jamshed         case DLT_PPI:
268576404edcSAsim Jamshed             s = gen_load_ppi_llprefixlen();
268676404edcSAsim Jamshed             break;
268776404edcSAsim Jamshed 
268876404edcSAsim Jamshed         default:
268976404edcSAsim Jamshed             s = NULL;
269076404edcSAsim Jamshed             break;
269176404edcSAsim Jamshed     }
269276404edcSAsim Jamshed 
269376404edcSAsim Jamshed     /*
269476404edcSAsim Jamshed      * For link-layer types that have a variable-length link-layer
269576404edcSAsim Jamshed      * header, generate code to load the offset of the MAC-layer
269676404edcSAsim Jamshed      * payload into the register assigned to that offset, if any.
269776404edcSAsim Jamshed      */
269876404edcSAsim Jamshed     switch (linktype)
269976404edcSAsim Jamshed     {
270076404edcSAsim Jamshed 
270176404edcSAsim Jamshed         case DLT_IEEE802_11:
270276404edcSAsim Jamshed         case DLT_PRISM_HEADER:
270376404edcSAsim Jamshed         case DLT_IEEE802_11_RADIO_AVS:
270476404edcSAsim Jamshed         case DLT_IEEE802_11_RADIO:
270576404edcSAsim Jamshed         case DLT_PPI:
270676404edcSAsim Jamshed             s = gen_load_802_11_header_len(s, b->stmts);
270776404edcSAsim Jamshed             break;
270876404edcSAsim Jamshed     }
270976404edcSAsim Jamshed 
271076404edcSAsim Jamshed     /*
271176404edcSAsim Jamshed      * If we have any offset-loading code, append all the
271276404edcSAsim Jamshed      * existing statements in the block to those statements,
271376404edcSAsim Jamshed      * and make the resulting list the list of statements
271476404edcSAsim Jamshed      * for the block.
271576404edcSAsim Jamshed      */
271676404edcSAsim Jamshed     if (s != NULL)
271776404edcSAsim Jamshed     {
271876404edcSAsim Jamshed         sappend(s, b->stmts);
271976404edcSAsim Jamshed         b->stmts = s;
272076404edcSAsim Jamshed     }
272176404edcSAsim Jamshed }
272276404edcSAsim Jamshed 
gen_ppi_dlt_check(void)272376404edcSAsim Jamshed static struct block *gen_ppi_dlt_check(void)
272476404edcSAsim Jamshed {
272576404edcSAsim Jamshed     struct slist *s_load_dlt;
272676404edcSAsim Jamshed     struct block *b;
272776404edcSAsim Jamshed 
272876404edcSAsim Jamshed     if (linktype == DLT_PPI)
272976404edcSAsim Jamshed     {
273076404edcSAsim Jamshed         /* Create the statements that check for the DLT
273176404edcSAsim Jamshed          */
273276404edcSAsim Jamshed         s_load_dlt = new_stmt(BPF_LD | BPF_W | BPF_ABS);
273376404edcSAsim Jamshed         s_load_dlt->s.k = 4;
273476404edcSAsim Jamshed 
273576404edcSAsim Jamshed         b = new_block(JMP(BPF_JEQ));
273676404edcSAsim Jamshed 
273776404edcSAsim Jamshed         b->stmts = s_load_dlt;
273876404edcSAsim Jamshed         b->s.k = SWAPLONG(DLT_IEEE802_11);
273976404edcSAsim Jamshed     }
274076404edcSAsim Jamshed     else
274176404edcSAsim Jamshed     {
274276404edcSAsim Jamshed         b = NULL;
274376404edcSAsim Jamshed     }
274476404edcSAsim Jamshed 
274576404edcSAsim Jamshed     return b;
274676404edcSAsim Jamshed }
274776404edcSAsim Jamshed 
gen_prism_llprefixlen(void)274876404edcSAsim Jamshed static struct slist *gen_prism_llprefixlen(void)
274976404edcSAsim Jamshed {
275076404edcSAsim Jamshed     struct slist *s;
275176404edcSAsim Jamshed 
275276404edcSAsim Jamshed     if (reg_off_ll == -1)
275376404edcSAsim Jamshed     {
275476404edcSAsim Jamshed         /*
275576404edcSAsim Jamshed          * We haven't yet assigned a register for the length
275676404edcSAsim Jamshed          * of the radio header; allocate one.
275776404edcSAsim Jamshed          */
275876404edcSAsim Jamshed         reg_off_ll = alloc_reg();
275976404edcSAsim Jamshed     }
276076404edcSAsim Jamshed 
276176404edcSAsim Jamshed     /*
276276404edcSAsim Jamshed      * Load the register containing the radio length
276376404edcSAsim Jamshed      * into the X register.
276476404edcSAsim Jamshed      */
276576404edcSAsim Jamshed     s = new_stmt(BPF_LDX | BPF_MEM);
276676404edcSAsim Jamshed     s->s.k = reg_off_ll;
276776404edcSAsim Jamshed     return s;
276876404edcSAsim Jamshed }
276976404edcSAsim Jamshed 
gen_avs_llprefixlen(void)277076404edcSAsim Jamshed static struct slist *gen_avs_llprefixlen(void)
277176404edcSAsim Jamshed {
277276404edcSAsim Jamshed     struct slist *s;
277376404edcSAsim Jamshed 
277476404edcSAsim Jamshed     if (reg_off_ll == -1)
277576404edcSAsim Jamshed     {
277676404edcSAsim Jamshed         /*
277776404edcSAsim Jamshed          * We haven't yet assigned a register for the length
277876404edcSAsim Jamshed          * of the AVS header; allocate one.
277976404edcSAsim Jamshed          */
278076404edcSAsim Jamshed         reg_off_ll = alloc_reg();
278176404edcSAsim Jamshed     }
278276404edcSAsim Jamshed 
278376404edcSAsim Jamshed     /*
278476404edcSAsim Jamshed      * Load the register containing the AVS length
278576404edcSAsim Jamshed      * into the X register.
278676404edcSAsim Jamshed      */
278776404edcSAsim Jamshed     s = new_stmt(BPF_LDX | BPF_MEM);
278876404edcSAsim Jamshed     s->s.k = reg_off_ll;
278976404edcSAsim Jamshed     return s;
279076404edcSAsim Jamshed }
279176404edcSAsim Jamshed 
gen_radiotap_llprefixlen(void)279276404edcSAsim Jamshed static struct slist *gen_radiotap_llprefixlen(void)
279376404edcSAsim Jamshed {
279476404edcSAsim Jamshed     struct slist *s;
279576404edcSAsim Jamshed 
279676404edcSAsim Jamshed     if (reg_off_ll == -1)
279776404edcSAsim Jamshed     {
279876404edcSAsim Jamshed         /*
279976404edcSAsim Jamshed          * We haven't yet assigned a register for the length
280076404edcSAsim Jamshed          * of the radiotap header; allocate one.
280176404edcSAsim Jamshed          */
280276404edcSAsim Jamshed         reg_off_ll = alloc_reg();
280376404edcSAsim Jamshed     }
280476404edcSAsim Jamshed 
280576404edcSAsim Jamshed     /*
280676404edcSAsim Jamshed      * Load the register containing the radiotap length
280776404edcSAsim Jamshed      * into the X register.
280876404edcSAsim Jamshed      */
280976404edcSAsim Jamshed     s = new_stmt(BPF_LDX | BPF_MEM);
281076404edcSAsim Jamshed     s->s.k = reg_off_ll;
281176404edcSAsim Jamshed     return s;
281276404edcSAsim Jamshed }
281376404edcSAsim Jamshed 
281476404edcSAsim Jamshed /*
281576404edcSAsim Jamshed  * At the moment we treat PPI as normal Radiotap encoded
281676404edcSAsim Jamshed  * packets. The difference is in the function that generates
281776404edcSAsim Jamshed  * the code at the beginning to compute the header length.
281876404edcSAsim Jamshed  * Since this code generator of PPI supports bare 802.11
281976404edcSAsim Jamshed  * encapsulation only (i.e. the encapsulated DLT should be
282076404edcSAsim Jamshed  * DLT_IEEE802_11) we generate code to check for this too.
282176404edcSAsim Jamshed  */
gen_ppi_llprefixlen(void)282276404edcSAsim Jamshed static struct slist *gen_ppi_llprefixlen(void)
282376404edcSAsim Jamshed {
282476404edcSAsim Jamshed     struct slist *s;
282576404edcSAsim Jamshed 
282676404edcSAsim Jamshed     if (reg_off_ll == -1)
282776404edcSAsim Jamshed     {
282876404edcSAsim Jamshed         /*
282976404edcSAsim Jamshed          * We haven't yet assigned a register for the length
283076404edcSAsim Jamshed          * of the radiotap header; allocate one.
283176404edcSAsim Jamshed          */
283276404edcSAsim Jamshed         reg_off_ll = alloc_reg();
283376404edcSAsim Jamshed     }
283476404edcSAsim Jamshed 
283576404edcSAsim Jamshed     /*
283676404edcSAsim Jamshed      * Load the register containing the PPI length
283776404edcSAsim Jamshed      * into the X register.
283876404edcSAsim Jamshed      */
283976404edcSAsim Jamshed     s = new_stmt(BPF_LDX | BPF_MEM);
284076404edcSAsim Jamshed     s->s.k = reg_off_ll;
284176404edcSAsim Jamshed     return s;
284276404edcSAsim Jamshed }
284376404edcSAsim Jamshed 
284476404edcSAsim Jamshed /*
284576404edcSAsim Jamshed  * Generate code to compute the link-layer header length, if necessary,
284676404edcSAsim Jamshed  * putting it into the X register, and to return either a pointer to a
284776404edcSAsim Jamshed  * "struct slist" for the list of statements in that code, or NULL if
284876404edcSAsim Jamshed  * no code is necessary.
284976404edcSAsim Jamshed  */
gen_llprefixlen(void)285076404edcSAsim Jamshed static struct slist *gen_llprefixlen(void)
285176404edcSAsim Jamshed {
285276404edcSAsim Jamshed     switch (linktype)
285376404edcSAsim Jamshed     {
285476404edcSAsim Jamshed 
285576404edcSAsim Jamshed         case DLT_PRISM_HEADER:
285676404edcSAsim Jamshed             return gen_prism_llprefixlen();
285776404edcSAsim Jamshed 
285876404edcSAsim Jamshed         case DLT_IEEE802_11_RADIO_AVS:
285976404edcSAsim Jamshed             return gen_avs_llprefixlen();
286076404edcSAsim Jamshed 
286176404edcSAsim Jamshed         case DLT_IEEE802_11_RADIO:
286276404edcSAsim Jamshed             return gen_radiotap_llprefixlen();
286376404edcSAsim Jamshed 
286476404edcSAsim Jamshed         case DLT_PPI:
286576404edcSAsim Jamshed             return gen_ppi_llprefixlen();
286676404edcSAsim Jamshed 
286776404edcSAsim Jamshed         default:
286876404edcSAsim Jamshed             return NULL;
286976404edcSAsim Jamshed     }
287076404edcSAsim Jamshed }
287176404edcSAsim Jamshed 
287276404edcSAsim Jamshed /*
287376404edcSAsim Jamshed  * Generate code to load the register containing the offset of the
287476404edcSAsim Jamshed  * MAC-layer payload into the X register; if no register for that offset
287576404edcSAsim Jamshed  * has been allocated, allocate it first.
287676404edcSAsim Jamshed  */
gen_off_macpl(void)287776404edcSAsim Jamshed static struct slist *gen_off_macpl(void)
287876404edcSAsim Jamshed {
287976404edcSAsim Jamshed     struct slist *s;
288076404edcSAsim Jamshed 
288176404edcSAsim Jamshed     if (off_macpl_is_variable)
288276404edcSAsim Jamshed     {
288376404edcSAsim Jamshed         if (reg_off_macpl == -1)
288476404edcSAsim Jamshed         {
288576404edcSAsim Jamshed             /*
288676404edcSAsim Jamshed              * We haven't yet assigned a register for the offset
288776404edcSAsim Jamshed              * of the MAC-layer payload; allocate one.
288876404edcSAsim Jamshed              */
288976404edcSAsim Jamshed             reg_off_macpl = alloc_reg();
289076404edcSAsim Jamshed         }
289176404edcSAsim Jamshed 
289276404edcSAsim Jamshed         /*
289376404edcSAsim Jamshed          * Load the register containing the offset of the MAC-layer
289476404edcSAsim Jamshed          * payload into the X register.
289576404edcSAsim Jamshed          */
289676404edcSAsim Jamshed         s = new_stmt(BPF_LDX | BPF_MEM);
289776404edcSAsim Jamshed         s->s.k = reg_off_macpl;
289876404edcSAsim Jamshed         return s;
289976404edcSAsim Jamshed     }
290076404edcSAsim Jamshed     else
290176404edcSAsim Jamshed     {
290276404edcSAsim Jamshed         /*
290376404edcSAsim Jamshed          * That offset isn't variable, so we don't need to
290476404edcSAsim Jamshed          * generate any code.
290576404edcSAsim Jamshed          */
290676404edcSAsim Jamshed         return NULL;
290776404edcSAsim Jamshed     }
290876404edcSAsim Jamshed }
290976404edcSAsim Jamshed 
291076404edcSAsim Jamshed /*
291176404edcSAsim Jamshed  * Map an Ethernet type to the equivalent PPP type.
291276404edcSAsim Jamshed  */
ethertype_to_ppptype(proto)291376404edcSAsim Jamshed static int ethertype_to_ppptype(proto)
291476404edcSAsim Jamshed      int proto;
291576404edcSAsim Jamshed {
291676404edcSAsim Jamshed     switch (proto)
291776404edcSAsim Jamshed     {
291876404edcSAsim Jamshed 
291976404edcSAsim Jamshed         case ETHERTYPE_IP:
292076404edcSAsim Jamshed             proto = PPP_IP;
292176404edcSAsim Jamshed             break;
292276404edcSAsim Jamshed 
292376404edcSAsim Jamshed #ifdef INET6
292476404edcSAsim Jamshed         case ETHERTYPE_IPV6:
292576404edcSAsim Jamshed             proto = PPP_IPV6;
292676404edcSAsim Jamshed             break;
292776404edcSAsim Jamshed #endif
292876404edcSAsim Jamshed 
292976404edcSAsim Jamshed         case ETHERTYPE_DN:
293076404edcSAsim Jamshed             proto = PPP_DECNET;
293176404edcSAsim Jamshed             break;
293276404edcSAsim Jamshed 
293376404edcSAsim Jamshed         case ETHERTYPE_ATALK:
293476404edcSAsim Jamshed             proto = PPP_APPLE;
293576404edcSAsim Jamshed             break;
293676404edcSAsim Jamshed 
293776404edcSAsim Jamshed         case ETHERTYPE_NS:
293876404edcSAsim Jamshed             proto = PPP_NS;
293976404edcSAsim Jamshed             break;
294076404edcSAsim Jamshed 
294176404edcSAsim Jamshed         case LLCSAP_ISONS:
294276404edcSAsim Jamshed             proto = PPP_OSI;
294376404edcSAsim Jamshed             break;
294476404edcSAsim Jamshed 
294576404edcSAsim Jamshed         case LLCSAP_8021D:
294676404edcSAsim Jamshed             /*
294776404edcSAsim Jamshed              * I'm assuming the "Bridging PDU"s that go
294876404edcSAsim Jamshed              * over PPP are Spanning Tree Protocol
294976404edcSAsim Jamshed              * Bridging PDUs.
295076404edcSAsim Jamshed              */
295176404edcSAsim Jamshed             proto = PPP_BRPDU;
295276404edcSAsim Jamshed             break;
295376404edcSAsim Jamshed 
295476404edcSAsim Jamshed         case LLCSAP_IPX:
295576404edcSAsim Jamshed             proto = PPP_IPX;
295676404edcSAsim Jamshed             break;
295776404edcSAsim Jamshed     }
295876404edcSAsim Jamshed     return (proto);
295976404edcSAsim Jamshed }
296076404edcSAsim Jamshed 
296176404edcSAsim Jamshed /*
296276404edcSAsim Jamshed  * Generate code to match a particular packet type by matching the
296376404edcSAsim Jamshed  * link-layer type field or fields in the 802.2 LLC header.
296476404edcSAsim Jamshed  *
296576404edcSAsim Jamshed  * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
296676404edcSAsim Jamshed  * value, if <= ETHERMTU.
296776404edcSAsim Jamshed  */
gen_linktype(proto)296876404edcSAsim Jamshed static struct block *gen_linktype(proto)
296976404edcSAsim Jamshed      register int proto;
297076404edcSAsim Jamshed {
297176404edcSAsim Jamshed     struct block *b0, *b1, *b2;
297276404edcSAsim Jamshed 
297376404edcSAsim Jamshed     /* are we checking MPLS-encapsulated packets? */
297476404edcSAsim Jamshed     if (label_stack_depth > 0)
297576404edcSAsim Jamshed     {
297676404edcSAsim Jamshed         switch (proto)
297776404edcSAsim Jamshed         {
297876404edcSAsim Jamshed             case ETHERTYPE_IP:
297976404edcSAsim Jamshed             case PPP_IP:
298076404edcSAsim Jamshed                 /* FIXME add other L3 proto IDs */
298176404edcSAsim Jamshed                 return gen_mpls_linktype(Q_IP);
298276404edcSAsim Jamshed 
298376404edcSAsim Jamshed             case ETHERTYPE_IPV6:
298476404edcSAsim Jamshed             case PPP_IPV6:
298576404edcSAsim Jamshed                 /* FIXME add other L3 proto IDs */
298676404edcSAsim Jamshed                 return gen_mpls_linktype(Q_IPV6);
298776404edcSAsim Jamshed 
298876404edcSAsim Jamshed             default:
298976404edcSAsim Jamshed                 bpf_error("unsupported protocol over mpls");
299076404edcSAsim Jamshed                 /* NOTREACHED */
299176404edcSAsim Jamshed         }
299276404edcSAsim Jamshed     }
299376404edcSAsim Jamshed 
299476404edcSAsim Jamshed     /*
299576404edcSAsim Jamshed      * Are we testing PPPoE packets?
299676404edcSAsim Jamshed      */
299776404edcSAsim Jamshed     if (is_pppoes)
299876404edcSAsim Jamshed     {
299976404edcSAsim Jamshed         /*
300076404edcSAsim Jamshed          * The PPPoE session header is part of the
300176404edcSAsim Jamshed          * MAC-layer payload, so all references
300276404edcSAsim Jamshed          * should be relative to the beginning of
300376404edcSAsim Jamshed          * that payload.
300476404edcSAsim Jamshed          */
300576404edcSAsim Jamshed 
300676404edcSAsim Jamshed         /*
300776404edcSAsim Jamshed          * We use Ethernet protocol types inside libpcap;
300876404edcSAsim Jamshed          * map them to the corresponding PPP protocol types.
300976404edcSAsim Jamshed          */
301076404edcSAsim Jamshed         proto = ethertype_to_ppptype(proto);
301176404edcSAsim Jamshed         return gen_cmp(OR_MACPL, off_linktype, BPF_H, (bpf_int32) proto);
301276404edcSAsim Jamshed     }
301376404edcSAsim Jamshed 
301476404edcSAsim Jamshed     switch (linktype)
301576404edcSAsim Jamshed     {
301676404edcSAsim Jamshed 
301776404edcSAsim Jamshed         case DLT_EN10MB:
301876404edcSAsim Jamshed             return gen_ether_linktype(proto);
301976404edcSAsim Jamshed              /*NOTREACHED*/ break;
302076404edcSAsim Jamshed 
302176404edcSAsim Jamshed         case DLT_C_HDLC:
302276404edcSAsim Jamshed             switch (proto)
302376404edcSAsim Jamshed             {
302476404edcSAsim Jamshed 
302576404edcSAsim Jamshed                 case LLCSAP_ISONS:
302676404edcSAsim Jamshed                     proto = (proto << 8 | LLCSAP_ISONS);
302776404edcSAsim Jamshed                     /* fall through */
302876404edcSAsim Jamshed 
302976404edcSAsim Jamshed                 default:
303076404edcSAsim Jamshed                     return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32) proto);
303176404edcSAsim Jamshed                      /*NOTREACHED*/ break;
303276404edcSAsim Jamshed             }
303376404edcSAsim Jamshed             break;
303476404edcSAsim Jamshed 
303576404edcSAsim Jamshed         case DLT_IEEE802_11:
303676404edcSAsim Jamshed         case DLT_PRISM_HEADER:
303776404edcSAsim Jamshed         case DLT_IEEE802_11_RADIO_AVS:
303876404edcSAsim Jamshed         case DLT_IEEE802_11_RADIO:
303976404edcSAsim Jamshed         case DLT_PPI:
304076404edcSAsim Jamshed             /*
304176404edcSAsim Jamshed              * Check that we have a data frame.
304276404edcSAsim Jamshed              */
304376404edcSAsim Jamshed             b0 = gen_check_802_11_data_frame();
304476404edcSAsim Jamshed 
304576404edcSAsim Jamshed             /*
304676404edcSAsim Jamshed              * Now check for the specified link-layer type.
304776404edcSAsim Jamshed              */
304876404edcSAsim Jamshed             b1 = gen_llc_linktype(proto);
304976404edcSAsim Jamshed             gen_and(b0, b1);
305076404edcSAsim Jamshed             return b1;
305176404edcSAsim Jamshed              /*NOTREACHED*/ break;
305276404edcSAsim Jamshed 
305376404edcSAsim Jamshed         case DLT_FDDI:
305476404edcSAsim Jamshed             /*
305576404edcSAsim Jamshed              * XXX - check for asynchronous frames, as per RFC 1103.
305676404edcSAsim Jamshed              */
305776404edcSAsim Jamshed             return gen_llc_linktype(proto);
305876404edcSAsim Jamshed              /*NOTREACHED*/ break;
305976404edcSAsim Jamshed 
306076404edcSAsim Jamshed         case DLT_IEEE802:
306176404edcSAsim Jamshed             /*
306276404edcSAsim Jamshed              * XXX - check for LLC PDUs, as per IEEE 802.5.
306376404edcSAsim Jamshed              */
306476404edcSAsim Jamshed             return gen_llc_linktype(proto);
306576404edcSAsim Jamshed              /*NOTREACHED*/ break;
306676404edcSAsim Jamshed 
306776404edcSAsim Jamshed         case DLT_ATM_RFC1483:
306876404edcSAsim Jamshed         case DLT_ATM_CLIP:
306976404edcSAsim Jamshed         case DLT_IP_OVER_FC:
307076404edcSAsim Jamshed             return gen_llc_linktype(proto);
307176404edcSAsim Jamshed              /*NOTREACHED*/ break;
307276404edcSAsim Jamshed 
307376404edcSAsim Jamshed         case DLT_SUNATM:
307476404edcSAsim Jamshed             /*
307576404edcSAsim Jamshed              * If "is_lane" is set, check for a LANE-encapsulated
307676404edcSAsim Jamshed              * version of this protocol, otherwise check for an
307776404edcSAsim Jamshed              * LLC-encapsulated version of this protocol.
307876404edcSAsim Jamshed              *
307976404edcSAsim Jamshed              * We assume LANE means Ethernet, not Token Ring.
308076404edcSAsim Jamshed              */
308176404edcSAsim Jamshed             if (is_lane)
308276404edcSAsim Jamshed             {
308376404edcSAsim Jamshed                 /*
308476404edcSAsim Jamshed                  * Check that the packet doesn't begin with an
308576404edcSAsim Jamshed                  * LE Control marker.  (We've already generated
308676404edcSAsim Jamshed                  * a test for LANE.)
308776404edcSAsim Jamshed                  */
308876404edcSAsim Jamshed                 b0 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
308976404edcSAsim Jamshed                 gen_not(b0);
309076404edcSAsim Jamshed 
309176404edcSAsim Jamshed                 /*
309276404edcSAsim Jamshed                  * Now generate an Ethernet test.
309376404edcSAsim Jamshed                  */
309476404edcSAsim Jamshed                 b1 = gen_ether_linktype(proto);
309576404edcSAsim Jamshed                 gen_and(b0, b1);
309676404edcSAsim Jamshed                 return b1;
309776404edcSAsim Jamshed             }
309876404edcSAsim Jamshed             else
309976404edcSAsim Jamshed             {
310076404edcSAsim Jamshed                 /*
310176404edcSAsim Jamshed                  * Check for LLC encapsulation and then check the
310276404edcSAsim Jamshed                  * protocol.
310376404edcSAsim Jamshed                  */
310476404edcSAsim Jamshed                 b0 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
310576404edcSAsim Jamshed                 b1 = gen_llc_linktype(proto);
310676404edcSAsim Jamshed                 gen_and(b0, b1);
310776404edcSAsim Jamshed                 return b1;
310876404edcSAsim Jamshed             }
310976404edcSAsim Jamshed              /*NOTREACHED*/ break;
311076404edcSAsim Jamshed 
311176404edcSAsim Jamshed         case DLT_LINUX_SLL:
311276404edcSAsim Jamshed             return gen_linux_sll_linktype(proto);
311376404edcSAsim Jamshed              /*NOTREACHED*/ break;
311476404edcSAsim Jamshed 
311576404edcSAsim Jamshed         case DLT_SLIP:
311676404edcSAsim Jamshed         case DLT_SLIP_BSDOS:
311776404edcSAsim Jamshed         case DLT_RAW:
311876404edcSAsim Jamshed             /*
311976404edcSAsim Jamshed              * These types don't provide any type field; packets
312076404edcSAsim Jamshed              * are always IPv4 or IPv6.
312176404edcSAsim Jamshed              *
312276404edcSAsim Jamshed              * XXX - for IPv4, check for a version number of 4, and,
312376404edcSAsim Jamshed              * for IPv6, check for a version number of 6?
312476404edcSAsim Jamshed              */
312576404edcSAsim Jamshed             switch (proto)
312676404edcSAsim Jamshed             {
312776404edcSAsim Jamshed 
312876404edcSAsim Jamshed                 case ETHERTYPE_IP:
312976404edcSAsim Jamshed                     /* Check for a version number of 4. */
313076404edcSAsim Jamshed                     return gen_mcmp(OR_LINK, 0, BPF_B, 0x40, 0xF0);
313176404edcSAsim Jamshed #ifdef INET6
313276404edcSAsim Jamshed                 case ETHERTYPE_IPV6:
313376404edcSAsim Jamshed                     /* Check for a version number of 6. */
313476404edcSAsim Jamshed                     return gen_mcmp(OR_LINK, 0, BPF_B, 0x60, 0xF0);
313576404edcSAsim Jamshed #endif
313676404edcSAsim Jamshed 
313776404edcSAsim Jamshed                 default:
313876404edcSAsim Jamshed                     return gen_false(); /* always false */
313976404edcSAsim Jamshed             }
314076404edcSAsim Jamshed              /*NOTREACHED*/ break;
314176404edcSAsim Jamshed 
314276404edcSAsim Jamshed         case DLT_IPV4:
314376404edcSAsim Jamshed             /*
314476404edcSAsim Jamshed              * Raw IPv4, so no type field.
314576404edcSAsim Jamshed              */
314676404edcSAsim Jamshed             if (proto == ETHERTYPE_IP)
314776404edcSAsim Jamshed                 return gen_true();  /* always true */
314876404edcSAsim Jamshed 
314976404edcSAsim Jamshed             /* Checking for something other than IPv4; always false */
315076404edcSAsim Jamshed             return gen_false();
315176404edcSAsim Jamshed              /*NOTREACHED*/ break;
315276404edcSAsim Jamshed 
315376404edcSAsim Jamshed         case DLT_IPV6:
315476404edcSAsim Jamshed             /*
315576404edcSAsim Jamshed              * Raw IPv6, so no type field.
315676404edcSAsim Jamshed              */
315776404edcSAsim Jamshed #ifdef INET6
315876404edcSAsim Jamshed             if (proto == ETHERTYPE_IPV6)
315976404edcSAsim Jamshed                 return gen_true();  /* always true */
316076404edcSAsim Jamshed #endif
316176404edcSAsim Jamshed 
316276404edcSAsim Jamshed             /* Checking for something other than IPv6; always false */
316376404edcSAsim Jamshed             return gen_false();
316476404edcSAsim Jamshed              /*NOTREACHED*/ break;
316576404edcSAsim Jamshed 
316676404edcSAsim Jamshed         case DLT_PPP:
316776404edcSAsim Jamshed         case DLT_PPP_PPPD:
316876404edcSAsim Jamshed         case DLT_PPP_SERIAL:
316976404edcSAsim Jamshed         case DLT_PPP_ETHER:
317076404edcSAsim Jamshed             /*
317176404edcSAsim Jamshed              * We use Ethernet protocol types inside libpcap;
317276404edcSAsim Jamshed              * map them to the corresponding PPP protocol types.
317376404edcSAsim Jamshed              */
317476404edcSAsim Jamshed             proto = ethertype_to_ppptype(proto);
317576404edcSAsim Jamshed             return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32) proto);
317676404edcSAsim Jamshed              /*NOTREACHED*/ break;
317776404edcSAsim Jamshed 
317876404edcSAsim Jamshed         case DLT_PPP_BSDOS:
317976404edcSAsim Jamshed             /*
318076404edcSAsim Jamshed              * We use Ethernet protocol types inside libpcap;
318176404edcSAsim Jamshed              * map them to the corresponding PPP protocol types.
318276404edcSAsim Jamshed              */
318376404edcSAsim Jamshed             switch (proto)
318476404edcSAsim Jamshed             {
318576404edcSAsim Jamshed 
318676404edcSAsim Jamshed                 case ETHERTYPE_IP:
318776404edcSAsim Jamshed                     /*
318876404edcSAsim Jamshed                      * Also check for Van Jacobson-compressed IP.
318976404edcSAsim Jamshed                      * XXX - do this for other forms of PPP?
319076404edcSAsim Jamshed                      */
319176404edcSAsim Jamshed                     b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_IP);
319276404edcSAsim Jamshed                     b1 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJC);
319376404edcSAsim Jamshed                     gen_or(b0, b1);
319476404edcSAsim Jamshed                     b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, PPP_VJNC);
319576404edcSAsim Jamshed                     gen_or(b1, b0);
319676404edcSAsim Jamshed                     return b0;
319776404edcSAsim Jamshed 
319876404edcSAsim Jamshed                 default:
319976404edcSAsim Jamshed                     proto = ethertype_to_ppptype(proto);
320076404edcSAsim Jamshed                     return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32) proto);
320176404edcSAsim Jamshed             }
320276404edcSAsim Jamshed              /*NOTREACHED*/ break;
320376404edcSAsim Jamshed 
320476404edcSAsim Jamshed         case DLT_NULL:
320576404edcSAsim Jamshed         case DLT_LOOP:
320676404edcSAsim Jamshed         case DLT_ENC:
320776404edcSAsim Jamshed             /*
320876404edcSAsim Jamshed              * For DLT_NULL, the link-layer header is a 32-bit
320976404edcSAsim Jamshed              * word containing an AF_ value in *host* byte order,
321076404edcSAsim Jamshed              * and for DLT_ENC, the link-layer header begins
321176404edcSAsim Jamshed              * with a 32-bit work containing an AF_ value in
321276404edcSAsim Jamshed              * host byte order.
321376404edcSAsim Jamshed              *
321476404edcSAsim Jamshed              * In addition, if we're reading a saved capture file,
321576404edcSAsim Jamshed              * the host byte order in the capture may not be the
321676404edcSAsim Jamshed              * same as the host byte order on this machine.
321776404edcSAsim Jamshed              *
321876404edcSAsim Jamshed              * For DLT_LOOP, the link-layer header is a 32-bit
321976404edcSAsim Jamshed              * word containing an AF_ value in *network* byte order.
322076404edcSAsim Jamshed              *
322176404edcSAsim Jamshed              * XXX - AF_ values may, unfortunately, be platform-
322276404edcSAsim Jamshed              * dependent; for example, FreeBSD's AF_INET6 is 24
322376404edcSAsim Jamshed              * whilst NetBSD's and OpenBSD's is 26.
322476404edcSAsim Jamshed              *
322576404edcSAsim Jamshed              * This means that, when reading a capture file, just
322676404edcSAsim Jamshed              * checking for our AF_INET6 value won't work if the
322776404edcSAsim Jamshed              * capture file came from another OS.
322876404edcSAsim Jamshed              */
322976404edcSAsim Jamshed             switch (proto)
323076404edcSAsim Jamshed             {
323176404edcSAsim Jamshed 
323276404edcSAsim Jamshed                 case ETHERTYPE_IP:
323376404edcSAsim Jamshed                     proto = AF_INET;
323476404edcSAsim Jamshed                     break;
323576404edcSAsim Jamshed 
323676404edcSAsim Jamshed #ifdef INET6
323776404edcSAsim Jamshed                 case ETHERTYPE_IPV6:
323876404edcSAsim Jamshed                     proto = AF_INET6;
323976404edcSAsim Jamshed                     break;
324076404edcSAsim Jamshed #endif
324176404edcSAsim Jamshed 
324276404edcSAsim Jamshed                 default:
324376404edcSAsim Jamshed                     /*
324476404edcSAsim Jamshed                      * Not a type on which we support filtering.
324576404edcSAsim Jamshed                      * XXX - support those that have AF_ values
324676404edcSAsim Jamshed                      * #defined on this platform, at least?
324776404edcSAsim Jamshed                      */
324876404edcSAsim Jamshed                     return gen_false();
324976404edcSAsim Jamshed             }
325076404edcSAsim Jamshed 
325176404edcSAsim Jamshed             if (linktype == DLT_NULL || linktype == DLT_ENC)
325276404edcSAsim Jamshed             {
325376404edcSAsim Jamshed                 /*
325476404edcSAsim Jamshed                  * The AF_ value is in host byte order, but
325576404edcSAsim Jamshed                  * the BPF interpreter will convert it to
325676404edcSAsim Jamshed                  * network byte order.
325776404edcSAsim Jamshed                  *
325876404edcSAsim Jamshed                  * If this is a save file, and it's from a
325976404edcSAsim Jamshed                  * machine with the opposite byte order to
326076404edcSAsim Jamshed                  * ours, we byte-swap the AF_ value.
326176404edcSAsim Jamshed                  *
326276404edcSAsim Jamshed                  * Then we run it through "htonl()", and
326376404edcSAsim Jamshed                  * generate code to compare against the result.
326476404edcSAsim Jamshed                  */
326576404edcSAsim Jamshed                 //if (bpf_pcap->sf.rfile != NULL && bpf_pcap->sf.swapped)
326676404edcSAsim Jamshed                 //    proto = SWAPLONG(proto);
326776404edcSAsim Jamshed                 proto = htonl(proto);
326876404edcSAsim Jamshed             }
326976404edcSAsim Jamshed             return (gen_cmp(OR_LINK, 0, BPF_W, (bpf_int32) proto));
327076404edcSAsim Jamshed 
327176404edcSAsim Jamshed #ifdef HAVE_NET_PFVAR_H
327276404edcSAsim Jamshed         case DLT_PFLOG:
327376404edcSAsim Jamshed             /*
327476404edcSAsim Jamshed              * af field is host byte order in contrast to the rest of
327576404edcSAsim Jamshed              * the packet.
327676404edcSAsim Jamshed              */
327776404edcSAsim Jamshed             if (proto == ETHERTYPE_IP)
327876404edcSAsim Jamshed                 return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af), BPF_B, (bpf_int32) AF_INET));
327976404edcSAsim Jamshed #ifdef INET6
328076404edcSAsim Jamshed             else if (proto == ETHERTYPE_IPV6)
328176404edcSAsim Jamshed                 return (gen_cmp(OR_LINK, offsetof(struct pfloghdr, af), BPF_B, (bpf_int32) AF_INET6));
328276404edcSAsim Jamshed #endif /* INET6 */
328376404edcSAsim Jamshed             else
328476404edcSAsim Jamshed                 return gen_false();
328576404edcSAsim Jamshed              /*NOTREACHED*/ break;
328676404edcSAsim Jamshed #endif /* HAVE_NET_PFVAR_H */
328776404edcSAsim Jamshed 
328876404edcSAsim Jamshed         case DLT_ARCNET:
328976404edcSAsim Jamshed         case DLT_ARCNET_LINUX:
329076404edcSAsim Jamshed             /*
329176404edcSAsim Jamshed              * XXX should we check for first fragment if the protocol
329276404edcSAsim Jamshed              * uses PHDS?
329376404edcSAsim Jamshed              */
329476404edcSAsim Jamshed             switch (proto)
329576404edcSAsim Jamshed             {
329676404edcSAsim Jamshed 
329776404edcSAsim Jamshed                 default:
329876404edcSAsim Jamshed                     return gen_false();
329976404edcSAsim Jamshed 
330076404edcSAsim Jamshed #ifdef INET6
330176404edcSAsim Jamshed                 case ETHERTYPE_IPV6:
330276404edcSAsim Jamshed                     return (gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32) ARCTYPE_INET6));
330376404edcSAsim Jamshed #endif /* INET6 */
330476404edcSAsim Jamshed 
330576404edcSAsim Jamshed                 case ETHERTYPE_IP:
330676404edcSAsim Jamshed                     b0 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32) ARCTYPE_IP);
330776404edcSAsim Jamshed                     b1 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32) ARCTYPE_IP_OLD);
330876404edcSAsim Jamshed                     gen_or(b0, b1);
330976404edcSAsim Jamshed                     return (b1);
331076404edcSAsim Jamshed 
331176404edcSAsim Jamshed                 case ETHERTYPE_ARP:
331276404edcSAsim Jamshed                     b0 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32) ARCTYPE_ARP);
331376404edcSAsim Jamshed                     b1 = gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32) ARCTYPE_ARP_OLD);
331476404edcSAsim Jamshed                     gen_or(b0, b1);
331576404edcSAsim Jamshed                     return (b1);
331676404edcSAsim Jamshed 
331776404edcSAsim Jamshed                 case ETHERTYPE_REVARP:
331876404edcSAsim Jamshed                     return (gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32) ARCTYPE_REVARP));
331976404edcSAsim Jamshed 
332076404edcSAsim Jamshed                 case ETHERTYPE_ATALK:
332176404edcSAsim Jamshed                     return (gen_cmp(OR_LINK, off_linktype, BPF_B, (bpf_int32) ARCTYPE_ATALK));
332276404edcSAsim Jamshed             }
332376404edcSAsim Jamshed              /*NOTREACHED*/ break;
332476404edcSAsim Jamshed 
332576404edcSAsim Jamshed         case DLT_LTALK:
332676404edcSAsim Jamshed             switch (proto)
332776404edcSAsim Jamshed             {
332876404edcSAsim Jamshed                 case ETHERTYPE_ATALK:
332976404edcSAsim Jamshed                     return gen_true();
333076404edcSAsim Jamshed                 default:
333176404edcSAsim Jamshed                     return gen_false();
333276404edcSAsim Jamshed             }
333376404edcSAsim Jamshed              /*NOTREACHED*/ break;
333476404edcSAsim Jamshed 
333576404edcSAsim Jamshed         case DLT_FRELAY:
333676404edcSAsim Jamshed             /*
333776404edcSAsim Jamshed              * XXX - assumes a 2-byte Frame Relay header with
333876404edcSAsim Jamshed              * DLCI and flags.  What if the address is longer?
333976404edcSAsim Jamshed              */
334076404edcSAsim Jamshed             switch (proto)
334176404edcSAsim Jamshed             {
334276404edcSAsim Jamshed 
334376404edcSAsim Jamshed                 case ETHERTYPE_IP:
334476404edcSAsim Jamshed                     /*
334576404edcSAsim Jamshed                      * Check for the special NLPID for IP.
334676404edcSAsim Jamshed                      */
334776404edcSAsim Jamshed                     return gen_cmp(OR_LINK, 2, BPF_H, (0x03 << 8) | 0xcc);
334876404edcSAsim Jamshed 
334976404edcSAsim Jamshed #ifdef INET6
335076404edcSAsim Jamshed                 case ETHERTYPE_IPV6:
335176404edcSAsim Jamshed                     /*
335276404edcSAsim Jamshed                      * Check for the special NLPID for IPv6.
335376404edcSAsim Jamshed                      */
335476404edcSAsim Jamshed                     return gen_cmp(OR_LINK, 2, BPF_H, (0x03 << 8) | 0x8e);
335576404edcSAsim Jamshed #endif
335676404edcSAsim Jamshed 
335776404edcSAsim Jamshed                 case LLCSAP_ISONS:
335876404edcSAsim Jamshed                     /*
335976404edcSAsim Jamshed                      * Check for several OSI protocols.
336076404edcSAsim Jamshed                      *
336176404edcSAsim Jamshed                      * Frame Relay packets typically have an OSI
336276404edcSAsim Jamshed                      * NLPID at the beginning; we check for each
336376404edcSAsim Jamshed                      * of them.
336476404edcSAsim Jamshed                      *
336576404edcSAsim Jamshed                      * What we check for is the NLPID and a frame
336676404edcSAsim Jamshed                      * control field of UI, i.e. 0x03 followed
336776404edcSAsim Jamshed                      * by the NLPID.
336876404edcSAsim Jamshed                      */
336976404edcSAsim Jamshed                     b0 = gen_cmp(OR_LINK, 2, BPF_H, (0x03 << 8) | ISO8473_CLNP);
337076404edcSAsim Jamshed                     b1 = gen_cmp(OR_LINK, 2, BPF_H, (0x03 << 8) | ISO9542_ESIS);
337176404edcSAsim Jamshed                     b2 = gen_cmp(OR_LINK, 2, BPF_H, (0x03 << 8) | ISO10589_ISIS);
337276404edcSAsim Jamshed                     gen_or(b1, b2);
337376404edcSAsim Jamshed                     gen_or(b0, b2);
337476404edcSAsim Jamshed                     return b2;
337576404edcSAsim Jamshed 
337676404edcSAsim Jamshed                 default:
337776404edcSAsim Jamshed                     return gen_false();
337876404edcSAsim Jamshed             }
337976404edcSAsim Jamshed              /*NOTREACHED*/ break;
338076404edcSAsim Jamshed 
338176404edcSAsim Jamshed         case DLT_MFR:
338276404edcSAsim Jamshed             bpf_error("Multi-link Frame Relay link-layer type filtering not implemented");
338376404edcSAsim Jamshed 
338476404edcSAsim Jamshed         case DLT_JUNIPER_MFR:
338576404edcSAsim Jamshed         case DLT_JUNIPER_MLFR:
338676404edcSAsim Jamshed         case DLT_JUNIPER_MLPPP:
338776404edcSAsim Jamshed         case DLT_JUNIPER_ATM1:
338876404edcSAsim Jamshed         case DLT_JUNIPER_ATM2:
338976404edcSAsim Jamshed         case DLT_JUNIPER_PPPOE:
339076404edcSAsim Jamshed         case DLT_JUNIPER_PPPOE_ATM:
339176404edcSAsim Jamshed         case DLT_JUNIPER_GGSN:
339276404edcSAsim Jamshed         case DLT_JUNIPER_ES:
339376404edcSAsim Jamshed         case DLT_JUNIPER_MONITOR:
339476404edcSAsim Jamshed         case DLT_JUNIPER_SERVICES:
339576404edcSAsim Jamshed         case DLT_JUNIPER_ETHER:
339676404edcSAsim Jamshed         case DLT_JUNIPER_PPP:
339776404edcSAsim Jamshed         case DLT_JUNIPER_FRELAY:
339876404edcSAsim Jamshed         case DLT_JUNIPER_CHDLC:
339976404edcSAsim Jamshed         case DLT_JUNIPER_VP:
340076404edcSAsim Jamshed         case DLT_JUNIPER_ST:
340176404edcSAsim Jamshed         case DLT_JUNIPER_ISM:
340276404edcSAsim Jamshed             /* just lets verify the magic number for now -
340376404edcSAsim Jamshed              * on ATM we may have up to 6 different encapsulations on the wire
340476404edcSAsim Jamshed              * and need a lot of heuristics to figure out that the payload
340576404edcSAsim Jamshed              * might be;
340676404edcSAsim Jamshed              *
340776404edcSAsim Jamshed              * FIXME encapsulation specific BPF_ filters
340876404edcSAsim Jamshed              */
340976404edcSAsim Jamshed             return gen_mcmp(OR_LINK, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
341076404edcSAsim Jamshed 
341176404edcSAsim Jamshed         case DLT_IPNET:
341276404edcSAsim Jamshed             return gen_ipnet_linktype(proto);
341376404edcSAsim Jamshed 
341476404edcSAsim Jamshed         case DLT_LINUX_IRDA:
341576404edcSAsim Jamshed             bpf_error("IrDA link-layer type filtering not implemented");
341676404edcSAsim Jamshed 
341776404edcSAsim Jamshed         case DLT_DOCSIS:
341876404edcSAsim Jamshed             bpf_error("DOCSIS link-layer type filtering not implemented");
341976404edcSAsim Jamshed 
342076404edcSAsim Jamshed         case DLT_MTP2:
342176404edcSAsim Jamshed         case DLT_MTP2_WITH_PHDR:
342276404edcSAsim Jamshed             bpf_error("MTP2 link-layer type filtering not implemented");
342376404edcSAsim Jamshed 
342476404edcSAsim Jamshed         case DLT_ERF:
342576404edcSAsim Jamshed             bpf_error("ERF link-layer type filtering not implemented");
342676404edcSAsim Jamshed 
342776404edcSAsim Jamshed #ifdef DLT_PFSYNC
342876404edcSAsim Jamshed         case DLT_PFSYNC:
342976404edcSAsim Jamshed             bpf_error("PFSYNC link-layer type filtering not implemented");
343076404edcSAsim Jamshed #endif
343176404edcSAsim Jamshed 
343276404edcSAsim Jamshed         case DLT_LINUX_LAPD:
343376404edcSAsim Jamshed             bpf_error("LAPD link-layer type filtering not implemented");
343476404edcSAsim Jamshed 
343576404edcSAsim Jamshed         case DLT_USB:
343676404edcSAsim Jamshed         case DLT_USB_LINUX:
343776404edcSAsim Jamshed         case DLT_USB_LINUX_MMAPPED:
343876404edcSAsim Jamshed             bpf_error("USB link-layer type filtering not implemented");
343976404edcSAsim Jamshed 
344076404edcSAsim Jamshed         case DLT_BLUETOOTH_HCI_H4:
344176404edcSAsim Jamshed         case DLT_BLUETOOTH_HCI_H4_WITH_PHDR:
344276404edcSAsim Jamshed             bpf_error("Bluetooth link-layer type filtering not implemented");
344376404edcSAsim Jamshed 
344476404edcSAsim Jamshed         case DLT_CAN20B:
344576404edcSAsim Jamshed         case DLT_CAN_SOCKETCAN:
344676404edcSAsim Jamshed             bpf_error("CAN link-layer type filtering not implemented");
344776404edcSAsim Jamshed 
344876404edcSAsim Jamshed         case DLT_IEEE802_15_4:
344976404edcSAsim Jamshed         case DLT_IEEE802_15_4_LINUX:
345076404edcSAsim Jamshed         case DLT_IEEE802_15_4_NONASK_PHY:
345176404edcSAsim Jamshed             bpf_error("IEEE 802.15.4 link-layer type filtering not implemented");
345276404edcSAsim Jamshed 
345376404edcSAsim Jamshed         case DLT_IEEE802_16_MAC_CPS_RADIO:
345476404edcSAsim Jamshed             bpf_error("IEEE 802.16 link-layer type filtering not implemented");
345576404edcSAsim Jamshed 
345676404edcSAsim Jamshed         case DLT_SITA:
345776404edcSAsim Jamshed             bpf_error("SITA link-layer type filtering not implemented");
345876404edcSAsim Jamshed 
345976404edcSAsim Jamshed         case DLT_RAIF1:
346076404edcSAsim Jamshed             bpf_error("RAIF1 link-layer type filtering not implemented");
346176404edcSAsim Jamshed 
346276404edcSAsim Jamshed         case DLT_IPMB:
346376404edcSAsim Jamshed             bpf_error("IPMB link-layer type filtering not implemented");
346476404edcSAsim Jamshed 
346576404edcSAsim Jamshed         case DLT_AX25_KISS:
346676404edcSAsim Jamshed             bpf_error("AX.25 link-layer type filtering not implemented");
346776404edcSAsim Jamshed     }
346876404edcSAsim Jamshed 
346976404edcSAsim Jamshed     /*
347076404edcSAsim Jamshed      * All the types that have no encapsulation should either be
347176404edcSAsim Jamshed      * handled as DLT_SLIP, DLT_SLIP_BSDOS, and DLT_RAW are, if
347276404edcSAsim Jamshed      * all packets are IP packets, or should be handled in some
347376404edcSAsim Jamshed      * special case, if none of them are (if some are and some
347476404edcSAsim Jamshed      * aren't, the lack of encapsulation is a problem, as we'd
347576404edcSAsim Jamshed      * have to find some other way of determining the packet type).
347676404edcSAsim Jamshed      *
347776404edcSAsim Jamshed      * Therefore, if "off_linktype" is -1, there's an error.
347876404edcSAsim Jamshed      */
347976404edcSAsim Jamshed     if (off_linktype == (u_int) - 1)
348076404edcSAsim Jamshed         abort();
348176404edcSAsim Jamshed 
348276404edcSAsim Jamshed     /*
348376404edcSAsim Jamshed      * Any type not handled above should always have an Ethernet
348476404edcSAsim Jamshed      * type at an offset of "off_linktype".
348576404edcSAsim Jamshed      */
348676404edcSAsim Jamshed     return gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32) proto);
348776404edcSAsim Jamshed }
348876404edcSAsim Jamshed 
348976404edcSAsim Jamshed /*
349076404edcSAsim Jamshed  * Check for an LLC SNAP packet with a given organization code and
349176404edcSAsim Jamshed  * protocol type; we check the entire contents of the 802.2 LLC and
349276404edcSAsim Jamshed  * snap headers, checking for DSAP and SSAP of SNAP and a control
349376404edcSAsim Jamshed  * field of 0x03 in the LLC header, and for the specified organization
349476404edcSAsim Jamshed  * code and protocol type in the SNAP header.
349576404edcSAsim Jamshed  */
gen_snap(orgcode,ptype)349676404edcSAsim Jamshed static struct block *gen_snap(orgcode, ptype)
349776404edcSAsim Jamshed      bpf_u_int32 orgcode;
349876404edcSAsim Jamshed      bpf_u_int32 ptype;
349976404edcSAsim Jamshed {
350076404edcSAsim Jamshed     u_char snapblock[8];
350176404edcSAsim Jamshed 
350276404edcSAsim Jamshed     snapblock[0] = LLCSAP_SNAP; /* DSAP = SNAP */
350376404edcSAsim Jamshed     snapblock[1] = LLCSAP_SNAP; /* SSAP = SNAP */
350476404edcSAsim Jamshed     snapblock[2] = 0x03;        /* control = UI */
350576404edcSAsim Jamshed     snapblock[3] = (orgcode >> 16); /* upper 8 bits of organization code */
350676404edcSAsim Jamshed     snapblock[4] = (orgcode >> 8);  /* middle 8 bits of organization code */
350776404edcSAsim Jamshed     snapblock[5] = (orgcode >> 0);  /* lower 8 bits of organization code */
350876404edcSAsim Jamshed     snapblock[6] = (ptype >> 8);    /* upper 8 bits of protocol type */
350976404edcSAsim Jamshed     snapblock[7] = (ptype >> 0);    /* lower 8 bits of protocol type */
351076404edcSAsim Jamshed     return gen_bcmp(OR_MACPL, 0, 8, snapblock);
351176404edcSAsim Jamshed }
351276404edcSAsim Jamshed 
351376404edcSAsim Jamshed /*
351476404edcSAsim Jamshed  * Generate code to match a particular packet type, for link-layer types
351576404edcSAsim Jamshed  * using 802.2 LLC headers.
351676404edcSAsim Jamshed  *
351776404edcSAsim Jamshed  * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used
351876404edcSAsim Jamshed  * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues.
351976404edcSAsim Jamshed  *
352076404edcSAsim Jamshed  * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
352176404edcSAsim Jamshed  * value, if <= ETHERMTU.  We use that to determine whether to
352276404edcSAsim Jamshed  * match the DSAP or both DSAP and LSAP or to check the OUI and
352376404edcSAsim Jamshed  * protocol ID in a SNAP header.
352476404edcSAsim Jamshed  */
gen_llc_linktype(proto)352576404edcSAsim Jamshed static struct block *gen_llc_linktype(proto)
352676404edcSAsim Jamshed      int proto;
352776404edcSAsim Jamshed {
352876404edcSAsim Jamshed     /*
352976404edcSAsim Jamshed      * XXX - handle token-ring variable-length header.
353076404edcSAsim Jamshed      */
353176404edcSAsim Jamshed     switch (proto)
353276404edcSAsim Jamshed     {
353376404edcSAsim Jamshed 
353476404edcSAsim Jamshed         case LLCSAP_IP:
353576404edcSAsim Jamshed         case LLCSAP_ISONS:
353676404edcSAsim Jamshed         case LLCSAP_NETBEUI:
353776404edcSAsim Jamshed             /*
353876404edcSAsim Jamshed              * XXX - should we check both the DSAP and the
353976404edcSAsim Jamshed              * SSAP, like this, or should we check just the
354076404edcSAsim Jamshed              * DSAP, as we do for other types <= ETHERMTU
354176404edcSAsim Jamshed              * (i.e., other SAP values)?
354276404edcSAsim Jamshed              */
354376404edcSAsim Jamshed             return gen_cmp(OR_MACPL, 0, BPF_H, (bpf_u_int32) ((proto << 8) | proto));
354476404edcSAsim Jamshed 
354576404edcSAsim Jamshed         case LLCSAP_IPX:
354676404edcSAsim Jamshed             /*
354776404edcSAsim Jamshed              * XXX - are there ever SNAP frames for IPX on
354876404edcSAsim Jamshed              * non-Ethernet 802.x networks?
354976404edcSAsim Jamshed              */
355076404edcSAsim Jamshed             return gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32) LLCSAP_IPX);
355176404edcSAsim Jamshed 
355276404edcSAsim Jamshed         case ETHERTYPE_ATALK:
355376404edcSAsim Jamshed             /*
355476404edcSAsim Jamshed              * 802.2-encapsulated ETHERTYPE_ATALK packets are
355576404edcSAsim Jamshed              * SNAP packets with an organization code of
355676404edcSAsim Jamshed              * 0x080007 (Apple, for Appletalk) and a protocol
355776404edcSAsim Jamshed              * type of ETHERTYPE_ATALK (Appletalk).
355876404edcSAsim Jamshed              *
355976404edcSAsim Jamshed              * XXX - check for an organization code of
356076404edcSAsim Jamshed              * encapsulated Ethernet as well?
356176404edcSAsim Jamshed              */
356276404edcSAsim Jamshed             return gen_snap(0x080007, ETHERTYPE_ATALK);
356376404edcSAsim Jamshed 
356476404edcSAsim Jamshed         default:
356576404edcSAsim Jamshed             /*
356676404edcSAsim Jamshed              * XXX - we don't have to check for IPX 802.3
356776404edcSAsim Jamshed              * here, but should we check for the IPX Ethertype?
356876404edcSAsim Jamshed              */
356976404edcSAsim Jamshed             if (proto <= ETHERMTU)
357076404edcSAsim Jamshed             {
357176404edcSAsim Jamshed                 /*
357276404edcSAsim Jamshed                  * This is an LLC SAP value, so check
357376404edcSAsim Jamshed                  * the DSAP.
357476404edcSAsim Jamshed                  */
357576404edcSAsim Jamshed                 return gen_cmp(OR_MACPL, 0, BPF_B, (bpf_int32) proto);
357676404edcSAsim Jamshed             }
357776404edcSAsim Jamshed             else
357876404edcSAsim Jamshed             {
357976404edcSAsim Jamshed                 /*
358076404edcSAsim Jamshed                  * This is an Ethernet type; we assume that it's
358176404edcSAsim Jamshed                  * unlikely that it'll appear in the right place
358276404edcSAsim Jamshed                  * at random, and therefore check only the
358376404edcSAsim Jamshed                  * location that would hold the Ethernet type
358476404edcSAsim Jamshed                  * in a SNAP frame with an organization code of
358576404edcSAsim Jamshed                  * 0x000000 (encapsulated Ethernet).
358676404edcSAsim Jamshed                  *
358776404edcSAsim Jamshed                  * XXX - if we were to check for the SNAP DSAP and
358876404edcSAsim Jamshed                  * LSAP, as per XXX, and were also to check for an
358976404edcSAsim Jamshed                  * organization code of 0x000000 (encapsulated
359076404edcSAsim Jamshed                  * Ethernet), we'd do
359176404edcSAsim Jamshed                  *
359276404edcSAsim Jamshed                  *  return gen_snap(0x000000, proto);
359376404edcSAsim Jamshed                  *
359476404edcSAsim Jamshed                  * here; for now, we don't, as per the above.
359576404edcSAsim Jamshed                  * I don't know whether it's worth the extra CPU
359676404edcSAsim Jamshed                  * time to do the right check or not.
359776404edcSAsim Jamshed                  */
359876404edcSAsim Jamshed                 return gen_cmp(OR_MACPL, 6, BPF_H, (bpf_int32) proto);
359976404edcSAsim Jamshed             }
360076404edcSAsim Jamshed     }
360176404edcSAsim Jamshed }
360276404edcSAsim Jamshed 
gen_hostop(addr,mask,dir,proto,src_off,dst_off)360376404edcSAsim Jamshed static struct block *gen_hostop(addr, mask, dir, proto, src_off, dst_off)
360476404edcSAsim Jamshed      bpf_u_int32 addr;
360576404edcSAsim Jamshed      bpf_u_int32 mask;
360676404edcSAsim Jamshed      int dir, proto;
360776404edcSAsim Jamshed      u_int src_off, dst_off;
360876404edcSAsim Jamshed {
360976404edcSAsim Jamshed     struct block *b0, *b1;
361076404edcSAsim Jamshed     u_int offset;
361176404edcSAsim Jamshed 
361276404edcSAsim Jamshed     switch (dir)
361376404edcSAsim Jamshed     {
361476404edcSAsim Jamshed 
361576404edcSAsim Jamshed         case Q_SRC:
361676404edcSAsim Jamshed             offset = src_off;
361776404edcSAsim Jamshed             break;
361876404edcSAsim Jamshed 
361976404edcSAsim Jamshed         case Q_DST:
362076404edcSAsim Jamshed             offset = dst_off;
362176404edcSAsim Jamshed             break;
362276404edcSAsim Jamshed 
362376404edcSAsim Jamshed         case Q_AND:
362476404edcSAsim Jamshed             b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
362576404edcSAsim Jamshed             b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
362676404edcSAsim Jamshed             gen_and(b0, b1);
362776404edcSAsim Jamshed             return b1;
362876404edcSAsim Jamshed 
362976404edcSAsim Jamshed         case Q_OR:
363076404edcSAsim Jamshed         case Q_DEFAULT:
363176404edcSAsim Jamshed             b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off);
363276404edcSAsim Jamshed             b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off);
363376404edcSAsim Jamshed             gen_or(b0, b1);
363476404edcSAsim Jamshed             return b1;
363576404edcSAsim Jamshed 
363676404edcSAsim Jamshed         default:
363776404edcSAsim Jamshed             abort();
363876404edcSAsim Jamshed     }
363976404edcSAsim Jamshed     b0 = gen_linktype(proto);
364076404edcSAsim Jamshed     b1 = gen_mcmp(OR_NET, offset, BPF_W, (bpf_int32) addr, mask);
364176404edcSAsim Jamshed     gen_and(b0, b1);
364276404edcSAsim Jamshed     return b1;
364376404edcSAsim Jamshed }
364476404edcSAsim Jamshed 
364576404edcSAsim Jamshed #ifdef INET6
gen_hostop6(addr,mask,dir,proto,src_off,dst_off)364676404edcSAsim Jamshed static struct block *gen_hostop6(addr, mask, dir, proto, src_off, dst_off)
364776404edcSAsim Jamshed      struct in6_addr *addr;
364876404edcSAsim Jamshed      struct in6_addr *mask;
364976404edcSAsim Jamshed      int dir, proto;
365076404edcSAsim Jamshed      u_int src_off, dst_off;
365176404edcSAsim Jamshed {
365276404edcSAsim Jamshed     struct block *b0, *b1;
365376404edcSAsim Jamshed     u_int offset;
365476404edcSAsim Jamshed     u_int32_t *a, *m;
365576404edcSAsim Jamshed 
365676404edcSAsim Jamshed     switch (dir)
365776404edcSAsim Jamshed     {
365876404edcSAsim Jamshed 
365976404edcSAsim Jamshed         case Q_SRC:
366076404edcSAsim Jamshed             offset = src_off;
366176404edcSAsim Jamshed             break;
366276404edcSAsim Jamshed 
366376404edcSAsim Jamshed         case Q_DST:
366476404edcSAsim Jamshed             offset = dst_off;
366576404edcSAsim Jamshed             break;
366676404edcSAsim Jamshed 
366776404edcSAsim Jamshed         case Q_AND:
366876404edcSAsim Jamshed             b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
366976404edcSAsim Jamshed             b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
367076404edcSAsim Jamshed             gen_and(b0, b1);
367176404edcSAsim Jamshed             return b1;
367276404edcSAsim Jamshed 
367376404edcSAsim Jamshed         case Q_OR:
367476404edcSAsim Jamshed         case Q_DEFAULT:
367576404edcSAsim Jamshed             b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off);
367676404edcSAsim Jamshed             b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off);
367776404edcSAsim Jamshed             gen_or(b0, b1);
367876404edcSAsim Jamshed             return b1;
367976404edcSAsim Jamshed 
368076404edcSAsim Jamshed         default:
368176404edcSAsim Jamshed             abort();
368276404edcSAsim Jamshed     }
368376404edcSAsim Jamshed     /* this order is important */
368476404edcSAsim Jamshed     a = (u_int32_t *) addr;
368576404edcSAsim Jamshed     m = (u_int32_t *) mask;
368676404edcSAsim Jamshed     b1 = gen_mcmp(OR_NET, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
368776404edcSAsim Jamshed     b0 = gen_mcmp(OR_NET, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
368876404edcSAsim Jamshed     gen_and(b0, b1);
368976404edcSAsim Jamshed     b0 = gen_mcmp(OR_NET, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
369076404edcSAsim Jamshed     gen_and(b0, b1);
369176404edcSAsim Jamshed     b0 = gen_mcmp(OR_NET, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
369276404edcSAsim Jamshed     gen_and(b0, b1);
369376404edcSAsim Jamshed     b0 = gen_linktype(proto);
369476404edcSAsim Jamshed     gen_and(b0, b1);
369576404edcSAsim Jamshed     return b1;
369676404edcSAsim Jamshed }
369776404edcSAsim Jamshed #endif /*INET6 */
369876404edcSAsim Jamshed 
gen_ehostop(eaddr,dir)369976404edcSAsim Jamshed static struct block *gen_ehostop(eaddr, dir)
370076404edcSAsim Jamshed      register const u_char *eaddr;
370176404edcSAsim Jamshed      register int dir;
370276404edcSAsim Jamshed {
370376404edcSAsim Jamshed     register struct block *b0, *b1;
370476404edcSAsim Jamshed 
370576404edcSAsim Jamshed     switch (dir)
370676404edcSAsim Jamshed     {
370776404edcSAsim Jamshed         case Q_SRC:
370876404edcSAsim Jamshed             return gen_bcmp(OR_LINK, off_mac + 6, 6, eaddr);
370976404edcSAsim Jamshed 
371076404edcSAsim Jamshed         case Q_DST:
371176404edcSAsim Jamshed             return gen_bcmp(OR_LINK, off_mac + 0, 6, eaddr);
371276404edcSAsim Jamshed 
371376404edcSAsim Jamshed         case Q_AND:
371476404edcSAsim Jamshed             b0 = gen_ehostop(eaddr, Q_SRC);
371576404edcSAsim Jamshed             b1 = gen_ehostop(eaddr, Q_DST);
371676404edcSAsim Jamshed             gen_and(b0, b1);
371776404edcSAsim Jamshed             return b1;
371876404edcSAsim Jamshed 
371976404edcSAsim Jamshed         case Q_DEFAULT:
372076404edcSAsim Jamshed         case Q_OR:
372176404edcSAsim Jamshed             b0 = gen_ehostop(eaddr, Q_SRC);
372276404edcSAsim Jamshed             b1 = gen_ehostop(eaddr, Q_DST);
372376404edcSAsim Jamshed             gen_or(b0, b1);
372476404edcSAsim Jamshed             return b1;
372576404edcSAsim Jamshed     }
372676404edcSAsim Jamshed     abort();
372776404edcSAsim Jamshed     /* NOTREACHED */
372876404edcSAsim Jamshed }
372976404edcSAsim Jamshed 
373076404edcSAsim Jamshed /*
373176404edcSAsim Jamshed  * Like gen_ehostop, but for DLT_FDDI
373276404edcSAsim Jamshed  */
gen_fhostop(eaddr,dir)373376404edcSAsim Jamshed static struct block *gen_fhostop(eaddr, dir)
373476404edcSAsim Jamshed      register const u_char *eaddr;
373576404edcSAsim Jamshed      register int dir;
373676404edcSAsim Jamshed {
373776404edcSAsim Jamshed     struct block *b0, *b1;
373876404edcSAsim Jamshed 
373976404edcSAsim Jamshed     switch (dir)
374076404edcSAsim Jamshed     {
374176404edcSAsim Jamshed         case Q_SRC:
374276404edcSAsim Jamshed #ifdef PCAP_FDDIPAD
374376404edcSAsim Jamshed             return gen_bcmp(OR_LINK, 6 + 1 + pcap_fddipad, 6, eaddr);
374476404edcSAsim Jamshed #else
374576404edcSAsim Jamshed             return gen_bcmp(OR_LINK, 6 + 1, 6, eaddr);
374676404edcSAsim Jamshed #endif
374776404edcSAsim Jamshed 
374876404edcSAsim Jamshed         case Q_DST:
374976404edcSAsim Jamshed #ifdef PCAP_FDDIPAD
375076404edcSAsim Jamshed             return gen_bcmp(OR_LINK, 0 + 1 + pcap_fddipad, 6, eaddr);
375176404edcSAsim Jamshed #else
375276404edcSAsim Jamshed             return gen_bcmp(OR_LINK, 0 + 1, 6, eaddr);
375376404edcSAsim Jamshed #endif
375476404edcSAsim Jamshed 
375576404edcSAsim Jamshed         case Q_AND:
375676404edcSAsim Jamshed             b0 = gen_fhostop(eaddr, Q_SRC);
375776404edcSAsim Jamshed             b1 = gen_fhostop(eaddr, Q_DST);
375876404edcSAsim Jamshed             gen_and(b0, b1);
375976404edcSAsim Jamshed             return b1;
376076404edcSAsim Jamshed 
376176404edcSAsim Jamshed         case Q_DEFAULT:
376276404edcSAsim Jamshed         case Q_OR:
376376404edcSAsim Jamshed             b0 = gen_fhostop(eaddr, Q_SRC);
376476404edcSAsim Jamshed             b1 = gen_fhostop(eaddr, Q_DST);
376576404edcSAsim Jamshed             gen_or(b0, b1);
376676404edcSAsim Jamshed             return b1;
376776404edcSAsim Jamshed     }
376876404edcSAsim Jamshed     abort();
376976404edcSAsim Jamshed     /* NOTREACHED */
377076404edcSAsim Jamshed }
377176404edcSAsim Jamshed 
377276404edcSAsim Jamshed /*
377376404edcSAsim Jamshed  * Like gen_ehostop, but for DLT_IEEE802 (Token Ring)
377476404edcSAsim Jamshed  */
gen_thostop(eaddr,dir)377576404edcSAsim Jamshed static struct block *gen_thostop(eaddr, dir)
377676404edcSAsim Jamshed      register const u_char *eaddr;
377776404edcSAsim Jamshed      register int dir;
377876404edcSAsim Jamshed {
377976404edcSAsim Jamshed     register struct block *b0, *b1;
378076404edcSAsim Jamshed 
378176404edcSAsim Jamshed     switch (dir)
378276404edcSAsim Jamshed     {
378376404edcSAsim Jamshed         case Q_SRC:
378476404edcSAsim Jamshed             return gen_bcmp(OR_LINK, 8, 6, eaddr);
378576404edcSAsim Jamshed 
378676404edcSAsim Jamshed         case Q_DST:
378776404edcSAsim Jamshed             return gen_bcmp(OR_LINK, 2, 6, eaddr);
378876404edcSAsim Jamshed 
378976404edcSAsim Jamshed         case Q_AND:
379076404edcSAsim Jamshed             b0 = gen_thostop(eaddr, Q_SRC);
379176404edcSAsim Jamshed             b1 = gen_thostop(eaddr, Q_DST);
379276404edcSAsim Jamshed             gen_and(b0, b1);
379376404edcSAsim Jamshed             return b1;
379476404edcSAsim Jamshed 
379576404edcSAsim Jamshed         case Q_DEFAULT:
379676404edcSAsim Jamshed         case Q_OR:
379776404edcSAsim Jamshed             b0 = gen_thostop(eaddr, Q_SRC);
379876404edcSAsim Jamshed             b1 = gen_thostop(eaddr, Q_DST);
379976404edcSAsim Jamshed             gen_or(b0, b1);
380076404edcSAsim Jamshed             return b1;
380176404edcSAsim Jamshed     }
380276404edcSAsim Jamshed     abort();
380376404edcSAsim Jamshed     /* NOTREACHED */
380476404edcSAsim Jamshed }
380576404edcSAsim Jamshed 
380676404edcSAsim Jamshed /*
380776404edcSAsim Jamshed  * Like gen_ehostop, but for DLT_IEEE802_11 (802.11 wireless LAN) and
380876404edcSAsim Jamshed  * various 802.11 + radio headers.
380976404edcSAsim Jamshed  */
gen_wlanhostop(eaddr,dir)381076404edcSAsim Jamshed static struct block *gen_wlanhostop(eaddr, dir)
381176404edcSAsim Jamshed      register const u_char *eaddr;
381276404edcSAsim Jamshed      register int dir;
381376404edcSAsim Jamshed {
381476404edcSAsim Jamshed     register struct block *b0, *b1, *b2;
381576404edcSAsim Jamshed     register struct slist *s;
381676404edcSAsim Jamshed 
381776404edcSAsim Jamshed #ifdef ENABLE_WLAN_FILTERING_PATCH
381876404edcSAsim Jamshed     /*
381976404edcSAsim Jamshed      * GV 20070613
382076404edcSAsim Jamshed      * We need to disable the optimizer because the optimizer is buggy
382176404edcSAsim Jamshed      * and wipes out some LD instructions generated by the below
382276404edcSAsim Jamshed      * code to validate the Frame Control bits
382376404edcSAsim Jamshed      */
382476404edcSAsim Jamshed     no_optimize = 1;
382576404edcSAsim Jamshed #endif /* ENABLE_WLAN_FILTERING_PATCH */
382676404edcSAsim Jamshed 
382776404edcSAsim Jamshed     switch (dir)
382876404edcSAsim Jamshed     {
382976404edcSAsim Jamshed         case Q_SRC:
383076404edcSAsim Jamshed             /*
383176404edcSAsim Jamshed              * Oh, yuk.
383276404edcSAsim Jamshed              *
383376404edcSAsim Jamshed              *  For control frames, there is no SA.
383476404edcSAsim Jamshed              *
383576404edcSAsim Jamshed              *  For management frames, SA is at an
383676404edcSAsim Jamshed              *  offset of 10 from the beginning of
383776404edcSAsim Jamshed              *  the packet.
383876404edcSAsim Jamshed              *
383976404edcSAsim Jamshed              *  For data frames, SA is at an offset
384076404edcSAsim Jamshed              *  of 10 from the beginning of the packet
384176404edcSAsim Jamshed              *  if From DS is clear, at an offset of
384276404edcSAsim Jamshed              *  16 from the beginning of the packet
384376404edcSAsim Jamshed              *  if From DS is set and To DS is clear,
384476404edcSAsim Jamshed              *  and an offset of 24 from the beginning
384576404edcSAsim Jamshed              *  of the packet if From DS is set and To DS
384676404edcSAsim Jamshed              *  is set.
384776404edcSAsim Jamshed              */
384876404edcSAsim Jamshed 
384976404edcSAsim Jamshed             /*
385076404edcSAsim Jamshed              * Generate the tests to be done for data frames
385176404edcSAsim Jamshed              * with From DS set.
385276404edcSAsim Jamshed              *
385376404edcSAsim Jamshed              * First, check for To DS set, i.e. check "link[1] & 0x01".
385476404edcSAsim Jamshed              */
385576404edcSAsim Jamshed             s = gen_load_a(OR_LINK, 1, BPF_B);
385676404edcSAsim Jamshed             b1 = new_block(JMP(BPF_JSET));
385776404edcSAsim Jamshed             b1->s.k = 0x01;     /* To DS */
385876404edcSAsim Jamshed             b1->stmts = s;
385976404edcSAsim Jamshed 
386076404edcSAsim Jamshed             /*
386176404edcSAsim Jamshed              * If To DS is set, the SA is at 24.
386276404edcSAsim Jamshed              */
386376404edcSAsim Jamshed             b0 = gen_bcmp(OR_LINK, 24, 6, eaddr);
386476404edcSAsim Jamshed             gen_and(b1, b0);
386576404edcSAsim Jamshed 
386676404edcSAsim Jamshed             /*
386776404edcSAsim Jamshed              * Now, check for To DS not set, i.e. check
386876404edcSAsim Jamshed              * "!(link[1] & 0x01)".
386976404edcSAsim Jamshed              */
387076404edcSAsim Jamshed             s = gen_load_a(OR_LINK, 1, BPF_B);
387176404edcSAsim Jamshed             b2 = new_block(JMP(BPF_JSET));
387276404edcSAsim Jamshed             b2->s.k = 0x01;     /* To DS */
387376404edcSAsim Jamshed             b2->stmts = s;
387476404edcSAsim Jamshed             gen_not(b2);
387576404edcSAsim Jamshed 
387676404edcSAsim Jamshed             /*
387776404edcSAsim Jamshed              * If To DS is not set, the SA is at 16.
387876404edcSAsim Jamshed              */
387976404edcSAsim Jamshed             b1 = gen_bcmp(OR_LINK, 16, 6, eaddr);
388076404edcSAsim Jamshed             gen_and(b2, b1);
388176404edcSAsim Jamshed 
388276404edcSAsim Jamshed             /*
388376404edcSAsim Jamshed              * Now OR together the last two checks.  That gives
388476404edcSAsim Jamshed              * the complete set of checks for data frames with
388576404edcSAsim Jamshed              * From DS set.
388676404edcSAsim Jamshed              */
388776404edcSAsim Jamshed             gen_or(b1, b0);
388876404edcSAsim Jamshed 
388976404edcSAsim Jamshed             /*
389076404edcSAsim Jamshed              * Now check for From DS being set, and AND that with
389176404edcSAsim Jamshed              * the ORed-together checks.
389276404edcSAsim Jamshed              */
389376404edcSAsim Jamshed             s = gen_load_a(OR_LINK, 1, BPF_B);
389476404edcSAsim Jamshed             b1 = new_block(JMP(BPF_JSET));
389576404edcSAsim Jamshed             b1->s.k = 0x02;     /* From DS */
389676404edcSAsim Jamshed             b1->stmts = s;
389776404edcSAsim Jamshed             gen_and(b1, b0);
389876404edcSAsim Jamshed 
389976404edcSAsim Jamshed             /*
390076404edcSAsim Jamshed              * Now check for data frames with From DS not set.
390176404edcSAsim Jamshed              */
390276404edcSAsim Jamshed             s = gen_load_a(OR_LINK, 1, BPF_B);
390376404edcSAsim Jamshed             b2 = new_block(JMP(BPF_JSET));
390476404edcSAsim Jamshed             b2->s.k = 0x02;     /* From DS */
390576404edcSAsim Jamshed             b2->stmts = s;
390676404edcSAsim Jamshed             gen_not(b2);
390776404edcSAsim Jamshed 
390876404edcSAsim Jamshed             /*
390976404edcSAsim Jamshed              * If From DS isn't set, the SA is at 10.
391076404edcSAsim Jamshed              */
391176404edcSAsim Jamshed             b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
391276404edcSAsim Jamshed             gen_and(b2, b1);
391376404edcSAsim Jamshed 
391476404edcSAsim Jamshed             /*
391576404edcSAsim Jamshed              * Now OR together the checks for data frames with
391676404edcSAsim Jamshed              * From DS not set and for data frames with From DS
391776404edcSAsim Jamshed              * set; that gives the checks done for data frames.
391876404edcSAsim Jamshed              */
391976404edcSAsim Jamshed             gen_or(b1, b0);
392076404edcSAsim Jamshed 
392176404edcSAsim Jamshed             /*
392276404edcSAsim Jamshed              * Now check for a data frame.
392376404edcSAsim Jamshed              * I.e, check "link[0] & 0x08".
392476404edcSAsim Jamshed              */
392576404edcSAsim Jamshed             s = gen_load_a(OR_LINK, 0, BPF_B);
392676404edcSAsim Jamshed             b1 = new_block(JMP(BPF_JSET));
392776404edcSAsim Jamshed             b1->s.k = 0x08;
392876404edcSAsim Jamshed             b1->stmts = s;
392976404edcSAsim Jamshed 
393076404edcSAsim Jamshed             /*
393176404edcSAsim Jamshed              * AND that with the checks done for data frames.
393276404edcSAsim Jamshed              */
393376404edcSAsim Jamshed             gen_and(b1, b0);
393476404edcSAsim Jamshed 
393576404edcSAsim Jamshed             /*
393676404edcSAsim Jamshed              * If the high-order bit of the type value is 0, this
393776404edcSAsim Jamshed              * is a management frame.
393876404edcSAsim Jamshed              * I.e, check "!(link[0] & 0x08)".
393976404edcSAsim Jamshed              */
394076404edcSAsim Jamshed             s = gen_load_a(OR_LINK, 0, BPF_B);
394176404edcSAsim Jamshed             b2 = new_block(JMP(BPF_JSET));
394276404edcSAsim Jamshed             b2->s.k = 0x08;
394376404edcSAsim Jamshed             b2->stmts = s;
394476404edcSAsim Jamshed             gen_not(b2);
394576404edcSAsim Jamshed 
394676404edcSAsim Jamshed             /*
394776404edcSAsim Jamshed              * For management frames, the SA is at 10.
394876404edcSAsim Jamshed              */
394976404edcSAsim Jamshed             b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
395076404edcSAsim Jamshed             gen_and(b2, b1);
395176404edcSAsim Jamshed 
395276404edcSAsim Jamshed             /*
395376404edcSAsim Jamshed              * OR that with the checks done for data frames.
395476404edcSAsim Jamshed              * That gives the checks done for management and
395576404edcSAsim Jamshed              * data frames.
395676404edcSAsim Jamshed              */
395776404edcSAsim Jamshed             gen_or(b1, b0);
395876404edcSAsim Jamshed 
395976404edcSAsim Jamshed             /*
396076404edcSAsim Jamshed              * If the low-order bit of the type value is 1,
396176404edcSAsim Jamshed              * this is either a control frame or a frame
396276404edcSAsim Jamshed              * with a reserved type, and thus not a
396376404edcSAsim Jamshed              * frame with an SA.
396476404edcSAsim Jamshed              *
396576404edcSAsim Jamshed              * I.e., check "!(link[0] & 0x04)".
396676404edcSAsim Jamshed              */
396776404edcSAsim Jamshed             s = gen_load_a(OR_LINK, 0, BPF_B);
396876404edcSAsim Jamshed             b1 = new_block(JMP(BPF_JSET));
396976404edcSAsim Jamshed             b1->s.k = 0x04;
397076404edcSAsim Jamshed             b1->stmts = s;
397176404edcSAsim Jamshed             gen_not(b1);
397276404edcSAsim Jamshed 
397376404edcSAsim Jamshed             /*
397476404edcSAsim Jamshed              * AND that with the checks for data and management
397576404edcSAsim Jamshed              * frames.
397676404edcSAsim Jamshed              */
397776404edcSAsim Jamshed             gen_and(b1, b0);
397876404edcSAsim Jamshed             return b0;
397976404edcSAsim Jamshed 
398076404edcSAsim Jamshed         case Q_DST:
398176404edcSAsim Jamshed             /*
398276404edcSAsim Jamshed              * Oh, yuk.
398376404edcSAsim Jamshed              *
398476404edcSAsim Jamshed              *  For control frames, there is no DA.
398576404edcSAsim Jamshed              *
398676404edcSAsim Jamshed              *  For management frames, DA is at an
398776404edcSAsim Jamshed              *  offset of 4 from the beginning of
398876404edcSAsim Jamshed              *  the packet.
398976404edcSAsim Jamshed              *
399076404edcSAsim Jamshed              *  For data frames, DA is at an offset
399176404edcSAsim Jamshed              *  of 4 from the beginning of the packet
399276404edcSAsim Jamshed              *  if To DS is clear and at an offset of
399376404edcSAsim Jamshed              *  16 from the beginning of the packet
399476404edcSAsim Jamshed              *  if To DS is set.
399576404edcSAsim Jamshed              */
399676404edcSAsim Jamshed 
399776404edcSAsim Jamshed             /*
399876404edcSAsim Jamshed              * Generate the tests to be done for data frames.
399976404edcSAsim Jamshed              *
400076404edcSAsim Jamshed              * First, check for To DS set, i.e. "link[1] & 0x01".
400176404edcSAsim Jamshed              */
400276404edcSAsim Jamshed             s = gen_load_a(OR_LINK, 1, BPF_B);
400376404edcSAsim Jamshed             b1 = new_block(JMP(BPF_JSET));
400476404edcSAsim Jamshed             b1->s.k = 0x01;     /* To DS */
400576404edcSAsim Jamshed             b1->stmts = s;
400676404edcSAsim Jamshed 
400776404edcSAsim Jamshed             /*
400876404edcSAsim Jamshed              * If To DS is set, the DA is at 16.
400976404edcSAsim Jamshed              */
401076404edcSAsim Jamshed             b0 = gen_bcmp(OR_LINK, 16, 6, eaddr);
401176404edcSAsim Jamshed             gen_and(b1, b0);
401276404edcSAsim Jamshed 
401376404edcSAsim Jamshed             /*
401476404edcSAsim Jamshed              * Now, check for To DS not set, i.e. check
401576404edcSAsim Jamshed              * "!(link[1] & 0x01)".
401676404edcSAsim Jamshed              */
401776404edcSAsim Jamshed             s = gen_load_a(OR_LINK, 1, BPF_B);
401876404edcSAsim Jamshed             b2 = new_block(JMP(BPF_JSET));
401976404edcSAsim Jamshed             b2->s.k = 0x01;     /* To DS */
402076404edcSAsim Jamshed             b2->stmts = s;
402176404edcSAsim Jamshed             gen_not(b2);
402276404edcSAsim Jamshed 
402376404edcSAsim Jamshed             /*
402476404edcSAsim Jamshed              * If To DS is not set, the DA is at 4.
402576404edcSAsim Jamshed              */
402676404edcSAsim Jamshed             b1 = gen_bcmp(OR_LINK, 4, 6, eaddr);
402776404edcSAsim Jamshed             gen_and(b2, b1);
402876404edcSAsim Jamshed 
402976404edcSAsim Jamshed             /*
403076404edcSAsim Jamshed              * Now OR together the last two checks.  That gives
403176404edcSAsim Jamshed              * the complete set of checks for data frames.
403276404edcSAsim Jamshed              */
403376404edcSAsim Jamshed             gen_or(b1, b0);
403476404edcSAsim Jamshed 
403576404edcSAsim Jamshed             /*
403676404edcSAsim Jamshed              * Now check for a data frame.
403776404edcSAsim Jamshed              * I.e, check "link[0] & 0x08".
403876404edcSAsim Jamshed              */
403976404edcSAsim Jamshed             s = gen_load_a(OR_LINK, 0, BPF_B);
404076404edcSAsim Jamshed             b1 = new_block(JMP(BPF_JSET));
404176404edcSAsim Jamshed             b1->s.k = 0x08;
404276404edcSAsim Jamshed             b1->stmts = s;
404376404edcSAsim Jamshed 
404476404edcSAsim Jamshed             /*
404576404edcSAsim Jamshed              * AND that with the checks done for data frames.
404676404edcSAsim Jamshed              */
404776404edcSAsim Jamshed             gen_and(b1, b0);
404876404edcSAsim Jamshed 
404976404edcSAsim Jamshed             /*
405076404edcSAsim Jamshed              * If the high-order bit of the type value is 0, this
405176404edcSAsim Jamshed              * is a management frame.
405276404edcSAsim Jamshed              * I.e, check "!(link[0] & 0x08)".
405376404edcSAsim Jamshed              */
405476404edcSAsim Jamshed             s = gen_load_a(OR_LINK, 0, BPF_B);
405576404edcSAsim Jamshed             b2 = new_block(JMP(BPF_JSET));
405676404edcSAsim Jamshed             b2->s.k = 0x08;
405776404edcSAsim Jamshed             b2->stmts = s;
405876404edcSAsim Jamshed             gen_not(b2);
405976404edcSAsim Jamshed 
406076404edcSAsim Jamshed             /*
406176404edcSAsim Jamshed              * For management frames, the DA is at 4.
406276404edcSAsim Jamshed              */
406376404edcSAsim Jamshed             b1 = gen_bcmp(OR_LINK, 4, 6, eaddr);
406476404edcSAsim Jamshed             gen_and(b2, b1);
406576404edcSAsim Jamshed 
406676404edcSAsim Jamshed             /*
406776404edcSAsim Jamshed              * OR that with the checks done for data frames.
406876404edcSAsim Jamshed              * That gives the checks done for management and
406976404edcSAsim Jamshed              * data frames.
407076404edcSAsim Jamshed              */
407176404edcSAsim Jamshed             gen_or(b1, b0);
407276404edcSAsim Jamshed 
407376404edcSAsim Jamshed             /*
407476404edcSAsim Jamshed              * If the low-order bit of the type value is 1,
407576404edcSAsim Jamshed              * this is either a control frame or a frame
407676404edcSAsim Jamshed              * with a reserved type, and thus not a
407776404edcSAsim Jamshed              * frame with an SA.
407876404edcSAsim Jamshed              *
407976404edcSAsim Jamshed              * I.e., check "!(link[0] & 0x04)".
408076404edcSAsim Jamshed              */
408176404edcSAsim Jamshed             s = gen_load_a(OR_LINK, 0, BPF_B);
408276404edcSAsim Jamshed             b1 = new_block(JMP(BPF_JSET));
408376404edcSAsim Jamshed             b1->s.k = 0x04;
408476404edcSAsim Jamshed             b1->stmts = s;
408576404edcSAsim Jamshed             gen_not(b1);
408676404edcSAsim Jamshed 
408776404edcSAsim Jamshed             /*
408876404edcSAsim Jamshed              * AND that with the checks for data and management
408976404edcSAsim Jamshed              * frames.
409076404edcSAsim Jamshed              */
409176404edcSAsim Jamshed             gen_and(b1, b0);
409276404edcSAsim Jamshed             return b0;
409376404edcSAsim Jamshed 
409476404edcSAsim Jamshed             /*
409576404edcSAsim Jamshed              * XXX - add RA, TA, and BSSID keywords?
409676404edcSAsim Jamshed              */
409776404edcSAsim Jamshed         case Q_ADDR1:
409876404edcSAsim Jamshed             return (gen_bcmp(OR_LINK, 4, 6, eaddr));
409976404edcSAsim Jamshed 
410076404edcSAsim Jamshed         case Q_ADDR2:
410176404edcSAsim Jamshed             /*
410276404edcSAsim Jamshed              * Not present in CTS or ACK control frames.
410376404edcSAsim Jamshed              */
410476404edcSAsim Jamshed             b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL, IEEE80211_FC0_TYPE_MASK);
410576404edcSAsim Jamshed             gen_not(b0);
410676404edcSAsim Jamshed             b1 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS, IEEE80211_FC0_SUBTYPE_MASK);
410776404edcSAsim Jamshed             gen_not(b1);
410876404edcSAsim Jamshed             b2 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK, IEEE80211_FC0_SUBTYPE_MASK);
410976404edcSAsim Jamshed             gen_not(b2);
411076404edcSAsim Jamshed             gen_and(b1, b2);
411176404edcSAsim Jamshed             gen_or(b0, b2);
411276404edcSAsim Jamshed             b1 = gen_bcmp(OR_LINK, 10, 6, eaddr);
411376404edcSAsim Jamshed             gen_and(b2, b1);
411476404edcSAsim Jamshed             return b1;
411576404edcSAsim Jamshed 
411676404edcSAsim Jamshed         case Q_ADDR3:
411776404edcSAsim Jamshed             /*
411876404edcSAsim Jamshed              * Not present in control frames.
411976404edcSAsim Jamshed              */
412076404edcSAsim Jamshed             b0 = gen_mcmp(OR_LINK, 0, BPF_B, IEEE80211_FC0_TYPE_CTL, IEEE80211_FC0_TYPE_MASK);
412176404edcSAsim Jamshed             gen_not(b0);
412276404edcSAsim Jamshed             b1 = gen_bcmp(OR_LINK, 16, 6, eaddr);
412376404edcSAsim Jamshed             gen_and(b0, b1);
412476404edcSAsim Jamshed             return b1;
412576404edcSAsim Jamshed 
412676404edcSAsim Jamshed         case Q_ADDR4:
412776404edcSAsim Jamshed             /*
412876404edcSAsim Jamshed              * Present only if the direction mask has both "From DS"
412976404edcSAsim Jamshed              * and "To DS" set.  Neither control frames nor management
413076404edcSAsim Jamshed              * frames should have both of those set, so we don't
413176404edcSAsim Jamshed              * check the frame type.
413276404edcSAsim Jamshed              */
413376404edcSAsim Jamshed             b0 = gen_mcmp(OR_LINK, 1, BPF_B, IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
413476404edcSAsim Jamshed             b1 = gen_bcmp(OR_LINK, 24, 6, eaddr);
413576404edcSAsim Jamshed             gen_and(b0, b1);
413676404edcSAsim Jamshed             return b1;
413776404edcSAsim Jamshed 
413876404edcSAsim Jamshed         case Q_AND:
413976404edcSAsim Jamshed             b0 = gen_wlanhostop(eaddr, Q_SRC);
414076404edcSAsim Jamshed             b1 = gen_wlanhostop(eaddr, Q_DST);
414176404edcSAsim Jamshed             gen_and(b0, b1);
414276404edcSAsim Jamshed             return b1;
414376404edcSAsim Jamshed 
414476404edcSAsim Jamshed         case Q_DEFAULT:
414576404edcSAsim Jamshed         case Q_OR:
414676404edcSAsim Jamshed             b0 = gen_wlanhostop(eaddr, Q_SRC);
414776404edcSAsim Jamshed             b1 = gen_wlanhostop(eaddr, Q_DST);
414876404edcSAsim Jamshed             gen_or(b0, b1);
414976404edcSAsim Jamshed             return b1;
415076404edcSAsim Jamshed     }
415176404edcSAsim Jamshed     abort();
415276404edcSAsim Jamshed     /* NOTREACHED */
415376404edcSAsim Jamshed }
415476404edcSAsim Jamshed 
415576404edcSAsim Jamshed /*
415676404edcSAsim Jamshed  * Like gen_ehostop, but for RFC 2625 IP-over-Fibre-Channel.
415776404edcSAsim Jamshed  * (We assume that the addresses are IEEE 48-bit MAC addresses,
415876404edcSAsim Jamshed  * as the RFC states.)
415976404edcSAsim Jamshed  */
gen_ipfchostop(eaddr,dir)416076404edcSAsim Jamshed static struct block *gen_ipfchostop(eaddr, dir)
416176404edcSAsim Jamshed      register const u_char *eaddr;
416276404edcSAsim Jamshed      register int dir;
416376404edcSAsim Jamshed {
416476404edcSAsim Jamshed     register struct block *b0, *b1;
416576404edcSAsim Jamshed 
416676404edcSAsim Jamshed     switch (dir)
416776404edcSAsim Jamshed     {
416876404edcSAsim Jamshed         case Q_SRC:
416976404edcSAsim Jamshed             return gen_bcmp(OR_LINK, 10, 6, eaddr);
417076404edcSAsim Jamshed 
417176404edcSAsim Jamshed         case Q_DST:
417276404edcSAsim Jamshed             return gen_bcmp(OR_LINK, 2, 6, eaddr);
417376404edcSAsim Jamshed 
417476404edcSAsim Jamshed         case Q_AND:
417576404edcSAsim Jamshed             b0 = gen_ipfchostop(eaddr, Q_SRC);
417676404edcSAsim Jamshed             b1 = gen_ipfchostop(eaddr, Q_DST);
417776404edcSAsim Jamshed             gen_and(b0, b1);
417876404edcSAsim Jamshed             return b1;
417976404edcSAsim Jamshed 
418076404edcSAsim Jamshed         case Q_DEFAULT:
418176404edcSAsim Jamshed         case Q_OR:
418276404edcSAsim Jamshed             b0 = gen_ipfchostop(eaddr, Q_SRC);
418376404edcSAsim Jamshed             b1 = gen_ipfchostop(eaddr, Q_DST);
418476404edcSAsim Jamshed             gen_or(b0, b1);
418576404edcSAsim Jamshed             return b1;
418676404edcSAsim Jamshed     }
418776404edcSAsim Jamshed     abort();
418876404edcSAsim Jamshed     /* NOTREACHED */
418976404edcSAsim Jamshed }
419076404edcSAsim Jamshed 
419176404edcSAsim Jamshed /*
419276404edcSAsim Jamshed  * This is quite tricky because there may be pad bytes in front of the
419376404edcSAsim Jamshed  * DECNET header, and then there are two possible data packet formats that
419476404edcSAsim Jamshed  * carry both src and dst addresses, plus 5 packet types in a format that
419576404edcSAsim Jamshed  * carries only the src node, plus 2 types that use a different format and
419676404edcSAsim Jamshed  * also carry just the src node.
419776404edcSAsim Jamshed  *
419876404edcSAsim Jamshed  * Yuck.
419976404edcSAsim Jamshed  *
420076404edcSAsim Jamshed  * Instead of doing those all right, we just look for data packets with
420176404edcSAsim Jamshed  * 0 or 1 bytes of padding.  If you want to look at other packets, that
420276404edcSAsim Jamshed  * will require a lot more hacking.
420376404edcSAsim Jamshed  *
420476404edcSAsim Jamshed  * To add support for filtering on DECNET "areas" (network numbers)
420576404edcSAsim Jamshed  * one would want to add a "mask" argument to this routine.  That would
420676404edcSAsim Jamshed  * make the filter even more inefficient, although one could be clever
420776404edcSAsim Jamshed  * and not generate masking instructions if the mask is 0xFFFF.
420876404edcSAsim Jamshed  */
gen_dnhostop(addr,dir)420976404edcSAsim Jamshed static struct block *gen_dnhostop(addr, dir)
421076404edcSAsim Jamshed      bpf_u_int32 addr;
421176404edcSAsim Jamshed      int dir;
421276404edcSAsim Jamshed {
421376404edcSAsim Jamshed     struct block *b0, *b1, *b2, *tmp;
421476404edcSAsim Jamshed     u_int offset_lh;            /* offset if long header is received */
421576404edcSAsim Jamshed     u_int offset_sh;            /* offset if short header is received */
421676404edcSAsim Jamshed 
421776404edcSAsim Jamshed     switch (dir)
421876404edcSAsim Jamshed     {
421976404edcSAsim Jamshed 
422076404edcSAsim Jamshed         case Q_DST:
422176404edcSAsim Jamshed             offset_sh = 1;      /* follows flags */
422276404edcSAsim Jamshed             offset_lh = 7;      /* flgs,darea,dsubarea,HIORD */
422376404edcSAsim Jamshed             break;
422476404edcSAsim Jamshed 
422576404edcSAsim Jamshed         case Q_SRC:
422676404edcSAsim Jamshed             offset_sh = 3;      /* follows flags, dstnode */
422776404edcSAsim Jamshed             offset_lh = 15;     /* flgs,darea,dsubarea,did,sarea,ssub,HIORD */
422876404edcSAsim Jamshed             break;
422976404edcSAsim Jamshed 
423076404edcSAsim Jamshed         case Q_AND:
423176404edcSAsim Jamshed             /* Inefficient because we do our Calvinball dance twice */
423276404edcSAsim Jamshed             b0 = gen_dnhostop(addr, Q_SRC);
423376404edcSAsim Jamshed             b1 = gen_dnhostop(addr, Q_DST);
423476404edcSAsim Jamshed             gen_and(b0, b1);
423576404edcSAsim Jamshed             return b1;
423676404edcSAsim Jamshed 
423776404edcSAsim Jamshed         case Q_OR:
423876404edcSAsim Jamshed         case Q_DEFAULT:
423976404edcSAsim Jamshed             /* Inefficient because we do our Calvinball dance twice */
424076404edcSAsim Jamshed             b0 = gen_dnhostop(addr, Q_SRC);
424176404edcSAsim Jamshed             b1 = gen_dnhostop(addr, Q_DST);
424276404edcSAsim Jamshed             gen_or(b0, b1);
424376404edcSAsim Jamshed             return b1;
424476404edcSAsim Jamshed 
424576404edcSAsim Jamshed         case Q_ISO:
424676404edcSAsim Jamshed             bpf_error("ISO host filtering not implemented");
424776404edcSAsim Jamshed 
424876404edcSAsim Jamshed         default:
424976404edcSAsim Jamshed             abort();
425076404edcSAsim Jamshed     }
425176404edcSAsim Jamshed     b0 = gen_linktype(ETHERTYPE_DN);
425276404edcSAsim Jamshed     /* Check for pad = 1, long header case */
425376404edcSAsim Jamshed     tmp = gen_mcmp(OR_NET, 2, BPF_H, (bpf_int32) ntohs(0x0681), (bpf_int32) ntohs(0x07FF));
425476404edcSAsim Jamshed     b1 = gen_cmp(OR_NET, 2 + 1 + offset_lh, BPF_H, (bpf_int32) ntohs((u_short) addr));
425576404edcSAsim Jamshed     gen_and(tmp, b1);
425676404edcSAsim Jamshed     /* Check for pad = 0, long header case */
425776404edcSAsim Jamshed     tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32) 0x06, (bpf_int32) 0x7);
425876404edcSAsim Jamshed     b2 = gen_cmp(OR_NET, 2 + offset_lh, BPF_H, (bpf_int32) ntohs((u_short) addr));
425976404edcSAsim Jamshed     gen_and(tmp, b2);
426076404edcSAsim Jamshed     gen_or(b2, b1);
426176404edcSAsim Jamshed     /* Check for pad = 1, short header case */
426276404edcSAsim Jamshed     tmp = gen_mcmp(OR_NET, 2, BPF_H, (bpf_int32) ntohs(0x0281), (bpf_int32) ntohs(0x07FF));
426376404edcSAsim Jamshed     b2 = gen_cmp(OR_NET, 2 + 1 + offset_sh, BPF_H, (bpf_int32) ntohs((u_short) addr));
426476404edcSAsim Jamshed     gen_and(tmp, b2);
426576404edcSAsim Jamshed     gen_or(b2, b1);
426676404edcSAsim Jamshed     /* Check for pad = 0, short header case */
426776404edcSAsim Jamshed     tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32) 0x02, (bpf_int32) 0x7);
426876404edcSAsim Jamshed     b2 = gen_cmp(OR_NET, 2 + offset_sh, BPF_H, (bpf_int32) ntohs((u_short) addr));
426976404edcSAsim Jamshed     gen_and(tmp, b2);
427076404edcSAsim Jamshed     gen_or(b2, b1);
427176404edcSAsim Jamshed 
427276404edcSAsim Jamshed     /* Combine with test for linktype */
427376404edcSAsim Jamshed     gen_and(b0, b1);
427476404edcSAsim Jamshed     return b1;
427576404edcSAsim Jamshed }
427676404edcSAsim Jamshed 
427776404edcSAsim Jamshed /*
427876404edcSAsim Jamshed  * Generate a check for IPv4 or IPv6 for MPLS-encapsulated packets;
427976404edcSAsim Jamshed  * test the bottom-of-stack bit, and then check the version number
428076404edcSAsim Jamshed  * field in the IP header.
428176404edcSAsim Jamshed  */
gen_mpls_linktype(proto)428276404edcSAsim Jamshed static struct block *gen_mpls_linktype(proto)
428376404edcSAsim Jamshed      int proto;
428476404edcSAsim Jamshed {
428576404edcSAsim Jamshed     struct block *b0, *b1;
428676404edcSAsim Jamshed 
428776404edcSAsim Jamshed     switch (proto)
428876404edcSAsim Jamshed     {
428976404edcSAsim Jamshed 
429076404edcSAsim Jamshed         case Q_IP:
429176404edcSAsim Jamshed             /* match the bottom-of-stack bit */
429276404edcSAsim Jamshed             b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01);
429376404edcSAsim Jamshed             /* match the IPv4 version number */
429476404edcSAsim Jamshed             b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x40, 0xf0);
429576404edcSAsim Jamshed             gen_and(b0, b1);
429676404edcSAsim Jamshed             return b1;
429776404edcSAsim Jamshed 
429876404edcSAsim Jamshed         case Q_IPV6:
429976404edcSAsim Jamshed             /* match the bottom-of-stack bit */
430076404edcSAsim Jamshed             b0 = gen_mcmp(OR_NET, -2, BPF_B, 0x01, 0x01);
430176404edcSAsim Jamshed             /* match the IPv4 version number */
430276404edcSAsim Jamshed             b1 = gen_mcmp(OR_NET, 0, BPF_B, 0x60, 0xf0);
430376404edcSAsim Jamshed             gen_and(b0, b1);
430476404edcSAsim Jamshed             return b1;
430576404edcSAsim Jamshed 
430676404edcSAsim Jamshed         default:
430776404edcSAsim Jamshed             abort();
430876404edcSAsim Jamshed     }
430976404edcSAsim Jamshed }
431076404edcSAsim Jamshed 
gen_host(addr,mask,proto,dir,type)431176404edcSAsim Jamshed static struct block *gen_host(addr, mask, proto, dir, type)
431276404edcSAsim Jamshed      bpf_u_int32 addr;
431376404edcSAsim Jamshed      bpf_u_int32 mask;
431476404edcSAsim Jamshed      int proto;
431576404edcSAsim Jamshed      int dir;
431676404edcSAsim Jamshed      int type;
431776404edcSAsim Jamshed {
431876404edcSAsim Jamshed     struct block *b0, *b1;
431976404edcSAsim Jamshed     const char *typestr;
432076404edcSAsim Jamshed 
432176404edcSAsim Jamshed     if (type == Q_NET)
432276404edcSAsim Jamshed         typestr = "net";
432376404edcSAsim Jamshed     else
432476404edcSAsim Jamshed         typestr = "host";
432576404edcSAsim Jamshed 
432676404edcSAsim Jamshed     switch (proto)
432776404edcSAsim Jamshed     {
432876404edcSAsim Jamshed 
432976404edcSAsim Jamshed         case Q_DEFAULT:
433076404edcSAsim Jamshed             b0 = gen_host(addr, mask, Q_IP, dir, type);
433176404edcSAsim Jamshed             /*
433276404edcSAsim Jamshed              * Only check for non-IPv4 addresses if we're not
433376404edcSAsim Jamshed              * checking MPLS-encapsulated packets.
433476404edcSAsim Jamshed              */
433576404edcSAsim Jamshed             if (label_stack_depth == 0)
433676404edcSAsim Jamshed             {
433776404edcSAsim Jamshed                 b1 = gen_host(addr, mask, Q_ARP, dir, type);
433876404edcSAsim Jamshed                 gen_or(b0, b1);
433976404edcSAsim Jamshed                 b0 = gen_host(addr, mask, Q_RARP, dir, type);
434076404edcSAsim Jamshed                 gen_or(b1, b0);
434176404edcSAsim Jamshed             }
434276404edcSAsim Jamshed             return b0;
434376404edcSAsim Jamshed 
434476404edcSAsim Jamshed         case Q_IP:
434576404edcSAsim Jamshed             return gen_hostop(addr, mask, dir, ETHERTYPE_IP, 12, 16);
434676404edcSAsim Jamshed 
434776404edcSAsim Jamshed         case Q_RARP:
434876404edcSAsim Jamshed             return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, 14, 24);
434976404edcSAsim Jamshed 
435076404edcSAsim Jamshed         case Q_ARP:
435176404edcSAsim Jamshed             return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, 14, 24);
435276404edcSAsim Jamshed 
435376404edcSAsim Jamshed         case Q_TCP:
435476404edcSAsim Jamshed             bpf_error("'tcp' modifier applied to %s", typestr);
435576404edcSAsim Jamshed 
435676404edcSAsim Jamshed         case Q_SCTP:
435776404edcSAsim Jamshed             bpf_error("'sctp' modifier applied to %s", typestr);
435876404edcSAsim Jamshed 
435976404edcSAsim Jamshed         case Q_UDP:
436076404edcSAsim Jamshed             bpf_error("'udp' modifier applied to %s", typestr);
436176404edcSAsim Jamshed 
436276404edcSAsim Jamshed         case Q_ICMP:
436376404edcSAsim Jamshed             bpf_error("'icmp' modifier applied to %s", typestr);
436476404edcSAsim Jamshed 
436576404edcSAsim Jamshed         case Q_IGMP:
436676404edcSAsim Jamshed             bpf_error("'igmp' modifier applied to %s", typestr);
436776404edcSAsim Jamshed 
436876404edcSAsim Jamshed         case Q_IGRP:
436976404edcSAsim Jamshed             bpf_error("'igrp' modifier applied to %s", typestr);
437076404edcSAsim Jamshed 
437176404edcSAsim Jamshed         case Q_PIM:
437276404edcSAsim Jamshed             bpf_error("'pim' modifier applied to %s", typestr);
437376404edcSAsim Jamshed 
437476404edcSAsim Jamshed         case Q_VRRP:
437576404edcSAsim Jamshed             bpf_error("'vrrp' modifier applied to %s", typestr);
437676404edcSAsim Jamshed 
437776404edcSAsim Jamshed         case Q_ATALK:
437876404edcSAsim Jamshed             bpf_error("ATALK host filtering not implemented");
437976404edcSAsim Jamshed 
438076404edcSAsim Jamshed         case Q_AARP:
438176404edcSAsim Jamshed             bpf_error("AARP host filtering not implemented");
438276404edcSAsim Jamshed 
438376404edcSAsim Jamshed         case Q_DECNET:
438476404edcSAsim Jamshed             return gen_dnhostop(addr, dir);
438576404edcSAsim Jamshed 
438676404edcSAsim Jamshed         case Q_SCA:
438776404edcSAsim Jamshed             bpf_error("SCA host filtering not implemented");
438876404edcSAsim Jamshed 
438976404edcSAsim Jamshed         case Q_LAT:
439076404edcSAsim Jamshed             bpf_error("LAT host filtering not implemented");
439176404edcSAsim Jamshed 
439276404edcSAsim Jamshed         case Q_MOPDL:
439376404edcSAsim Jamshed             bpf_error("MOPDL host filtering not implemented");
439476404edcSAsim Jamshed 
439576404edcSAsim Jamshed         case Q_MOPRC:
439676404edcSAsim Jamshed             bpf_error("MOPRC host filtering not implemented");
439776404edcSAsim Jamshed 
439876404edcSAsim Jamshed #ifdef INET6
439976404edcSAsim Jamshed         case Q_IPV6:
440076404edcSAsim Jamshed             bpf_error("'ip6' modifier applied to ip host");
440176404edcSAsim Jamshed 
440276404edcSAsim Jamshed         case Q_ICMPV6:
440376404edcSAsim Jamshed             bpf_error("'icmp6' modifier applied to %s", typestr);
440476404edcSAsim Jamshed #endif /* INET6 */
440576404edcSAsim Jamshed 
440676404edcSAsim Jamshed         case Q_AH:
440776404edcSAsim Jamshed             bpf_error("'ah' modifier applied to %s", typestr);
440876404edcSAsim Jamshed 
440976404edcSAsim Jamshed         case Q_ESP:
441076404edcSAsim Jamshed             bpf_error("'esp' modifier applied to %s", typestr);
441176404edcSAsim Jamshed 
441276404edcSAsim Jamshed         case Q_ISO:
441376404edcSAsim Jamshed             bpf_error("ISO host filtering not implemented");
441476404edcSAsim Jamshed 
441576404edcSAsim Jamshed         case Q_ESIS:
441676404edcSAsim Jamshed             bpf_error("'esis' modifier applied to %s", typestr);
441776404edcSAsim Jamshed 
441876404edcSAsim Jamshed         case Q_ISIS:
441976404edcSAsim Jamshed             bpf_error("'isis' modifier applied to %s", typestr);
442076404edcSAsim Jamshed 
442176404edcSAsim Jamshed         case Q_CLNP:
442276404edcSAsim Jamshed             bpf_error("'clnp' modifier applied to %s", typestr);
442376404edcSAsim Jamshed 
442476404edcSAsim Jamshed         case Q_STP:
442576404edcSAsim Jamshed             bpf_error("'stp' modifier applied to %s", typestr);
442676404edcSAsim Jamshed 
442776404edcSAsim Jamshed         case Q_IPX:
442876404edcSAsim Jamshed             bpf_error("IPX host filtering not implemented");
442976404edcSAsim Jamshed 
443076404edcSAsim Jamshed         case Q_NETBEUI:
443176404edcSAsim Jamshed             bpf_error("'netbeui' modifier applied to %s", typestr);
443276404edcSAsim Jamshed 
443376404edcSAsim Jamshed         case Q_RADIO:
443476404edcSAsim Jamshed             bpf_error("'radio' modifier applied to %s", typestr);
443576404edcSAsim Jamshed 
443676404edcSAsim Jamshed         default:
443776404edcSAsim Jamshed             abort();
443876404edcSAsim Jamshed     }
443976404edcSAsim Jamshed     /* NOTREACHED */
444076404edcSAsim Jamshed }
444176404edcSAsim Jamshed 
444276404edcSAsim Jamshed #ifdef INET6
gen_host6(addr,mask,proto,dir,type)444376404edcSAsim Jamshed static struct block *gen_host6(addr, mask, proto, dir, type)
444476404edcSAsim Jamshed      struct in6_addr *addr;
444576404edcSAsim Jamshed      struct in6_addr *mask;
444676404edcSAsim Jamshed      int proto;
444776404edcSAsim Jamshed      int dir;
444876404edcSAsim Jamshed      int type;
444976404edcSAsim Jamshed {
445076404edcSAsim Jamshed     const char *typestr;
445176404edcSAsim Jamshed 
445276404edcSAsim Jamshed     if (type == Q_NET)
445376404edcSAsim Jamshed         typestr = "net";
445476404edcSAsim Jamshed     else
445576404edcSAsim Jamshed         typestr = "host";
445676404edcSAsim Jamshed 
445776404edcSAsim Jamshed     switch (proto)
445876404edcSAsim Jamshed     {
445976404edcSAsim Jamshed 
446076404edcSAsim Jamshed         case Q_DEFAULT:
446176404edcSAsim Jamshed             return gen_host6(addr, mask, Q_IPV6, dir, type);
446276404edcSAsim Jamshed 
446376404edcSAsim Jamshed         case Q_IP:
446476404edcSAsim Jamshed             bpf_error("'ip' modifier applied to ip6 %s", typestr);
446576404edcSAsim Jamshed 
446676404edcSAsim Jamshed         case Q_RARP:
446776404edcSAsim Jamshed             bpf_error("'rarp' modifier applied to ip6 %s", typestr);
446876404edcSAsim Jamshed 
446976404edcSAsim Jamshed         case Q_ARP:
447076404edcSAsim Jamshed             bpf_error("'arp' modifier applied to ip6 %s", typestr);
447176404edcSAsim Jamshed 
447276404edcSAsim Jamshed         case Q_SCTP:
447376404edcSAsim Jamshed             bpf_error("'sctp' modifier applied to %s", typestr);
447476404edcSAsim Jamshed 
447576404edcSAsim Jamshed         case Q_TCP:
447676404edcSAsim Jamshed             bpf_error("'tcp' modifier applied to %s", typestr);
447776404edcSAsim Jamshed 
447876404edcSAsim Jamshed         case Q_UDP:
447976404edcSAsim Jamshed             bpf_error("'udp' modifier applied to %s", typestr);
448076404edcSAsim Jamshed 
448176404edcSAsim Jamshed         case Q_ICMP:
448276404edcSAsim Jamshed             bpf_error("'icmp' modifier applied to %s", typestr);
448376404edcSAsim Jamshed 
448476404edcSAsim Jamshed         case Q_IGMP:
448576404edcSAsim Jamshed             bpf_error("'igmp' modifier applied to %s", typestr);
448676404edcSAsim Jamshed 
448776404edcSAsim Jamshed         case Q_IGRP:
448876404edcSAsim Jamshed             bpf_error("'igrp' modifier applied to %s", typestr);
448976404edcSAsim Jamshed 
449076404edcSAsim Jamshed         case Q_PIM:
449176404edcSAsim Jamshed             bpf_error("'pim' modifier applied to %s", typestr);
449276404edcSAsim Jamshed 
449376404edcSAsim Jamshed         case Q_VRRP:
449476404edcSAsim Jamshed             bpf_error("'vrrp' modifier applied to %s", typestr);
449576404edcSAsim Jamshed 
449676404edcSAsim Jamshed         case Q_ATALK:
449776404edcSAsim Jamshed             bpf_error("ATALK host filtering not implemented");
449876404edcSAsim Jamshed 
449976404edcSAsim Jamshed         case Q_AARP:
450076404edcSAsim Jamshed             bpf_error("AARP host filtering not implemented");
450176404edcSAsim Jamshed 
450276404edcSAsim Jamshed         case Q_DECNET:
450376404edcSAsim Jamshed             bpf_error("'decnet' modifier applied to ip6 %s", typestr);
450476404edcSAsim Jamshed 
450576404edcSAsim Jamshed         case Q_SCA:
450676404edcSAsim Jamshed             bpf_error("SCA host filtering not implemented");
450776404edcSAsim Jamshed 
450876404edcSAsim Jamshed         case Q_LAT:
450976404edcSAsim Jamshed             bpf_error("LAT host filtering not implemented");
451076404edcSAsim Jamshed 
451176404edcSAsim Jamshed         case Q_MOPDL:
451276404edcSAsim Jamshed             bpf_error("MOPDL host filtering not implemented");
451376404edcSAsim Jamshed 
451476404edcSAsim Jamshed         case Q_MOPRC:
451576404edcSAsim Jamshed             bpf_error("MOPRC host filtering not implemented");
451676404edcSAsim Jamshed 
451776404edcSAsim Jamshed         case Q_IPV6:
451876404edcSAsim Jamshed             return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6, 8, 24);
451976404edcSAsim Jamshed 
452076404edcSAsim Jamshed         case Q_ICMPV6:
452176404edcSAsim Jamshed             bpf_error("'icmp6' modifier applied to %s", typestr);
452276404edcSAsim Jamshed 
452376404edcSAsim Jamshed         case Q_AH:
452476404edcSAsim Jamshed             bpf_error("'ah' modifier applied to %s", typestr);
452576404edcSAsim Jamshed 
452676404edcSAsim Jamshed         case Q_ESP:
452776404edcSAsim Jamshed             bpf_error("'esp' modifier applied to %s", typestr);
452876404edcSAsim Jamshed 
452976404edcSAsim Jamshed         case Q_ISO:
453076404edcSAsim Jamshed             bpf_error("ISO host filtering not implemented");
453176404edcSAsim Jamshed 
453276404edcSAsim Jamshed         case Q_ESIS:
453376404edcSAsim Jamshed             bpf_error("'esis' modifier applied to %s", typestr);
453476404edcSAsim Jamshed 
453576404edcSAsim Jamshed         case Q_ISIS:
453676404edcSAsim Jamshed             bpf_error("'isis' modifier applied to %s", typestr);
453776404edcSAsim Jamshed 
453876404edcSAsim Jamshed         case Q_CLNP:
453976404edcSAsim Jamshed             bpf_error("'clnp' modifier applied to %s", typestr);
454076404edcSAsim Jamshed 
454176404edcSAsim Jamshed         case Q_STP:
454276404edcSAsim Jamshed             bpf_error("'stp' modifier applied to %s", typestr);
454376404edcSAsim Jamshed 
454476404edcSAsim Jamshed         case Q_IPX:
454576404edcSAsim Jamshed             bpf_error("IPX host filtering not implemented");
454676404edcSAsim Jamshed 
454776404edcSAsim Jamshed         case Q_NETBEUI:
454876404edcSAsim Jamshed             bpf_error("'netbeui' modifier applied to %s", typestr);
454976404edcSAsim Jamshed 
455076404edcSAsim Jamshed         case Q_RADIO:
455176404edcSAsim Jamshed             bpf_error("'radio' modifier applied to %s", typestr);
455276404edcSAsim Jamshed 
455376404edcSAsim Jamshed         default:
455476404edcSAsim Jamshed             abort();
455576404edcSAsim Jamshed     }
455676404edcSAsim Jamshed     /* NOTREACHED */
455776404edcSAsim Jamshed }
455876404edcSAsim Jamshed #endif /*INET6 */
455976404edcSAsim Jamshed 
456076404edcSAsim Jamshed #ifndef INET6
gen_gateway(eaddr,alist,proto,dir)456176404edcSAsim Jamshed static struct block *gen_gateway(eaddr, alist, proto, dir)
456276404edcSAsim Jamshed      const u_char *eaddr;
456376404edcSAsim Jamshed      bpf_u_int32 **alist;
456476404edcSAsim Jamshed      int proto;
456576404edcSAsim Jamshed      int dir;
456676404edcSAsim Jamshed {
456776404edcSAsim Jamshed     struct block *b0, *b1, *tmp;
456876404edcSAsim Jamshed 
456976404edcSAsim Jamshed     if (dir != 0)
457076404edcSAsim Jamshed         bpf_error("direction applied to 'gateway'");
457176404edcSAsim Jamshed 
457276404edcSAsim Jamshed     switch (proto)
457376404edcSAsim Jamshed     {
457476404edcSAsim Jamshed         case Q_DEFAULT:
457576404edcSAsim Jamshed         case Q_IP:
457676404edcSAsim Jamshed         case Q_ARP:
457776404edcSAsim Jamshed         case Q_RARP:
457876404edcSAsim Jamshed             switch (linktype)
457976404edcSAsim Jamshed             {
458076404edcSAsim Jamshed                 case DLT_EN10MB:
458176404edcSAsim Jamshed                     b0 = gen_ehostop(eaddr, Q_OR);
458276404edcSAsim Jamshed                     break;
458376404edcSAsim Jamshed                 case DLT_FDDI:
458476404edcSAsim Jamshed                     b0 = gen_fhostop(eaddr, Q_OR);
458576404edcSAsim Jamshed                     break;
458676404edcSAsim Jamshed                 case DLT_IEEE802:
458776404edcSAsim Jamshed                     b0 = gen_thostop(eaddr, Q_OR);
458876404edcSAsim Jamshed                     break;
458976404edcSAsim Jamshed                 case DLT_IEEE802_11:
459076404edcSAsim Jamshed                 case DLT_PRISM_HEADER:
459176404edcSAsim Jamshed                 case DLT_IEEE802_11_RADIO_AVS:
459276404edcSAsim Jamshed                 case DLT_IEEE802_11_RADIO:
459376404edcSAsim Jamshed                 case DLT_PPI:
459476404edcSAsim Jamshed                     b0 = gen_wlanhostop(eaddr, Q_OR);
459576404edcSAsim Jamshed                     break;
459676404edcSAsim Jamshed                 case DLT_SUNATM:
459776404edcSAsim Jamshed                     if (!is_lane)
459876404edcSAsim Jamshed                         bpf_error
459976404edcSAsim Jamshed                             ("'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
460076404edcSAsim Jamshed                     /*
460176404edcSAsim Jamshed                      * Check that the packet doesn't begin with an
460276404edcSAsim Jamshed                      * LE Control marker.  (We've already generated
460376404edcSAsim Jamshed                      * a test for LANE.)
460476404edcSAsim Jamshed                      */
460576404edcSAsim Jamshed                     b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
460676404edcSAsim Jamshed                     gen_not(b1);
460776404edcSAsim Jamshed 
460876404edcSAsim Jamshed                     /*
460976404edcSAsim Jamshed                      * Now check the MAC address.
461076404edcSAsim Jamshed                      */
461176404edcSAsim Jamshed                     b0 = gen_ehostop(eaddr, Q_OR);
461276404edcSAsim Jamshed                     gen_and(b1, b0);
461376404edcSAsim Jamshed                     break;
461476404edcSAsim Jamshed                 case DLT_IP_OVER_FC:
461576404edcSAsim Jamshed                     b0 = gen_ipfchostop(eaddr, Q_OR);
461676404edcSAsim Jamshed                     break;
461776404edcSAsim Jamshed                 default:
461876404edcSAsim Jamshed                     bpf_error
461976404edcSAsim Jamshed                         ("'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
462076404edcSAsim Jamshed             }
462176404edcSAsim Jamshed             b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST);
462276404edcSAsim Jamshed             while (*alist)
462376404edcSAsim Jamshed             {
462476404edcSAsim Jamshed                 tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR, Q_HOST);
462576404edcSAsim Jamshed                 gen_or(b1, tmp);
462676404edcSAsim Jamshed                 b1 = tmp;
462776404edcSAsim Jamshed             }
462876404edcSAsim Jamshed             gen_not(b1);
462976404edcSAsim Jamshed             gen_and(b0, b1);
463076404edcSAsim Jamshed             return b1;
463176404edcSAsim Jamshed     }
463276404edcSAsim Jamshed     bpf_error("illegal modifier of 'gateway'");
463376404edcSAsim Jamshed     /* NOTREACHED */
463476404edcSAsim Jamshed }
463576404edcSAsim Jamshed #endif
463676404edcSAsim Jamshed 
gen_proto_abbrev(proto)463776404edcSAsim Jamshed struct block *gen_proto_abbrev(proto)
463876404edcSAsim Jamshed      int proto;
463976404edcSAsim Jamshed {
464076404edcSAsim Jamshed     struct block *b0;
464176404edcSAsim Jamshed     struct block *b1;
464276404edcSAsim Jamshed 
464376404edcSAsim Jamshed     switch (proto)
464476404edcSAsim Jamshed     {
464576404edcSAsim Jamshed 
464676404edcSAsim Jamshed         case Q_SCTP:
464776404edcSAsim Jamshed             b1 = gen_proto(IPPROTO_SCTP, Q_IP, Q_DEFAULT);
464876404edcSAsim Jamshed #ifdef INET6
464976404edcSAsim Jamshed             b0 = gen_proto(IPPROTO_SCTP, Q_IPV6, Q_DEFAULT);
465076404edcSAsim Jamshed             gen_or(b0, b1);
465176404edcSAsim Jamshed #endif
465276404edcSAsim Jamshed             break;
465376404edcSAsim Jamshed 
465476404edcSAsim Jamshed         case Q_TCP:
465576404edcSAsim Jamshed             b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT);
465676404edcSAsim Jamshed #ifdef INET6
465776404edcSAsim Jamshed             b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
465876404edcSAsim Jamshed             gen_or(b0, b1);
465976404edcSAsim Jamshed #endif
466076404edcSAsim Jamshed             break;
466176404edcSAsim Jamshed 
466276404edcSAsim Jamshed         case Q_UDP:
466376404edcSAsim Jamshed             b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT);
466476404edcSAsim Jamshed #ifdef INET6
466576404edcSAsim Jamshed             b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
466676404edcSAsim Jamshed             gen_or(b0, b1);
466776404edcSAsim Jamshed #endif
466876404edcSAsim Jamshed             break;
466976404edcSAsim Jamshed 
467076404edcSAsim Jamshed         case Q_ICMP:
467176404edcSAsim Jamshed             b1 = gen_proto(IPPROTO_ICMP, Q_IP, Q_DEFAULT);
467276404edcSAsim Jamshed             break;
467376404edcSAsim Jamshed 
467476404edcSAsim Jamshed #ifndef	IPPROTO_IGMP
467576404edcSAsim Jamshed #define	IPPROTO_IGMP	2
467676404edcSAsim Jamshed #endif
467776404edcSAsim Jamshed 
467876404edcSAsim Jamshed         case Q_IGMP:
467976404edcSAsim Jamshed             b1 = gen_proto(IPPROTO_IGMP, Q_IP, Q_DEFAULT);
468076404edcSAsim Jamshed             break;
468176404edcSAsim Jamshed 
468276404edcSAsim Jamshed #ifndef	IPPROTO_IGRP
468376404edcSAsim Jamshed #define	IPPROTO_IGRP	9
468476404edcSAsim Jamshed #endif
468576404edcSAsim Jamshed         case Q_IGRP:
468676404edcSAsim Jamshed             b1 = gen_proto(IPPROTO_IGRP, Q_IP, Q_DEFAULT);
468776404edcSAsim Jamshed             break;
468876404edcSAsim Jamshed 
468976404edcSAsim Jamshed #ifndef IPPROTO_PIM
469076404edcSAsim Jamshed #define IPPROTO_PIM	103
469176404edcSAsim Jamshed #endif
469276404edcSAsim Jamshed 
469376404edcSAsim Jamshed         case Q_PIM:
469476404edcSAsim Jamshed             b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT);
469576404edcSAsim Jamshed #ifdef INET6
469676404edcSAsim Jamshed             b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
469776404edcSAsim Jamshed             gen_or(b0, b1);
469876404edcSAsim Jamshed #endif
469976404edcSAsim Jamshed             break;
470076404edcSAsim Jamshed 
470176404edcSAsim Jamshed #ifndef IPPROTO_VRRP
470276404edcSAsim Jamshed #define IPPROTO_VRRP	112
470376404edcSAsim Jamshed #endif
470476404edcSAsim Jamshed 
470576404edcSAsim Jamshed         case Q_VRRP:
470676404edcSAsim Jamshed             b1 = gen_proto(IPPROTO_VRRP, Q_IP, Q_DEFAULT);
470776404edcSAsim Jamshed             break;
470876404edcSAsim Jamshed 
470976404edcSAsim Jamshed         case Q_IP:
471076404edcSAsim Jamshed             b1 = gen_linktype(ETHERTYPE_IP);
471176404edcSAsim Jamshed             break;
471276404edcSAsim Jamshed 
471376404edcSAsim Jamshed         case Q_ARP:
471476404edcSAsim Jamshed             b1 = gen_linktype(ETHERTYPE_ARP);
471576404edcSAsim Jamshed             break;
471676404edcSAsim Jamshed 
471776404edcSAsim Jamshed         case Q_RARP:
471876404edcSAsim Jamshed             b1 = gen_linktype(ETHERTYPE_REVARP);
471976404edcSAsim Jamshed             break;
472076404edcSAsim Jamshed 
472176404edcSAsim Jamshed         case Q_LINK:
472276404edcSAsim Jamshed             bpf_error("link layer applied in wrong context");
472376404edcSAsim Jamshed 
472476404edcSAsim Jamshed         case Q_ATALK:
472576404edcSAsim Jamshed             b1 = gen_linktype(ETHERTYPE_ATALK);
472676404edcSAsim Jamshed             break;
472776404edcSAsim Jamshed 
472876404edcSAsim Jamshed         case Q_AARP:
472976404edcSAsim Jamshed             b1 = gen_linktype(ETHERTYPE_AARP);
473076404edcSAsim Jamshed             break;
473176404edcSAsim Jamshed 
473276404edcSAsim Jamshed         case Q_DECNET:
473376404edcSAsim Jamshed             b1 = gen_linktype(ETHERTYPE_DN);
473476404edcSAsim Jamshed             break;
473576404edcSAsim Jamshed 
473676404edcSAsim Jamshed         case Q_SCA:
473776404edcSAsim Jamshed             b1 = gen_linktype(ETHERTYPE_SCA);
473876404edcSAsim Jamshed             break;
473976404edcSAsim Jamshed 
474076404edcSAsim Jamshed         case Q_LAT:
474176404edcSAsim Jamshed             b1 = gen_linktype(ETHERTYPE_LAT);
474276404edcSAsim Jamshed             break;
474376404edcSAsim Jamshed 
474476404edcSAsim Jamshed         case Q_MOPDL:
474576404edcSAsim Jamshed             b1 = gen_linktype(ETHERTYPE_MOPDL);
474676404edcSAsim Jamshed             break;
474776404edcSAsim Jamshed 
474876404edcSAsim Jamshed         case Q_MOPRC:
474976404edcSAsim Jamshed             b1 = gen_linktype(ETHERTYPE_MOPRC);
475076404edcSAsim Jamshed             break;
475176404edcSAsim Jamshed 
475276404edcSAsim Jamshed #ifdef INET6
475376404edcSAsim Jamshed         case Q_IPV6:
475476404edcSAsim Jamshed             b1 = gen_linktype(ETHERTYPE_IPV6);
475576404edcSAsim Jamshed             break;
475676404edcSAsim Jamshed 
475776404edcSAsim Jamshed #ifndef IPPROTO_ICMPV6
475876404edcSAsim Jamshed #define IPPROTO_ICMPV6	58
475976404edcSAsim Jamshed #endif
476076404edcSAsim Jamshed         case Q_ICMPV6:
476176404edcSAsim Jamshed             b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT);
476276404edcSAsim Jamshed             break;
476376404edcSAsim Jamshed #endif /* INET6 */
476476404edcSAsim Jamshed 
476576404edcSAsim Jamshed #ifndef IPPROTO_AH
476676404edcSAsim Jamshed #define IPPROTO_AH	51
476776404edcSAsim Jamshed #endif
476876404edcSAsim Jamshed         case Q_AH:
476976404edcSAsim Jamshed             b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT);
477076404edcSAsim Jamshed #ifdef INET6
477176404edcSAsim Jamshed             b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT);
477276404edcSAsim Jamshed             gen_or(b0, b1);
477376404edcSAsim Jamshed #endif
477476404edcSAsim Jamshed             break;
477576404edcSAsim Jamshed 
477676404edcSAsim Jamshed #ifndef IPPROTO_ESP
477776404edcSAsim Jamshed #define IPPROTO_ESP	50
477876404edcSAsim Jamshed #endif
477976404edcSAsim Jamshed         case Q_ESP:
478076404edcSAsim Jamshed             b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT);
478176404edcSAsim Jamshed #ifdef INET6
478276404edcSAsim Jamshed             b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
478376404edcSAsim Jamshed             gen_or(b0, b1);
478476404edcSAsim Jamshed #endif
478576404edcSAsim Jamshed             break;
478676404edcSAsim Jamshed 
478776404edcSAsim Jamshed         case Q_ISO:
478876404edcSAsim Jamshed             b1 = gen_linktype(LLCSAP_ISONS);
478976404edcSAsim Jamshed             break;
479076404edcSAsim Jamshed 
479176404edcSAsim Jamshed         case Q_ESIS:
479276404edcSAsim Jamshed             b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT);
479376404edcSAsim Jamshed             break;
479476404edcSAsim Jamshed 
479576404edcSAsim Jamshed         case Q_ISIS:
479676404edcSAsim Jamshed             b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
479776404edcSAsim Jamshed             break;
479876404edcSAsim Jamshed 
479976404edcSAsim Jamshed         case Q_ISIS_L1:        /* all IS-IS Level1 PDU-Types */
480076404edcSAsim Jamshed             b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
480176404edcSAsim Jamshed             b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);    /* FIXME extract the circuit-type bits */
480276404edcSAsim Jamshed             gen_or(b0, b1);
480376404edcSAsim Jamshed             b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
480476404edcSAsim Jamshed             gen_or(b0, b1);
480576404edcSAsim Jamshed             b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
480676404edcSAsim Jamshed             gen_or(b0, b1);
480776404edcSAsim Jamshed             b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
480876404edcSAsim Jamshed             gen_or(b0, b1);
480976404edcSAsim Jamshed             break;
481076404edcSAsim Jamshed 
481176404edcSAsim Jamshed         case Q_ISIS_L2:        /* all IS-IS Level2 PDU-Types */
481276404edcSAsim Jamshed             b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
481376404edcSAsim Jamshed             b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);    /* FIXME extract the circuit-type bits */
481476404edcSAsim Jamshed             gen_or(b0, b1);
481576404edcSAsim Jamshed             b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
481676404edcSAsim Jamshed             gen_or(b0, b1);
481776404edcSAsim Jamshed             b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
481876404edcSAsim Jamshed             gen_or(b0, b1);
481976404edcSAsim Jamshed             b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
482076404edcSAsim Jamshed             gen_or(b0, b1);
482176404edcSAsim Jamshed             break;
482276404edcSAsim Jamshed 
482376404edcSAsim Jamshed         case Q_ISIS_IIH:       /* all IS-IS Hello PDU-Types */
482476404edcSAsim Jamshed             b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
482576404edcSAsim Jamshed             b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
482676404edcSAsim Jamshed             gen_or(b0, b1);
482776404edcSAsim Jamshed             b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);
482876404edcSAsim Jamshed             gen_or(b0, b1);
482976404edcSAsim Jamshed             break;
483076404edcSAsim Jamshed 
483176404edcSAsim Jamshed         case Q_ISIS_LSP:
483276404edcSAsim Jamshed             b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
483376404edcSAsim Jamshed             b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
483476404edcSAsim Jamshed             gen_or(b0, b1);
483576404edcSAsim Jamshed             break;
483676404edcSAsim Jamshed 
483776404edcSAsim Jamshed         case Q_ISIS_SNP:
483876404edcSAsim Jamshed             b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
483976404edcSAsim Jamshed             b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
484076404edcSAsim Jamshed             gen_or(b0, b1);
484176404edcSAsim Jamshed             b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
484276404edcSAsim Jamshed             gen_or(b0, b1);
484376404edcSAsim Jamshed             b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
484476404edcSAsim Jamshed             gen_or(b0, b1);
484576404edcSAsim Jamshed             break;
484676404edcSAsim Jamshed 
484776404edcSAsim Jamshed         case Q_ISIS_CSNP:
484876404edcSAsim Jamshed             b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
484976404edcSAsim Jamshed             b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
485076404edcSAsim Jamshed             gen_or(b0, b1);
485176404edcSAsim Jamshed             break;
485276404edcSAsim Jamshed 
485376404edcSAsim Jamshed         case Q_ISIS_PSNP:
485476404edcSAsim Jamshed             b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
485576404edcSAsim Jamshed             b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
485676404edcSAsim Jamshed             gen_or(b0, b1);
485776404edcSAsim Jamshed             break;
485876404edcSAsim Jamshed 
485976404edcSAsim Jamshed         case Q_CLNP:
486076404edcSAsim Jamshed             b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT);
486176404edcSAsim Jamshed             break;
486276404edcSAsim Jamshed 
486376404edcSAsim Jamshed         case Q_STP:
486476404edcSAsim Jamshed             b1 = gen_linktype(LLCSAP_8021D);
486576404edcSAsim Jamshed             break;
486676404edcSAsim Jamshed 
486776404edcSAsim Jamshed         case Q_IPX:
486876404edcSAsim Jamshed             b1 = gen_linktype(LLCSAP_IPX);
486976404edcSAsim Jamshed             break;
487076404edcSAsim Jamshed 
487176404edcSAsim Jamshed         case Q_NETBEUI:
487276404edcSAsim Jamshed             b1 = gen_linktype(LLCSAP_NETBEUI);
487376404edcSAsim Jamshed             break;
487476404edcSAsim Jamshed 
487576404edcSAsim Jamshed         case Q_RADIO:
487676404edcSAsim Jamshed             bpf_error("'radio' is not a valid protocol type");
487776404edcSAsim Jamshed 
487876404edcSAsim Jamshed         default:
487976404edcSAsim Jamshed             abort();
488076404edcSAsim Jamshed     }
488176404edcSAsim Jamshed     return b1;
488276404edcSAsim Jamshed }
488376404edcSAsim Jamshed 
gen_ipfrag()488476404edcSAsim Jamshed static struct block *gen_ipfrag()
488576404edcSAsim Jamshed {
488676404edcSAsim Jamshed     struct slist *s;
488776404edcSAsim Jamshed     struct block *b;
488876404edcSAsim Jamshed 
488976404edcSAsim Jamshed     /* not ip frag */
489076404edcSAsim Jamshed     s = gen_load_a(OR_NET, 6, BPF_H);
489176404edcSAsim Jamshed     b = new_block(JMP(BPF_JSET));
489276404edcSAsim Jamshed     b->s.k = 0x1fff;
489376404edcSAsim Jamshed     b->stmts = s;
489476404edcSAsim Jamshed     gen_not(b);
489576404edcSAsim Jamshed 
489676404edcSAsim Jamshed     return b;
489776404edcSAsim Jamshed }
489876404edcSAsim Jamshed 
489976404edcSAsim Jamshed /*
490076404edcSAsim Jamshed  * Generate a comparison to a port value in the transport-layer header
490176404edcSAsim Jamshed  * at the specified offset from the beginning of that header.
490276404edcSAsim Jamshed  *
490376404edcSAsim Jamshed  * XXX - this handles a variable-length prefix preceding the link-layer
490476404edcSAsim Jamshed  * header, such as the radiotap or AVS radio prefix, but doesn't handle
490576404edcSAsim Jamshed  * variable-length link-layer headers (such as Token Ring or 802.11
490676404edcSAsim Jamshed  * headers).
490776404edcSAsim Jamshed  */
gen_portatom(off,v)490876404edcSAsim Jamshed static struct block *gen_portatom(off, v)
490976404edcSAsim Jamshed      int off;
491076404edcSAsim Jamshed      bpf_int32 v;
491176404edcSAsim Jamshed {
491276404edcSAsim Jamshed     return gen_cmp(OR_TRAN_IPV4, off, BPF_H, v);
491376404edcSAsim Jamshed }
491476404edcSAsim Jamshed 
491576404edcSAsim Jamshed #ifdef INET6
gen_portatom6(off,v)491676404edcSAsim Jamshed static struct block *gen_portatom6(off, v)
491776404edcSAsim Jamshed      int off;
491876404edcSAsim Jamshed      bpf_int32 v;
491976404edcSAsim Jamshed {
492076404edcSAsim Jamshed     return gen_cmp(OR_TRAN_IPV6, off, BPF_H, v);
492176404edcSAsim Jamshed }
492276404edcSAsim Jamshed #endif /*INET6 */
492376404edcSAsim Jamshed 
gen_portop(port,proto,dir)492476404edcSAsim Jamshed struct block *gen_portop(port, proto, dir)
492576404edcSAsim Jamshed      int port, proto, dir;
492676404edcSAsim Jamshed {
492776404edcSAsim Jamshed     struct block *b0, *b1, *tmp;
492876404edcSAsim Jamshed 
492976404edcSAsim Jamshed     /* ip proto 'proto' */
493076404edcSAsim Jamshed     tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32) proto);
493176404edcSAsim Jamshed     b0 = gen_ipfrag();
493276404edcSAsim Jamshed     gen_and(tmp, b0);
493376404edcSAsim Jamshed 
493476404edcSAsim Jamshed     switch (dir)
493576404edcSAsim Jamshed     {
493676404edcSAsim Jamshed         case Q_SRC:
493776404edcSAsim Jamshed             b1 = gen_portatom(0, (bpf_int32) port);
493876404edcSAsim Jamshed             break;
493976404edcSAsim Jamshed 
494076404edcSAsim Jamshed         case Q_DST:
494176404edcSAsim Jamshed             b1 = gen_portatom(2, (bpf_int32) port);
494276404edcSAsim Jamshed             break;
494376404edcSAsim Jamshed 
494476404edcSAsim Jamshed         case Q_OR:
494576404edcSAsim Jamshed         case Q_DEFAULT:
494676404edcSAsim Jamshed             tmp = gen_portatom(0, (bpf_int32) port);
494776404edcSAsim Jamshed             b1 = gen_portatom(2, (bpf_int32) port);
494876404edcSAsim Jamshed             gen_or(tmp, b1);
494976404edcSAsim Jamshed             break;
495076404edcSAsim Jamshed 
495176404edcSAsim Jamshed         case Q_AND:
495276404edcSAsim Jamshed             tmp = gen_portatom(0, (bpf_int32) port);
495376404edcSAsim Jamshed             b1 = gen_portatom(2, (bpf_int32) port);
495476404edcSAsim Jamshed             gen_and(tmp, b1);
495576404edcSAsim Jamshed             break;
495676404edcSAsim Jamshed 
495776404edcSAsim Jamshed         default:
495876404edcSAsim Jamshed             abort();
495976404edcSAsim Jamshed     }
496076404edcSAsim Jamshed     gen_and(b0, b1);
496176404edcSAsim Jamshed 
496276404edcSAsim Jamshed     return b1;
496376404edcSAsim Jamshed }
496476404edcSAsim Jamshed 
gen_port(port,ip_proto,dir)496576404edcSAsim Jamshed static struct block *gen_port(port, ip_proto, dir)
496676404edcSAsim Jamshed      int port;
496776404edcSAsim Jamshed      int ip_proto;
496876404edcSAsim Jamshed      int dir;
496976404edcSAsim Jamshed {
497076404edcSAsim Jamshed     struct block *b0, *b1, *tmp;
497176404edcSAsim Jamshed 
497276404edcSAsim Jamshed     /*
497376404edcSAsim Jamshed      * ether proto ip
497476404edcSAsim Jamshed      *
497576404edcSAsim Jamshed      * For FDDI, RFC 1188 says that SNAP encapsulation is used,
497676404edcSAsim Jamshed      * not LLC encapsulation with LLCSAP_IP.
497776404edcSAsim Jamshed      *
497876404edcSAsim Jamshed      * For IEEE 802 networks - which includes 802.5 token ring
497976404edcSAsim Jamshed      * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042
498076404edcSAsim Jamshed      * says that SNAP encapsulation is used, not LLC encapsulation
498176404edcSAsim Jamshed      * with LLCSAP_IP.
498276404edcSAsim Jamshed      *
498376404edcSAsim Jamshed      * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and
498476404edcSAsim Jamshed      * RFC 2225 say that SNAP encapsulation is used, not LLC
498576404edcSAsim Jamshed      * encapsulation with LLCSAP_IP.
498676404edcSAsim Jamshed      *
498776404edcSAsim Jamshed      * So we always check for ETHERTYPE_IP.
498876404edcSAsim Jamshed      */
498976404edcSAsim Jamshed     b0 = gen_linktype(ETHERTYPE_IP);
499076404edcSAsim Jamshed 
499176404edcSAsim Jamshed     switch (ip_proto)
499276404edcSAsim Jamshed     {
499376404edcSAsim Jamshed         case IPPROTO_UDP:
499476404edcSAsim Jamshed         case IPPROTO_TCP:
499576404edcSAsim Jamshed         case IPPROTO_SCTP:
499676404edcSAsim Jamshed             b1 = gen_portop(port, ip_proto, dir);
499776404edcSAsim Jamshed             break;
499876404edcSAsim Jamshed 
499976404edcSAsim Jamshed         case PROTO_UNDEF:
500076404edcSAsim Jamshed             tmp = gen_portop(port, IPPROTO_TCP, dir);
500176404edcSAsim Jamshed             b1 = gen_portop(port, IPPROTO_UDP, dir);
500276404edcSAsim Jamshed             gen_or(tmp, b1);
500376404edcSAsim Jamshed             tmp = gen_portop(port, IPPROTO_SCTP, dir);
500476404edcSAsim Jamshed             gen_or(tmp, b1);
500576404edcSAsim Jamshed             break;
500676404edcSAsim Jamshed 
500776404edcSAsim Jamshed         default:
500876404edcSAsim Jamshed             abort();
500976404edcSAsim Jamshed     }
501076404edcSAsim Jamshed     gen_and(b0, b1);
501176404edcSAsim Jamshed     return b1;
501276404edcSAsim Jamshed }
501376404edcSAsim Jamshed 
501476404edcSAsim Jamshed #ifdef INET6
gen_portop6(port,proto,dir)501576404edcSAsim Jamshed struct block *gen_portop6(port, proto, dir)
501676404edcSAsim Jamshed      int port, proto, dir;
501776404edcSAsim Jamshed {
501876404edcSAsim Jamshed     struct block *b0, *b1, *tmp;
501976404edcSAsim Jamshed 
502076404edcSAsim Jamshed     /* ip6 proto 'proto' */
502176404edcSAsim Jamshed     b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32) proto);
502276404edcSAsim Jamshed 
502376404edcSAsim Jamshed     switch (dir)
502476404edcSAsim Jamshed     {
502576404edcSAsim Jamshed         case Q_SRC:
502676404edcSAsim Jamshed             b1 = gen_portatom6(0, (bpf_int32) port);
502776404edcSAsim Jamshed             break;
502876404edcSAsim Jamshed 
502976404edcSAsim Jamshed         case Q_DST:
503076404edcSAsim Jamshed             b1 = gen_portatom6(2, (bpf_int32) port);
503176404edcSAsim Jamshed             break;
503276404edcSAsim Jamshed 
503376404edcSAsim Jamshed         case Q_OR:
503476404edcSAsim Jamshed         case Q_DEFAULT:
503576404edcSAsim Jamshed             tmp = gen_portatom6(0, (bpf_int32) port);
503676404edcSAsim Jamshed             b1 = gen_portatom6(2, (bpf_int32) port);
503776404edcSAsim Jamshed             gen_or(tmp, b1);
503876404edcSAsim Jamshed             break;
503976404edcSAsim Jamshed 
504076404edcSAsim Jamshed         case Q_AND:
504176404edcSAsim Jamshed             tmp = gen_portatom6(0, (bpf_int32) port);
504276404edcSAsim Jamshed             b1 = gen_portatom6(2, (bpf_int32) port);
504376404edcSAsim Jamshed             gen_and(tmp, b1);
504476404edcSAsim Jamshed             break;
504576404edcSAsim Jamshed 
504676404edcSAsim Jamshed         default:
504776404edcSAsim Jamshed             abort();
504876404edcSAsim Jamshed     }
504976404edcSAsim Jamshed     gen_and(b0, b1);
505076404edcSAsim Jamshed 
505176404edcSAsim Jamshed     return b1;
505276404edcSAsim Jamshed }
505376404edcSAsim Jamshed 
gen_port6(port,ip_proto,dir)505476404edcSAsim Jamshed static struct block *gen_port6(port, ip_proto, dir)
505576404edcSAsim Jamshed      int port;
505676404edcSAsim Jamshed      int ip_proto;
505776404edcSAsim Jamshed      int dir;
505876404edcSAsim Jamshed {
505976404edcSAsim Jamshed     struct block *b0, *b1, *tmp;
506076404edcSAsim Jamshed 
506176404edcSAsim Jamshed     /* link proto ip6 */
506276404edcSAsim Jamshed     b0 = gen_linktype(ETHERTYPE_IPV6);
506376404edcSAsim Jamshed 
506476404edcSAsim Jamshed     switch (ip_proto)
506576404edcSAsim Jamshed     {
506676404edcSAsim Jamshed         case IPPROTO_UDP:
506776404edcSAsim Jamshed         case IPPROTO_TCP:
506876404edcSAsim Jamshed         case IPPROTO_SCTP:
506976404edcSAsim Jamshed             b1 = gen_portop6(port, ip_proto, dir);
507076404edcSAsim Jamshed             break;
507176404edcSAsim Jamshed 
507276404edcSAsim Jamshed         case PROTO_UNDEF:
507376404edcSAsim Jamshed             tmp = gen_portop6(port, IPPROTO_TCP, dir);
507476404edcSAsim Jamshed             b1 = gen_portop6(port, IPPROTO_UDP, dir);
507576404edcSAsim Jamshed             gen_or(tmp, b1);
507676404edcSAsim Jamshed             tmp = gen_portop6(port, IPPROTO_SCTP, dir);
507776404edcSAsim Jamshed             gen_or(tmp, b1);
507876404edcSAsim Jamshed             break;
507976404edcSAsim Jamshed 
508076404edcSAsim Jamshed         default:
508176404edcSAsim Jamshed             abort();
508276404edcSAsim Jamshed     }
508376404edcSAsim Jamshed     gen_and(b0, b1);
508476404edcSAsim Jamshed     return b1;
508576404edcSAsim Jamshed }
508676404edcSAsim Jamshed #endif /* INET6 */
508776404edcSAsim Jamshed 
508876404edcSAsim Jamshed /* gen_portrange code */
gen_portrangeatom(off,v1,v2)508976404edcSAsim Jamshed static struct block *gen_portrangeatom(off, v1, v2)
509076404edcSAsim Jamshed      int off;
509176404edcSAsim Jamshed      bpf_int32 v1, v2;
509276404edcSAsim Jamshed {
509376404edcSAsim Jamshed     struct block *b1, *b2;
509476404edcSAsim Jamshed 
509576404edcSAsim Jamshed     if (v1 > v2)
509676404edcSAsim Jamshed     {
509776404edcSAsim Jamshed         /*
509876404edcSAsim Jamshed          * Reverse the order of the ports, so v1 is the lower one.
509976404edcSAsim Jamshed          */
510076404edcSAsim Jamshed         bpf_int32 vtemp;
510176404edcSAsim Jamshed 
510276404edcSAsim Jamshed         vtemp = v1;
510376404edcSAsim Jamshed         v1 = v2;
510476404edcSAsim Jamshed         v2 = vtemp;
510576404edcSAsim Jamshed     }
510676404edcSAsim Jamshed 
510776404edcSAsim Jamshed     b1 = gen_cmp_ge(OR_TRAN_IPV4, off, BPF_H, v1);
510876404edcSAsim Jamshed     b2 = gen_cmp_le(OR_TRAN_IPV4, off, BPF_H, v2);
510976404edcSAsim Jamshed 
511076404edcSAsim Jamshed     gen_and(b1, b2);
511176404edcSAsim Jamshed 
511276404edcSAsim Jamshed     return b2;
511376404edcSAsim Jamshed }
511476404edcSAsim Jamshed 
gen_portrangeop(port1,port2,proto,dir)511576404edcSAsim Jamshed struct block *gen_portrangeop(port1, port2, proto, dir)
511676404edcSAsim Jamshed      int port1, port2;
511776404edcSAsim Jamshed      int proto;
511876404edcSAsim Jamshed      int dir;
511976404edcSAsim Jamshed {
512076404edcSAsim Jamshed     struct block *b0, *b1, *tmp;
512176404edcSAsim Jamshed 
512276404edcSAsim Jamshed     /* ip proto 'proto' */
512376404edcSAsim Jamshed     tmp = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32) proto);
512476404edcSAsim Jamshed     b0 = gen_ipfrag();
512576404edcSAsim Jamshed     gen_and(tmp, b0);
512676404edcSAsim Jamshed 
512776404edcSAsim Jamshed     switch (dir)
512876404edcSAsim Jamshed     {
512976404edcSAsim Jamshed         case Q_SRC:
513076404edcSAsim Jamshed             b1 = gen_portrangeatom(0, (bpf_int32) port1, (bpf_int32) port2);
513176404edcSAsim Jamshed             break;
513276404edcSAsim Jamshed 
513376404edcSAsim Jamshed         case Q_DST:
513476404edcSAsim Jamshed             b1 = gen_portrangeatom(2, (bpf_int32) port1, (bpf_int32) port2);
513576404edcSAsim Jamshed             break;
513676404edcSAsim Jamshed 
513776404edcSAsim Jamshed         case Q_OR:
513876404edcSAsim Jamshed         case Q_DEFAULT:
513976404edcSAsim Jamshed             tmp = gen_portrangeatom(0, (bpf_int32) port1, (bpf_int32) port2);
514076404edcSAsim Jamshed             b1 = gen_portrangeatom(2, (bpf_int32) port1, (bpf_int32) port2);
514176404edcSAsim Jamshed             gen_or(tmp, b1);
514276404edcSAsim Jamshed             break;
514376404edcSAsim Jamshed 
514476404edcSAsim Jamshed         case Q_AND:
514576404edcSAsim Jamshed             tmp = gen_portrangeatom(0, (bpf_int32) port1, (bpf_int32) port2);
514676404edcSAsim Jamshed             b1 = gen_portrangeatom(2, (bpf_int32) port1, (bpf_int32) port2);
514776404edcSAsim Jamshed             gen_and(tmp, b1);
514876404edcSAsim Jamshed             break;
514976404edcSAsim Jamshed 
515076404edcSAsim Jamshed         default:
515176404edcSAsim Jamshed             abort();
515276404edcSAsim Jamshed     }
515376404edcSAsim Jamshed     gen_and(b0, b1);
515476404edcSAsim Jamshed 
515576404edcSAsim Jamshed     return b1;
515676404edcSAsim Jamshed }
515776404edcSAsim Jamshed 
gen_portrange(port1,port2,ip_proto,dir)515876404edcSAsim Jamshed static struct block *gen_portrange(port1, port2, ip_proto, dir)
515976404edcSAsim Jamshed      int port1, port2;
516076404edcSAsim Jamshed      int ip_proto;
516176404edcSAsim Jamshed      int dir;
516276404edcSAsim Jamshed {
516376404edcSAsim Jamshed     struct block *b0, *b1, *tmp;
516476404edcSAsim Jamshed 
516576404edcSAsim Jamshed     /* link proto ip */
516676404edcSAsim Jamshed     b0 = gen_linktype(ETHERTYPE_IP);
516776404edcSAsim Jamshed 
516876404edcSAsim Jamshed     switch (ip_proto)
516976404edcSAsim Jamshed     {
517076404edcSAsim Jamshed         case IPPROTO_UDP:
517176404edcSAsim Jamshed         case IPPROTO_TCP:
517276404edcSAsim Jamshed         case IPPROTO_SCTP:
517376404edcSAsim Jamshed             b1 = gen_portrangeop(port1, port2, ip_proto, dir);
517476404edcSAsim Jamshed             break;
517576404edcSAsim Jamshed 
517676404edcSAsim Jamshed         case PROTO_UNDEF:
517776404edcSAsim Jamshed             tmp = gen_portrangeop(port1, port2, IPPROTO_TCP, dir);
517876404edcSAsim Jamshed             b1 = gen_portrangeop(port1, port2, IPPROTO_UDP, dir);
517976404edcSAsim Jamshed             gen_or(tmp, b1);
518076404edcSAsim Jamshed             tmp = gen_portrangeop(port1, port2, IPPROTO_SCTP, dir);
518176404edcSAsim Jamshed             gen_or(tmp, b1);
518276404edcSAsim Jamshed             break;
518376404edcSAsim Jamshed 
518476404edcSAsim Jamshed         default:
518576404edcSAsim Jamshed             abort();
518676404edcSAsim Jamshed     }
518776404edcSAsim Jamshed     gen_and(b0, b1);
518876404edcSAsim Jamshed     return b1;
518976404edcSAsim Jamshed }
519076404edcSAsim Jamshed 
519176404edcSAsim Jamshed #ifdef INET6
gen_portrangeatom6(off,v1,v2)519276404edcSAsim Jamshed static struct block *gen_portrangeatom6(off, v1, v2)
519376404edcSAsim Jamshed      int off;
519476404edcSAsim Jamshed      bpf_int32 v1, v2;
519576404edcSAsim Jamshed {
519676404edcSAsim Jamshed     struct block *b1, *b2;
519776404edcSAsim Jamshed 
519876404edcSAsim Jamshed     if (v1 > v2)
519976404edcSAsim Jamshed     {
520076404edcSAsim Jamshed         /*
520176404edcSAsim Jamshed          * Reverse the order of the ports, so v1 is the lower one.
520276404edcSAsim Jamshed          */
520376404edcSAsim Jamshed         bpf_int32 vtemp;
520476404edcSAsim Jamshed 
520576404edcSAsim Jamshed         vtemp = v1;
520676404edcSAsim Jamshed         v1 = v2;
520776404edcSAsim Jamshed         v2 = vtemp;
520876404edcSAsim Jamshed     }
520976404edcSAsim Jamshed 
521076404edcSAsim Jamshed     b1 = gen_cmp_ge(OR_TRAN_IPV6, off, BPF_H, v1);
521176404edcSAsim Jamshed     b2 = gen_cmp_le(OR_TRAN_IPV6, off, BPF_H, v2);
521276404edcSAsim Jamshed 
521376404edcSAsim Jamshed     gen_and(b1, b2);
521476404edcSAsim Jamshed 
521576404edcSAsim Jamshed     return b2;
521676404edcSAsim Jamshed }
521776404edcSAsim Jamshed 
gen_portrangeop6(port1,port2,proto,dir)521876404edcSAsim Jamshed struct block *gen_portrangeop6(port1, port2, proto, dir)
521976404edcSAsim Jamshed      int port1, port2;
522076404edcSAsim Jamshed      int proto;
522176404edcSAsim Jamshed      int dir;
522276404edcSAsim Jamshed {
522376404edcSAsim Jamshed     struct block *b0, *b1, *tmp;
522476404edcSAsim Jamshed 
522576404edcSAsim Jamshed     /* ip6 proto 'proto' */
522676404edcSAsim Jamshed     b0 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32) proto);
522776404edcSAsim Jamshed 
522876404edcSAsim Jamshed     switch (dir)
522976404edcSAsim Jamshed     {
523076404edcSAsim Jamshed         case Q_SRC:
523176404edcSAsim Jamshed             b1 = gen_portrangeatom6(0, (bpf_int32) port1, (bpf_int32) port2);
523276404edcSAsim Jamshed             break;
523376404edcSAsim Jamshed 
523476404edcSAsim Jamshed         case Q_DST:
523576404edcSAsim Jamshed             b1 = gen_portrangeatom6(2, (bpf_int32) port1, (bpf_int32) port2);
523676404edcSAsim Jamshed             break;
523776404edcSAsim Jamshed 
523876404edcSAsim Jamshed         case Q_OR:
523976404edcSAsim Jamshed         case Q_DEFAULT:
524076404edcSAsim Jamshed             tmp = gen_portrangeatom6(0, (bpf_int32) port1, (bpf_int32) port2);
524176404edcSAsim Jamshed             b1 = gen_portrangeatom6(2, (bpf_int32) port1, (bpf_int32) port2);
524276404edcSAsim Jamshed             gen_or(tmp, b1);
524376404edcSAsim Jamshed             break;
524476404edcSAsim Jamshed 
524576404edcSAsim Jamshed         case Q_AND:
524676404edcSAsim Jamshed             tmp = gen_portrangeatom6(0, (bpf_int32) port1, (bpf_int32) port2);
524776404edcSAsim Jamshed             b1 = gen_portrangeatom6(2, (bpf_int32) port1, (bpf_int32) port2);
524876404edcSAsim Jamshed             gen_and(tmp, b1);
524976404edcSAsim Jamshed             break;
525076404edcSAsim Jamshed 
525176404edcSAsim Jamshed         default:
525276404edcSAsim Jamshed             abort();
525376404edcSAsim Jamshed     }
525476404edcSAsim Jamshed     gen_and(b0, b1);
525576404edcSAsim Jamshed 
525676404edcSAsim Jamshed     return b1;
525776404edcSAsim Jamshed }
525876404edcSAsim Jamshed 
gen_portrange6(port1,port2,ip_proto,dir)525976404edcSAsim Jamshed static struct block *gen_portrange6(port1, port2, ip_proto, dir)
526076404edcSAsim Jamshed      int port1, port2;
526176404edcSAsim Jamshed      int ip_proto;
526276404edcSAsim Jamshed      int dir;
526376404edcSAsim Jamshed {
526476404edcSAsim Jamshed     struct block *b0, *b1, *tmp;
526576404edcSAsim Jamshed 
526676404edcSAsim Jamshed     /* link proto ip6 */
526776404edcSAsim Jamshed     b0 = gen_linktype(ETHERTYPE_IPV6);
526876404edcSAsim Jamshed 
526976404edcSAsim Jamshed     switch (ip_proto)
527076404edcSAsim Jamshed     {
527176404edcSAsim Jamshed         case IPPROTO_UDP:
527276404edcSAsim Jamshed         case IPPROTO_TCP:
527376404edcSAsim Jamshed         case IPPROTO_SCTP:
527476404edcSAsim Jamshed             b1 = gen_portrangeop6(port1, port2, ip_proto, dir);
527576404edcSAsim Jamshed             break;
527676404edcSAsim Jamshed 
527776404edcSAsim Jamshed         case PROTO_UNDEF:
527876404edcSAsim Jamshed             tmp = gen_portrangeop6(port1, port2, IPPROTO_TCP, dir);
527976404edcSAsim Jamshed             b1 = gen_portrangeop6(port1, port2, IPPROTO_UDP, dir);
528076404edcSAsim Jamshed             gen_or(tmp, b1);
528176404edcSAsim Jamshed             tmp = gen_portrangeop6(port1, port2, IPPROTO_SCTP, dir);
528276404edcSAsim Jamshed             gen_or(tmp, b1);
528376404edcSAsim Jamshed             break;
528476404edcSAsim Jamshed 
528576404edcSAsim Jamshed         default:
528676404edcSAsim Jamshed             abort();
528776404edcSAsim Jamshed     }
528876404edcSAsim Jamshed     gen_and(b0, b1);
528976404edcSAsim Jamshed     return b1;
529076404edcSAsim Jamshed }
529176404edcSAsim Jamshed #endif /* INET6 */
529276404edcSAsim Jamshed 
lookup_proto(name,proto)529376404edcSAsim Jamshed static int lookup_proto(name, proto)
529476404edcSAsim Jamshed      register const char *name;
529576404edcSAsim Jamshed      register int proto;
529676404edcSAsim Jamshed {
529776404edcSAsim Jamshed     register int v;
529876404edcSAsim Jamshed 
529976404edcSAsim Jamshed     switch (proto)
530076404edcSAsim Jamshed     {
530176404edcSAsim Jamshed 
530276404edcSAsim Jamshed         case Q_DEFAULT:
530376404edcSAsim Jamshed         case Q_IP:
530476404edcSAsim Jamshed         case Q_IPV6:
530576404edcSAsim Jamshed             v = pcap_nametoproto(name);
530676404edcSAsim Jamshed             if (v == PROTO_UNDEF)
530776404edcSAsim Jamshed                 bpf_error("unknown ip proto '%s'", name);
530876404edcSAsim Jamshed             break;
530976404edcSAsim Jamshed 
531076404edcSAsim Jamshed         case Q_LINK:
531176404edcSAsim Jamshed             /* XXX should look up h/w protocol type based on linktype */
531276404edcSAsim Jamshed             v = pcap_nametoeproto(name);
531376404edcSAsim Jamshed             if (v == PROTO_UNDEF)
531476404edcSAsim Jamshed             {
531576404edcSAsim Jamshed                 v = pcap_nametollc(name);
531676404edcSAsim Jamshed                 if (v == PROTO_UNDEF)
531776404edcSAsim Jamshed                     bpf_error("unknown ether proto '%s'", name);
531876404edcSAsim Jamshed             }
531976404edcSAsim Jamshed             break;
532076404edcSAsim Jamshed 
532176404edcSAsim Jamshed         case Q_ISO:
532276404edcSAsim Jamshed             if (strcmp(name, "esis") == 0)
532376404edcSAsim Jamshed                 v = ISO9542_ESIS;
532476404edcSAsim Jamshed             else if (strcmp(name, "isis") == 0)
532576404edcSAsim Jamshed                 v = ISO10589_ISIS;
532676404edcSAsim Jamshed             else if (strcmp(name, "clnp") == 0)
532776404edcSAsim Jamshed                 v = ISO8473_CLNP;
532876404edcSAsim Jamshed             else
532976404edcSAsim Jamshed                 bpf_error("unknown osi proto '%s'", name);
533076404edcSAsim Jamshed             break;
533176404edcSAsim Jamshed 
533276404edcSAsim Jamshed         default:
533376404edcSAsim Jamshed             v = PROTO_UNDEF;
533476404edcSAsim Jamshed             break;
533576404edcSAsim Jamshed     }
533676404edcSAsim Jamshed     return v;
533776404edcSAsim Jamshed }
533876404edcSAsim Jamshed 
gen_protochain(v,proto,dir)533976404edcSAsim Jamshed static struct block *gen_protochain(v, proto, dir)
534076404edcSAsim Jamshed      int v;
534176404edcSAsim Jamshed      int proto;
534276404edcSAsim Jamshed      int dir;
534376404edcSAsim Jamshed {
534476404edcSAsim Jamshed #ifdef NO_PROTOCHAIN
534576404edcSAsim Jamshed     return gen_proto(v, proto, dir);
534676404edcSAsim Jamshed #else
534776404edcSAsim Jamshed     struct block *b0, *b;
534876404edcSAsim Jamshed     struct slist *s[100];
534976404edcSAsim Jamshed     int fix2, fix3, fix4, fix5;
535076404edcSAsim Jamshed     int ahcheck, again, end;
535176404edcSAsim Jamshed     int i, max;
535276404edcSAsim Jamshed     int reg2 = alloc_reg();
535376404edcSAsim Jamshed 
535476404edcSAsim Jamshed     memset(s, 0, sizeof(s));
535576404edcSAsim Jamshed     fix2 = fix3 = fix4 = fix5 = 0;
535676404edcSAsim Jamshed 
535776404edcSAsim Jamshed     switch (proto)
535876404edcSAsim Jamshed     {
535976404edcSAsim Jamshed         case Q_IP:
536076404edcSAsim Jamshed         case Q_IPV6:
536176404edcSAsim Jamshed             break;
536276404edcSAsim Jamshed         case Q_DEFAULT:
536376404edcSAsim Jamshed             b0 = gen_protochain(v, Q_IP, dir);
536476404edcSAsim Jamshed             b = gen_protochain(v, Q_IPV6, dir);
536576404edcSAsim Jamshed             gen_or(b0, b);
536676404edcSAsim Jamshed             return b;
536776404edcSAsim Jamshed         default:
536876404edcSAsim Jamshed             bpf_error("bad protocol applied for 'protochain'");
536976404edcSAsim Jamshed      /*NOTREACHED*/}
537076404edcSAsim Jamshed 
537176404edcSAsim Jamshed     /*
537276404edcSAsim Jamshed      * We don't handle variable-length prefixes before the link-layer
537376404edcSAsim Jamshed      * header, or variable-length link-layer headers, here yet.
537476404edcSAsim Jamshed      * We might want to add BPF instructions to do the protochain
537576404edcSAsim Jamshed      * work, to simplify that and, on platforms that have a BPF
537676404edcSAsim Jamshed      * interpreter with the new instructions, let the filtering
537776404edcSAsim Jamshed      * be done in the kernel.  (We already require a modified BPF
537876404edcSAsim Jamshed      * engine to do the protochain stuff, to support backward
537976404edcSAsim Jamshed      * branches, and backward branch support is unlikely to appear
538076404edcSAsim Jamshed      * in kernel BPF engines.)
538176404edcSAsim Jamshed      */
538276404edcSAsim Jamshed     switch (linktype)
538376404edcSAsim Jamshed     {
538476404edcSAsim Jamshed 
538576404edcSAsim Jamshed         case DLT_IEEE802_11:
538676404edcSAsim Jamshed         case DLT_PRISM_HEADER:
538776404edcSAsim Jamshed         case DLT_IEEE802_11_RADIO_AVS:
538876404edcSAsim Jamshed         case DLT_IEEE802_11_RADIO:
538976404edcSAsim Jamshed         case DLT_PPI:
539076404edcSAsim Jamshed             bpf_error("'protochain' not supported with 802.11");
539176404edcSAsim Jamshed     }
539276404edcSAsim Jamshed 
539376404edcSAsim Jamshed     no_optimize = 1;            /*this code is not compatible with optimzer yet */
539476404edcSAsim Jamshed 
539576404edcSAsim Jamshed     /*
539676404edcSAsim Jamshed      * s[0] is a dummy entry to protect other BPF insn from damage
539776404edcSAsim Jamshed      * by s[fix] = foo with uninitialized variable "fix".  It is somewhat
539876404edcSAsim Jamshed      * hard to find interdependency made by jump table fixup.
539976404edcSAsim Jamshed      */
540076404edcSAsim Jamshed     i = 0;
540176404edcSAsim Jamshed     s[i] = new_stmt(0);         /*dummy */
540276404edcSAsim Jamshed     i++;
540376404edcSAsim Jamshed 
540476404edcSAsim Jamshed     switch (proto)
540576404edcSAsim Jamshed     {
540676404edcSAsim Jamshed         case Q_IP:
540776404edcSAsim Jamshed             b0 = gen_linktype(ETHERTYPE_IP);
540876404edcSAsim Jamshed 
540976404edcSAsim Jamshed             /* A = ip->ip_p */
541076404edcSAsim Jamshed             s[i] = new_stmt(BPF_LD | BPF_ABS | BPF_B);
541176404edcSAsim Jamshed             s[i]->s.k = off_macpl + off_nl + 9;
541276404edcSAsim Jamshed             i++;
541376404edcSAsim Jamshed             /* X = ip->ip_hl << 2 */
541476404edcSAsim Jamshed             s[i] = new_stmt(BPF_LDX | BPF_MSH | BPF_B);
541576404edcSAsim Jamshed             s[i]->s.k = off_macpl + off_nl;
541676404edcSAsim Jamshed             i++;
541776404edcSAsim Jamshed             break;
541876404edcSAsim Jamshed #ifdef INET6
541976404edcSAsim Jamshed         case Q_IPV6:
542076404edcSAsim Jamshed             b0 = gen_linktype(ETHERTYPE_IPV6);
542176404edcSAsim Jamshed 
542276404edcSAsim Jamshed             /* A = ip6->ip_nxt */
542376404edcSAsim Jamshed             s[i] = new_stmt(BPF_LD | BPF_ABS | BPF_B);
542476404edcSAsim Jamshed             s[i]->s.k = off_macpl + off_nl + 6;
542576404edcSAsim Jamshed             i++;
542676404edcSAsim Jamshed             /* X = sizeof(struct ip6_hdr) */
542776404edcSAsim Jamshed             s[i] = new_stmt(BPF_LDX | BPF_IMM);
542876404edcSAsim Jamshed             s[i]->s.k = 40;
542976404edcSAsim Jamshed             i++;
543076404edcSAsim Jamshed             break;
543176404edcSAsim Jamshed #endif
543276404edcSAsim Jamshed         default:
543376404edcSAsim Jamshed             bpf_error("unsupported proto to gen_protochain");
543476404edcSAsim Jamshed      /*NOTREACHED*/}
543576404edcSAsim Jamshed 
543676404edcSAsim Jamshed     /* again: if (A == v) goto end; else fall through; */
543776404edcSAsim Jamshed     again = i;
543876404edcSAsim Jamshed     s[i] = new_stmt(BPF_JMP | BPF_JEQ | BPF_K);
543976404edcSAsim Jamshed     s[i]->s.k = v;
544076404edcSAsim Jamshed     s[i]->s.jt = NULL;          /*later */
544176404edcSAsim Jamshed     s[i]->s.jf = NULL;          /*update in next stmt */
544276404edcSAsim Jamshed     fix5 = i;
544376404edcSAsim Jamshed     i++;
544476404edcSAsim Jamshed 
544576404edcSAsim Jamshed #ifndef IPPROTO_NONE
544676404edcSAsim Jamshed #define IPPROTO_NONE	59
544776404edcSAsim Jamshed #endif
544876404edcSAsim Jamshed     /* if (A == IPPROTO_NONE) goto end */
544976404edcSAsim Jamshed     s[i] = new_stmt(BPF_JMP | BPF_JEQ | BPF_K);
545076404edcSAsim Jamshed     s[i]->s.jt = NULL;          /*later */
545176404edcSAsim Jamshed     s[i]->s.jf = NULL;          /*update in next stmt */
545276404edcSAsim Jamshed     s[i]->s.k = IPPROTO_NONE;
545376404edcSAsim Jamshed     s[fix5]->s.jf = s[i];
545476404edcSAsim Jamshed     fix2 = i;
545576404edcSAsim Jamshed     i++;
545676404edcSAsim Jamshed 
545776404edcSAsim Jamshed #ifdef INET6
545876404edcSAsim Jamshed     if (proto == Q_IPV6)
545976404edcSAsim Jamshed     {
546076404edcSAsim Jamshed         int v6start, v6end, v6advance, j;
546176404edcSAsim Jamshed 
546276404edcSAsim Jamshed         v6start = i;
546376404edcSAsim Jamshed         /* if (A == IPPROTO_HOPOPTS) goto v6advance */
546476404edcSAsim Jamshed         s[i] = new_stmt(BPF_JMP | BPF_JEQ | BPF_K);
546576404edcSAsim Jamshed         s[i]->s.jt = NULL;      /*later */
546676404edcSAsim Jamshed         s[i]->s.jf = NULL;      /*update in next stmt */
546776404edcSAsim Jamshed         s[i]->s.k = IPPROTO_HOPOPTS;
546876404edcSAsim Jamshed         s[fix2]->s.jf = s[i];
546976404edcSAsim Jamshed         i++;
547076404edcSAsim Jamshed         /* if (A == IPPROTO_DSTOPTS) goto v6advance */
547176404edcSAsim Jamshed         s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP | BPF_JEQ | BPF_K);
547276404edcSAsim Jamshed         s[i]->s.jt = NULL;      /*later */
547376404edcSAsim Jamshed         s[i]->s.jf = NULL;      /*update in next stmt */
547476404edcSAsim Jamshed         s[i]->s.k = IPPROTO_DSTOPTS;
547576404edcSAsim Jamshed         i++;
547676404edcSAsim Jamshed         /* if (A == IPPROTO_ROUTING) goto v6advance */
547776404edcSAsim Jamshed         s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP | BPF_JEQ | BPF_K);
547876404edcSAsim Jamshed         s[i]->s.jt = NULL;      /*later */
547976404edcSAsim Jamshed         s[i]->s.jf = NULL;      /*update in next stmt */
548076404edcSAsim Jamshed         s[i]->s.k = IPPROTO_ROUTING;
548176404edcSAsim Jamshed         i++;
548276404edcSAsim Jamshed         /* if (A == IPPROTO_FRAGMENT) goto v6advance; else goto ahcheck; */
548376404edcSAsim Jamshed         s[i - 1]->s.jf = s[i] = new_stmt(BPF_JMP | BPF_JEQ | BPF_K);
548476404edcSAsim Jamshed         s[i]->s.jt = NULL;      /*later */
548576404edcSAsim Jamshed         s[i]->s.jf = NULL;      /*later */
548676404edcSAsim Jamshed         s[i]->s.k = IPPROTO_FRAGMENT;
548776404edcSAsim Jamshed         fix3 = i;
548876404edcSAsim Jamshed         v6end = i;
548976404edcSAsim Jamshed         i++;
549076404edcSAsim Jamshed 
549176404edcSAsim Jamshed         /* v6advance: */
549276404edcSAsim Jamshed         v6advance = i;
549376404edcSAsim Jamshed 
549476404edcSAsim Jamshed         /*
549576404edcSAsim Jamshed          * in short,
549676404edcSAsim Jamshed          * A = P[X];
549776404edcSAsim Jamshed          * X = X + (P[X + 1] + 1) * 8;
549876404edcSAsim Jamshed          */
549976404edcSAsim Jamshed         /* A = X */
550076404edcSAsim Jamshed         s[i] = new_stmt(BPF_MISC | BPF_TXA);
550176404edcSAsim Jamshed         i++;
550276404edcSAsim Jamshed         /* A = P[X + packet head] */
550376404edcSAsim Jamshed         s[i] = new_stmt(BPF_LD | BPF_IND | BPF_B);
550476404edcSAsim Jamshed         s[i]->s.k = off_macpl + off_nl;
550576404edcSAsim Jamshed         i++;
550676404edcSAsim Jamshed         /* MEM[reg2] = A */
550776404edcSAsim Jamshed         s[i] = new_stmt(BPF_ST);
550876404edcSAsim Jamshed         s[i]->s.k = reg2;
550976404edcSAsim Jamshed         i++;
551076404edcSAsim Jamshed         /* A = X */
551176404edcSAsim Jamshed         s[i] = new_stmt(BPF_MISC | BPF_TXA);
551276404edcSAsim Jamshed         i++;
551376404edcSAsim Jamshed         /* A += 1 */
551476404edcSAsim Jamshed         s[i] = new_stmt(BPF_ALU | BPF_ADD | BPF_K);
551576404edcSAsim Jamshed         s[i]->s.k = 1;
551676404edcSAsim Jamshed         i++;
551776404edcSAsim Jamshed         /* X = A */
551876404edcSAsim Jamshed         s[i] = new_stmt(BPF_MISC | BPF_TAX);
551976404edcSAsim Jamshed         i++;
552076404edcSAsim Jamshed         /* A = P[X + packet head]; */
552176404edcSAsim Jamshed         s[i] = new_stmt(BPF_LD | BPF_IND | BPF_B);
552276404edcSAsim Jamshed         s[i]->s.k = off_macpl + off_nl;
552376404edcSAsim Jamshed         i++;
552476404edcSAsim Jamshed         /* A += 1 */
552576404edcSAsim Jamshed         s[i] = new_stmt(BPF_ALU | BPF_ADD | BPF_K);
552676404edcSAsim Jamshed         s[i]->s.k = 1;
552776404edcSAsim Jamshed         i++;
552876404edcSAsim Jamshed         /* A *= 8 */
552976404edcSAsim Jamshed         s[i] = new_stmt(BPF_ALU | BPF_MUL | BPF_K);
553076404edcSAsim Jamshed         s[i]->s.k = 8;
553176404edcSAsim Jamshed         i++;
553276404edcSAsim Jamshed         /* X = A; */
553376404edcSAsim Jamshed         s[i] = new_stmt(BPF_MISC | BPF_TAX);
553476404edcSAsim Jamshed         i++;
553576404edcSAsim Jamshed         /* A = MEM[reg2] */
553676404edcSAsim Jamshed         s[i] = new_stmt(BPF_LD | BPF_MEM);
553776404edcSAsim Jamshed         s[i]->s.k = reg2;
553876404edcSAsim Jamshed         i++;
553976404edcSAsim Jamshed 
554076404edcSAsim Jamshed         /* goto again; (must use BPF_JA for backward jump) */
554176404edcSAsim Jamshed         s[i] = new_stmt(BPF_JMP | BPF_JA);
554276404edcSAsim Jamshed         s[i]->s.k = again - i - 1;
554376404edcSAsim Jamshed         s[i - 1]->s.jf = s[i];
554476404edcSAsim Jamshed         i++;
554576404edcSAsim Jamshed 
554676404edcSAsim Jamshed         /* fixup */
554776404edcSAsim Jamshed         for (j = v6start; j <= v6end; j++)
554876404edcSAsim Jamshed             s[j]->s.jt = s[v6advance];
554976404edcSAsim Jamshed     }
555076404edcSAsim Jamshed     else
555176404edcSAsim Jamshed #endif
555276404edcSAsim Jamshed     {
555376404edcSAsim Jamshed         /* nop */
555476404edcSAsim Jamshed         s[i] = new_stmt(BPF_ALU | BPF_ADD | BPF_K);
555576404edcSAsim Jamshed         s[i]->s.k = 0;
555676404edcSAsim Jamshed         s[fix2]->s.jf = s[i];
555776404edcSAsim Jamshed         i++;
555876404edcSAsim Jamshed     }
555976404edcSAsim Jamshed 
556076404edcSAsim Jamshed     /* ahcheck: */
556176404edcSAsim Jamshed     ahcheck = i;
556276404edcSAsim Jamshed     /* if (A == IPPROTO_AH) then fall through; else goto end; */
556376404edcSAsim Jamshed     s[i] = new_stmt(BPF_JMP | BPF_JEQ | BPF_K);
556476404edcSAsim Jamshed     s[i]->s.jt = NULL;          /*later */
556576404edcSAsim Jamshed     s[i]->s.jf = NULL;          /*later */
556676404edcSAsim Jamshed     s[i]->s.k = IPPROTO_AH;
556776404edcSAsim Jamshed     if (fix3)
556876404edcSAsim Jamshed         s[fix3]->s.jf = s[ahcheck];
556976404edcSAsim Jamshed     fix4 = i;
557076404edcSAsim Jamshed     i++;
557176404edcSAsim Jamshed 
557276404edcSAsim Jamshed     /*
557376404edcSAsim Jamshed      * in short,
557476404edcSAsim Jamshed      * A = P[X];
557576404edcSAsim Jamshed      * X = X + (P[X + 1] + 2) * 4;
557676404edcSAsim Jamshed      */
557776404edcSAsim Jamshed     /* A = X */
557876404edcSAsim Jamshed     s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC | BPF_TXA);
557976404edcSAsim Jamshed     i++;
558076404edcSAsim Jamshed     /* A = P[X + packet head]; */
558176404edcSAsim Jamshed     s[i] = new_stmt(BPF_LD | BPF_IND | BPF_B);
558276404edcSAsim Jamshed     s[i]->s.k = off_macpl + off_nl;
558376404edcSAsim Jamshed     i++;
558476404edcSAsim Jamshed     /* MEM[reg2] = A */
558576404edcSAsim Jamshed     s[i] = new_stmt(BPF_ST);
558676404edcSAsim Jamshed     s[i]->s.k = reg2;
558776404edcSAsim Jamshed     i++;
558876404edcSAsim Jamshed     /* A = X */
558976404edcSAsim Jamshed     s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC | BPF_TXA);
559076404edcSAsim Jamshed     i++;
559176404edcSAsim Jamshed     /* A += 1 */
559276404edcSAsim Jamshed     s[i] = new_stmt(BPF_ALU | BPF_ADD | BPF_K);
559376404edcSAsim Jamshed     s[i]->s.k = 1;
559476404edcSAsim Jamshed     i++;
559576404edcSAsim Jamshed     /* X = A */
559676404edcSAsim Jamshed     s[i] = new_stmt(BPF_MISC | BPF_TAX);
559776404edcSAsim Jamshed     i++;
559876404edcSAsim Jamshed     /* A = P[X + packet head] */
559976404edcSAsim Jamshed     s[i] = new_stmt(BPF_LD | BPF_IND | BPF_B);
560076404edcSAsim Jamshed     s[i]->s.k = off_macpl + off_nl;
560176404edcSAsim Jamshed     i++;
560276404edcSAsim Jamshed     /* A += 2 */
560376404edcSAsim Jamshed     s[i] = new_stmt(BPF_ALU | BPF_ADD | BPF_K);
560476404edcSAsim Jamshed     s[i]->s.k = 2;
560576404edcSAsim Jamshed     i++;
560676404edcSAsim Jamshed     /* A *= 4 */
560776404edcSAsim Jamshed     s[i] = new_stmt(BPF_ALU | BPF_MUL | BPF_K);
560876404edcSAsim Jamshed     s[i]->s.k = 4;
560976404edcSAsim Jamshed     i++;
561076404edcSAsim Jamshed     /* X = A; */
561176404edcSAsim Jamshed     s[i] = new_stmt(BPF_MISC | BPF_TAX);
561276404edcSAsim Jamshed     i++;
561376404edcSAsim Jamshed     /* A = MEM[reg2] */
561476404edcSAsim Jamshed     s[i] = new_stmt(BPF_LD | BPF_MEM);
561576404edcSAsim Jamshed     s[i]->s.k = reg2;
561676404edcSAsim Jamshed     i++;
561776404edcSAsim Jamshed 
561876404edcSAsim Jamshed     /* goto again; (must use BPF_JA for backward jump) */
561976404edcSAsim Jamshed     s[i] = new_stmt(BPF_JMP | BPF_JA);
562076404edcSAsim Jamshed     s[i]->s.k = again - i - 1;
562176404edcSAsim Jamshed     i++;
562276404edcSAsim Jamshed 
562376404edcSAsim Jamshed     /* end: nop */
562476404edcSAsim Jamshed     end = i;
562576404edcSAsim Jamshed     s[i] = new_stmt(BPF_ALU | BPF_ADD | BPF_K);
562676404edcSAsim Jamshed     s[i]->s.k = 0;
562776404edcSAsim Jamshed     s[fix2]->s.jt = s[end];
562876404edcSAsim Jamshed     s[fix4]->s.jf = s[end];
562976404edcSAsim Jamshed     s[fix5]->s.jt = s[end];
563076404edcSAsim Jamshed     i++;
563176404edcSAsim Jamshed 
563276404edcSAsim Jamshed     /*
563376404edcSAsim Jamshed      * make slist chain
563476404edcSAsim Jamshed      */
563576404edcSAsim Jamshed     max = i;
563676404edcSAsim Jamshed     for (i = 0; i < max - 1; i++)
563776404edcSAsim Jamshed         s[i]->next = s[i + 1];
563876404edcSAsim Jamshed     s[max - 1]->next = NULL;
563976404edcSAsim Jamshed 
564076404edcSAsim Jamshed     /*
564176404edcSAsim Jamshed      * emit final check
564276404edcSAsim Jamshed      */
564376404edcSAsim Jamshed     b = new_block(JMP(BPF_JEQ));
564476404edcSAsim Jamshed     b->stmts = s[1];            /*remember, s[0] is dummy */
564576404edcSAsim Jamshed     b->s.k = v;
564676404edcSAsim Jamshed 
564776404edcSAsim Jamshed     free_reg(reg2);
564876404edcSAsim Jamshed 
564976404edcSAsim Jamshed     gen_and(b0, b);
565076404edcSAsim Jamshed     return b;
565176404edcSAsim Jamshed #endif
565276404edcSAsim Jamshed }
565376404edcSAsim Jamshed 
gen_check_802_11_data_frame()565476404edcSAsim Jamshed static struct block *gen_check_802_11_data_frame()
565576404edcSAsim Jamshed {
565676404edcSAsim Jamshed     struct slist *s;
565776404edcSAsim Jamshed     struct block *b0, *b1;
565876404edcSAsim Jamshed 
565976404edcSAsim Jamshed     /*
566076404edcSAsim Jamshed      * A data frame has the 0x08 bit (b3) in the frame control field set
566176404edcSAsim Jamshed      * and the 0x04 bit (b2) clear.
566276404edcSAsim Jamshed      */
566376404edcSAsim Jamshed     s = gen_load_a(OR_LINK, 0, BPF_B);
566476404edcSAsim Jamshed     b0 = new_block(JMP(BPF_JSET));
566576404edcSAsim Jamshed     b0->s.k = 0x08;
566676404edcSAsim Jamshed     b0->stmts = s;
566776404edcSAsim Jamshed 
566876404edcSAsim Jamshed     s = gen_load_a(OR_LINK, 0, BPF_B);
566976404edcSAsim Jamshed     b1 = new_block(JMP(BPF_JSET));
567076404edcSAsim Jamshed     b1->s.k = 0x04;
567176404edcSAsim Jamshed     b1->stmts = s;
567276404edcSAsim Jamshed     gen_not(b1);
567376404edcSAsim Jamshed 
567476404edcSAsim Jamshed     gen_and(b1, b0);
567576404edcSAsim Jamshed 
567676404edcSAsim Jamshed     return b0;
567776404edcSAsim Jamshed }
567876404edcSAsim Jamshed 
567976404edcSAsim Jamshed /*
568076404edcSAsim Jamshed  * Generate code that checks whether the packet is a packet for protocol
568176404edcSAsim Jamshed  * <proto> and whether the type field in that protocol's header has
568276404edcSAsim Jamshed  * the value <v>, e.g. if <proto> is Q_IP, it checks whether it's an
568376404edcSAsim Jamshed  * IP packet and checks the protocol number in the IP header against <v>.
568476404edcSAsim Jamshed  *
568576404edcSAsim Jamshed  * If <proto> is Q_DEFAULT, i.e. just "proto" was specified, it checks
568676404edcSAsim Jamshed  * against Q_IP and Q_IPV6.
568776404edcSAsim Jamshed  */
gen_proto(v,proto,dir)568876404edcSAsim Jamshed static struct block *gen_proto(v, proto, dir)
568976404edcSAsim Jamshed      int v;
569076404edcSAsim Jamshed      int proto;
569176404edcSAsim Jamshed      int dir;
569276404edcSAsim Jamshed {
569376404edcSAsim Jamshed     struct block *b0, *b1;
569476404edcSAsim Jamshed 
569576404edcSAsim Jamshed     if (dir != Q_DEFAULT)
569676404edcSAsim Jamshed         bpf_error("direction applied to 'proto'");
569776404edcSAsim Jamshed 
569876404edcSAsim Jamshed     switch (proto)
569976404edcSAsim Jamshed     {
570076404edcSAsim Jamshed         case Q_DEFAULT:
570176404edcSAsim Jamshed #ifdef INET6
570276404edcSAsim Jamshed             b0 = gen_proto(v, Q_IP, dir);
570376404edcSAsim Jamshed             b1 = gen_proto(v, Q_IPV6, dir);
570476404edcSAsim Jamshed             gen_or(b0, b1);
570576404edcSAsim Jamshed             return b1;
570676404edcSAsim Jamshed #else
570776404edcSAsim Jamshed              /*FALLTHROUGH*/
570876404edcSAsim Jamshed #endif
570976404edcSAsim Jamshed         case Q_IP:
571076404edcSAsim Jamshed             /*
571176404edcSAsim Jamshed              * For FDDI, RFC 1188 says that SNAP encapsulation is used,
571276404edcSAsim Jamshed              * not LLC encapsulation with LLCSAP_IP.
571376404edcSAsim Jamshed              *
571476404edcSAsim Jamshed              * For IEEE 802 networks - which includes 802.5 token ring
571576404edcSAsim Jamshed              * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042
571676404edcSAsim Jamshed              * says that SNAP encapsulation is used, not LLC encapsulation
571776404edcSAsim Jamshed              * with LLCSAP_IP.
571876404edcSAsim Jamshed              *
571976404edcSAsim Jamshed              * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and
572076404edcSAsim Jamshed              * RFC 2225 say that SNAP encapsulation is used, not LLC
572176404edcSAsim Jamshed              * encapsulation with LLCSAP_IP.
572276404edcSAsim Jamshed              *
572376404edcSAsim Jamshed              * So we always check for ETHERTYPE_IP.
572476404edcSAsim Jamshed              */
572576404edcSAsim Jamshed             b0 = gen_linktype(ETHERTYPE_IP);
572676404edcSAsim Jamshed #ifndef CHASE_CHAIN
572776404edcSAsim Jamshed             b1 = gen_cmp(OR_NET, 9, BPF_B, (bpf_int32) v);
572876404edcSAsim Jamshed #else
572976404edcSAsim Jamshed             b1 = gen_protochain(v, Q_IP);
573076404edcSAsim Jamshed #endif
573176404edcSAsim Jamshed             gen_and(b0, b1);
573276404edcSAsim Jamshed             return b1;
573376404edcSAsim Jamshed 
573476404edcSAsim Jamshed         case Q_ISO:
573576404edcSAsim Jamshed             switch (linktype)
573676404edcSAsim Jamshed             {
573776404edcSAsim Jamshed 
573876404edcSAsim Jamshed                 case DLT_FRELAY:
573976404edcSAsim Jamshed                     /*
574076404edcSAsim Jamshed                      * Frame Relay packets typically have an OSI
574176404edcSAsim Jamshed                      * NLPID at the beginning; "gen_linktype(LLCSAP_ISONS)"
574276404edcSAsim Jamshed                      * generates code to check for all the OSI
574376404edcSAsim Jamshed                      * NLPIDs, so calling it and then adding a check
574476404edcSAsim Jamshed                      * for the particular NLPID for which we're
574576404edcSAsim Jamshed                      * looking is bogus, as we can just check for
574676404edcSAsim Jamshed                      * the NLPID.
574776404edcSAsim Jamshed                      *
574876404edcSAsim Jamshed                      * What we check for is the NLPID and a frame
574976404edcSAsim Jamshed                      * control field value of UI, i.e. 0x03 followed
575076404edcSAsim Jamshed                      * by the NLPID.
575176404edcSAsim Jamshed                      *
575276404edcSAsim Jamshed                      * XXX - assumes a 2-byte Frame Relay header with
575376404edcSAsim Jamshed                      * DLCI and flags.  What if the address is longer?
575476404edcSAsim Jamshed                      *
575576404edcSAsim Jamshed                      * XXX - what about SNAP-encapsulated frames?
575676404edcSAsim Jamshed                      */
575776404edcSAsim Jamshed                     return gen_cmp(OR_LINK, 2, BPF_H, (0x03 << 8) | v);
575876404edcSAsim Jamshed                      /*NOTREACHED*/ break;
575976404edcSAsim Jamshed 
576076404edcSAsim Jamshed                 case DLT_C_HDLC:
576176404edcSAsim Jamshed                     /*
576276404edcSAsim Jamshed                      * Cisco uses an Ethertype lookalike - for OSI,
576376404edcSAsim Jamshed                      * it's 0xfefe.
576476404edcSAsim Jamshed                      */
576576404edcSAsim Jamshed                     b0 = gen_linktype(LLCSAP_ISONS << 8 | LLCSAP_ISONS);
576676404edcSAsim Jamshed                     /* OSI in C-HDLC is stuffed with a fudge byte */
576776404edcSAsim Jamshed                     b1 = gen_cmp(OR_NET_NOSNAP, 1, BPF_B, (long) v);
576876404edcSAsim Jamshed                     gen_and(b0, b1);
576976404edcSAsim Jamshed                     return b1;
577076404edcSAsim Jamshed 
577176404edcSAsim Jamshed                 default:
577276404edcSAsim Jamshed                     b0 = gen_linktype(LLCSAP_ISONS);
577376404edcSAsim Jamshed                     b1 = gen_cmp(OR_NET_NOSNAP, 0, BPF_B, (long) v);
577476404edcSAsim Jamshed                     gen_and(b0, b1);
577576404edcSAsim Jamshed                     return b1;
577676404edcSAsim Jamshed             }
577776404edcSAsim Jamshed 
577876404edcSAsim Jamshed         case Q_ISIS:
577976404edcSAsim Jamshed             b0 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
578076404edcSAsim Jamshed             /*
578176404edcSAsim Jamshed              * 4 is the offset of the PDU type relative to the IS-IS
578276404edcSAsim Jamshed              * header.
578376404edcSAsim Jamshed              */
578476404edcSAsim Jamshed             b1 = gen_cmp(OR_NET_NOSNAP, 4, BPF_B, (long) v);
578576404edcSAsim Jamshed             gen_and(b0, b1);
578676404edcSAsim Jamshed             return b1;
578776404edcSAsim Jamshed 
578876404edcSAsim Jamshed         case Q_ARP:
578976404edcSAsim Jamshed             bpf_error("arp does not encapsulate another protocol");
579076404edcSAsim Jamshed             /* NOTREACHED */
579176404edcSAsim Jamshed 
579276404edcSAsim Jamshed         case Q_RARP:
579376404edcSAsim Jamshed             bpf_error("rarp does not encapsulate another protocol");
579476404edcSAsim Jamshed             /* NOTREACHED */
579576404edcSAsim Jamshed 
579676404edcSAsim Jamshed         case Q_ATALK:
579776404edcSAsim Jamshed             bpf_error("atalk encapsulation is not specifiable");
579876404edcSAsim Jamshed             /* NOTREACHED */
579976404edcSAsim Jamshed 
580076404edcSAsim Jamshed         case Q_DECNET:
580176404edcSAsim Jamshed             bpf_error("decnet encapsulation is not specifiable");
580276404edcSAsim Jamshed             /* NOTREACHED */
580376404edcSAsim Jamshed 
580476404edcSAsim Jamshed         case Q_SCA:
580576404edcSAsim Jamshed             bpf_error("sca does not encapsulate another protocol");
580676404edcSAsim Jamshed             /* NOTREACHED */
580776404edcSAsim Jamshed 
580876404edcSAsim Jamshed         case Q_LAT:
580976404edcSAsim Jamshed             bpf_error("lat does not encapsulate another protocol");
581076404edcSAsim Jamshed             /* NOTREACHED */
581176404edcSAsim Jamshed 
581276404edcSAsim Jamshed         case Q_MOPRC:
581376404edcSAsim Jamshed             bpf_error("moprc does not encapsulate another protocol");
581476404edcSAsim Jamshed             /* NOTREACHED */
581576404edcSAsim Jamshed 
581676404edcSAsim Jamshed         case Q_MOPDL:
581776404edcSAsim Jamshed             bpf_error("mopdl does not encapsulate another protocol");
581876404edcSAsim Jamshed             /* NOTREACHED */
581976404edcSAsim Jamshed 
582076404edcSAsim Jamshed         case Q_LINK:
582176404edcSAsim Jamshed             return gen_linktype(v);
582276404edcSAsim Jamshed 
582376404edcSAsim Jamshed         case Q_UDP:
582476404edcSAsim Jamshed             bpf_error("'udp proto' is bogus");
582576404edcSAsim Jamshed             /* NOTREACHED */
582676404edcSAsim Jamshed 
582776404edcSAsim Jamshed         case Q_TCP:
582876404edcSAsim Jamshed             bpf_error("'tcp proto' is bogus");
582976404edcSAsim Jamshed             /* NOTREACHED */
583076404edcSAsim Jamshed 
583176404edcSAsim Jamshed         case Q_SCTP:
583276404edcSAsim Jamshed             bpf_error("'sctp proto' is bogus");
583376404edcSAsim Jamshed             /* NOTREACHED */
583476404edcSAsim Jamshed 
583576404edcSAsim Jamshed         case Q_ICMP:
583676404edcSAsim Jamshed             bpf_error("'icmp proto' is bogus");
583776404edcSAsim Jamshed             /* NOTREACHED */
583876404edcSAsim Jamshed 
583976404edcSAsim Jamshed         case Q_IGMP:
584076404edcSAsim Jamshed             bpf_error("'igmp proto' is bogus");
584176404edcSAsim Jamshed             /* NOTREACHED */
584276404edcSAsim Jamshed 
584376404edcSAsim Jamshed         case Q_IGRP:
584476404edcSAsim Jamshed             bpf_error("'igrp proto' is bogus");
584576404edcSAsim Jamshed             /* NOTREACHED */
584676404edcSAsim Jamshed 
584776404edcSAsim Jamshed         case Q_PIM:
584876404edcSAsim Jamshed             bpf_error("'pim proto' is bogus");
584976404edcSAsim Jamshed             /* NOTREACHED */
585076404edcSAsim Jamshed 
585176404edcSAsim Jamshed         case Q_VRRP:
585276404edcSAsim Jamshed             bpf_error("'vrrp proto' is bogus");
585376404edcSAsim Jamshed             /* NOTREACHED */
585476404edcSAsim Jamshed 
585576404edcSAsim Jamshed #ifdef INET6
585676404edcSAsim Jamshed         case Q_IPV6:
585776404edcSAsim Jamshed             b0 = gen_linktype(ETHERTYPE_IPV6);
585876404edcSAsim Jamshed #ifndef CHASE_CHAIN
585976404edcSAsim Jamshed             b1 = gen_cmp(OR_NET, 6, BPF_B, (bpf_int32) v);
586076404edcSAsim Jamshed #else
586176404edcSAsim Jamshed             b1 = gen_protochain(v, Q_IPV6);
586276404edcSAsim Jamshed #endif
586376404edcSAsim Jamshed             gen_and(b0, b1);
586476404edcSAsim Jamshed             return b1;
586576404edcSAsim Jamshed 
586676404edcSAsim Jamshed         case Q_ICMPV6:
586776404edcSAsim Jamshed             bpf_error("'icmp6 proto' is bogus");
586876404edcSAsim Jamshed #endif /* INET6 */
586976404edcSAsim Jamshed 
587076404edcSAsim Jamshed         case Q_AH:
587176404edcSAsim Jamshed             bpf_error("'ah proto' is bogus");
587276404edcSAsim Jamshed 
587376404edcSAsim Jamshed         case Q_ESP:
587476404edcSAsim Jamshed             bpf_error("'ah proto' is bogus");
587576404edcSAsim Jamshed 
587676404edcSAsim Jamshed         case Q_STP:
587776404edcSAsim Jamshed             bpf_error("'stp proto' is bogus");
587876404edcSAsim Jamshed 
587976404edcSAsim Jamshed         case Q_IPX:
588076404edcSAsim Jamshed             bpf_error("'ipx proto' is bogus");
588176404edcSAsim Jamshed 
588276404edcSAsim Jamshed         case Q_NETBEUI:
588376404edcSAsim Jamshed             bpf_error("'netbeui proto' is bogus");
588476404edcSAsim Jamshed 
588576404edcSAsim Jamshed         case Q_RADIO:
588676404edcSAsim Jamshed             bpf_error("'radio proto' is bogus");
588776404edcSAsim Jamshed 
588876404edcSAsim Jamshed         default:
588976404edcSAsim Jamshed             abort();
589076404edcSAsim Jamshed             /* NOTREACHED */
589176404edcSAsim Jamshed     }
589276404edcSAsim Jamshed     /* NOTREACHED */
589376404edcSAsim Jamshed }
589476404edcSAsim Jamshed 
gen_scode(name,q)589576404edcSAsim Jamshed struct block *gen_scode(name, q)
589676404edcSAsim Jamshed      register const char *name;
589776404edcSAsim Jamshed      struct qual q;
589876404edcSAsim Jamshed {
589976404edcSAsim Jamshed     int proto = q.proto;
590076404edcSAsim Jamshed     int dir = q.dir;
590176404edcSAsim Jamshed     int tproto;
590276404edcSAsim Jamshed     u_char *eaddr;
590376404edcSAsim Jamshed     bpf_u_int32 mask, addr;
590476404edcSAsim Jamshed #ifndef INET6
590576404edcSAsim Jamshed     bpf_u_int32 **alist;
590676404edcSAsim Jamshed #else
590776404edcSAsim Jamshed     int tproto6;
590876404edcSAsim Jamshed     struct sockaddr_in *sin4;
590976404edcSAsim Jamshed     struct sockaddr_in6 *sin6;
591076404edcSAsim Jamshed     struct addrinfo *res, *res0;
591176404edcSAsim Jamshed     struct in6_addr mask128;
591276404edcSAsim Jamshed #endif /*INET6 */
591376404edcSAsim Jamshed     struct block *b, *tmp;
591476404edcSAsim Jamshed     int port, real_proto;
591576404edcSAsim Jamshed     int port1, port2;
591676404edcSAsim Jamshed 
591776404edcSAsim Jamshed     switch (q.addr)
591876404edcSAsim Jamshed     {
591976404edcSAsim Jamshed 
592076404edcSAsim Jamshed         case Q_NET:
592176404edcSAsim Jamshed             addr = pcap_nametonetaddr(name);
592276404edcSAsim Jamshed             if (addr == 0)
592376404edcSAsim Jamshed                 bpf_error("unknown network '%s'", name);
592476404edcSAsim Jamshed             /* Left justify network addr and calculate its network mask */
592576404edcSAsim Jamshed             mask = 0xffffffff;
592676404edcSAsim Jamshed             while (addr && (addr & 0xff000000) == 0)
592776404edcSAsim Jamshed             {
592876404edcSAsim Jamshed                 addr <<= 8;
592976404edcSAsim Jamshed                 mask <<= 8;
593076404edcSAsim Jamshed             }
593176404edcSAsim Jamshed             return gen_host(addr, mask, proto, dir, q.addr);
593276404edcSAsim Jamshed 
593376404edcSAsim Jamshed         case Q_DEFAULT:
593476404edcSAsim Jamshed         case Q_HOST:
593576404edcSAsim Jamshed             if (proto == Q_LINK)
593676404edcSAsim Jamshed             {
593776404edcSAsim Jamshed                 switch (linktype)
593876404edcSAsim Jamshed                 {
593976404edcSAsim Jamshed 
594076404edcSAsim Jamshed                     case DLT_EN10MB:
594176404edcSAsim Jamshed                         eaddr = pcap_ether_hostton(name);
594276404edcSAsim Jamshed                         if (eaddr == NULL)
594376404edcSAsim Jamshed                             bpf_error("unknown ether host '%s'", name);
594476404edcSAsim Jamshed                         b = gen_ehostop(eaddr, dir);
594576404edcSAsim Jamshed                         free(eaddr);
594676404edcSAsim Jamshed                         return b;
594776404edcSAsim Jamshed 
594876404edcSAsim Jamshed                     case DLT_FDDI:
594976404edcSAsim Jamshed                         eaddr = pcap_ether_hostton(name);
595076404edcSAsim Jamshed                         if (eaddr == NULL)
595176404edcSAsim Jamshed                             bpf_error("unknown FDDI host '%s'", name);
595276404edcSAsim Jamshed                         b = gen_fhostop(eaddr, dir);
595376404edcSAsim Jamshed                         free(eaddr);
595476404edcSAsim Jamshed                         return b;
595576404edcSAsim Jamshed 
595676404edcSAsim Jamshed                     case DLT_IEEE802:
595776404edcSAsim Jamshed                         eaddr = pcap_ether_hostton(name);
595876404edcSAsim Jamshed                         if (eaddr == NULL)
595976404edcSAsim Jamshed                             bpf_error("unknown token ring host '%s'", name);
596076404edcSAsim Jamshed                         b = gen_thostop(eaddr, dir);
596176404edcSAsim Jamshed                         free(eaddr);
596276404edcSAsim Jamshed                         return b;
596376404edcSAsim Jamshed 
596476404edcSAsim Jamshed                     case DLT_IEEE802_11:
596576404edcSAsim Jamshed                     case DLT_PRISM_HEADER:
596676404edcSAsim Jamshed                     case DLT_IEEE802_11_RADIO_AVS:
596776404edcSAsim Jamshed                     case DLT_IEEE802_11_RADIO:
596876404edcSAsim Jamshed                     case DLT_PPI:
596976404edcSAsim Jamshed                         eaddr = pcap_ether_hostton(name);
597076404edcSAsim Jamshed                         if (eaddr == NULL)
597176404edcSAsim Jamshed                             bpf_error("unknown 802.11 host '%s'", name);
597276404edcSAsim Jamshed                         b = gen_wlanhostop(eaddr, dir);
597376404edcSAsim Jamshed                         free(eaddr);
597476404edcSAsim Jamshed                         return b;
597576404edcSAsim Jamshed 
597676404edcSAsim Jamshed                     case DLT_IP_OVER_FC:
597776404edcSAsim Jamshed                         eaddr = pcap_ether_hostton(name);
597876404edcSAsim Jamshed                         if (eaddr == NULL)
597976404edcSAsim Jamshed                             bpf_error("unknown Fibre Channel host '%s'", name);
598076404edcSAsim Jamshed                         b = gen_ipfchostop(eaddr, dir);
598176404edcSAsim Jamshed                         free(eaddr);
598276404edcSAsim Jamshed                         return b;
598376404edcSAsim Jamshed 
598476404edcSAsim Jamshed                     case DLT_SUNATM:
598576404edcSAsim Jamshed                         if (!is_lane)
598676404edcSAsim Jamshed                             break;
598776404edcSAsim Jamshed 
598876404edcSAsim Jamshed                         /*
598976404edcSAsim Jamshed                          * Check that the packet doesn't begin
599076404edcSAsim Jamshed                          * with an LE Control marker.  (We've
599176404edcSAsim Jamshed                          * already generated a test for LANE.)
599276404edcSAsim Jamshed                          */
599376404edcSAsim Jamshed                         tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
599476404edcSAsim Jamshed                         gen_not(tmp);
599576404edcSAsim Jamshed 
599676404edcSAsim Jamshed                         eaddr = pcap_ether_hostton(name);
599776404edcSAsim Jamshed                         if (eaddr == NULL)
599876404edcSAsim Jamshed                             bpf_error("unknown ether host '%s'", name);
599976404edcSAsim Jamshed                         b = gen_ehostop(eaddr, dir);
600076404edcSAsim Jamshed                         gen_and(tmp, b);
600176404edcSAsim Jamshed                         free(eaddr);
600276404edcSAsim Jamshed                         return b;
600376404edcSAsim Jamshed                 }
600476404edcSAsim Jamshed 
600576404edcSAsim Jamshed                 bpf_error
600676404edcSAsim Jamshed                     ("only ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel supports link-level host name");
600776404edcSAsim Jamshed             }
600876404edcSAsim Jamshed             else if (proto == Q_DECNET)
600976404edcSAsim Jamshed             {
601076404edcSAsim Jamshed                 unsigned short dn_addr = __pcap_nametodnaddr(name);
601176404edcSAsim Jamshed                 /*
601276404edcSAsim Jamshed                  * I don't think DECNET hosts can be multihomed, so
601376404edcSAsim Jamshed                  * there is no need to build up a list of addresses
601476404edcSAsim Jamshed                  */
601576404edcSAsim Jamshed                 return (gen_host(dn_addr, 0, proto, dir, q.addr));
601676404edcSAsim Jamshed             }
601776404edcSAsim Jamshed             else
601876404edcSAsim Jamshed             {
601976404edcSAsim Jamshed #ifndef INET6
602076404edcSAsim Jamshed                 alist = pcap_nametoaddr(name);
602176404edcSAsim Jamshed                 if (alist == NULL || *alist == NULL)
602276404edcSAsim Jamshed                     bpf_error("unknown host '%s'", name);
602376404edcSAsim Jamshed                 tproto = proto;
602476404edcSAsim Jamshed                 if (off_linktype == (u_int) - 1 && tproto == Q_DEFAULT)
602576404edcSAsim Jamshed                     tproto = Q_IP;
602676404edcSAsim Jamshed                 b = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr);
602776404edcSAsim Jamshed                 while (*alist)
602876404edcSAsim Jamshed                 {
602976404edcSAsim Jamshed                     tmp = gen_host(**alist++, 0xffffffff, tproto, dir, q.addr);
603076404edcSAsim Jamshed                     gen_or(b, tmp);
603176404edcSAsim Jamshed                     b = tmp;
603276404edcSAsim Jamshed                 }
603376404edcSAsim Jamshed                 return b;
603476404edcSAsim Jamshed #else
603576404edcSAsim Jamshed                 memset(&mask128, 0xff, sizeof(mask128));
603676404edcSAsim Jamshed                 res0 = res = pcap_nametoaddrinfo(name);
603776404edcSAsim Jamshed                 if (res == NULL)
603876404edcSAsim Jamshed                     bpf_error("unknown host '%s'", name);
603976404edcSAsim Jamshed                 ai = res;
604076404edcSAsim Jamshed                 b = tmp = NULL;
604176404edcSAsim Jamshed                 tproto = tproto6 = proto;
604276404edcSAsim Jamshed                 if (off_linktype == -1 && tproto == Q_DEFAULT)
604376404edcSAsim Jamshed                 {
604476404edcSAsim Jamshed                     tproto = Q_IP;
604576404edcSAsim Jamshed                     tproto6 = Q_IPV6;
604676404edcSAsim Jamshed                 }
604776404edcSAsim Jamshed                 for (res = res0; res; res = res->ai_next)
604876404edcSAsim Jamshed                 {
604976404edcSAsim Jamshed                     switch (res->ai_family)
605076404edcSAsim Jamshed                     {
605176404edcSAsim Jamshed                         case AF_INET:
605276404edcSAsim Jamshed                             if (tproto == Q_IPV6)
605376404edcSAsim Jamshed                                 continue;
605476404edcSAsim Jamshed 
605576404edcSAsim Jamshed                             sin4 = (struct sockaddr_in *) res->ai_addr;
605676404edcSAsim Jamshed                             tmp = gen_host(ntohl(sin4->sin_addr.s_addr), 0xffffffff, tproto, dir, q.addr);
605776404edcSAsim Jamshed                             break;
605876404edcSAsim Jamshed                         case AF_INET6:
605976404edcSAsim Jamshed                             if (tproto6 == Q_IP)
606076404edcSAsim Jamshed                                 continue;
606176404edcSAsim Jamshed 
606276404edcSAsim Jamshed                             sin6 = (struct sockaddr_in6 *) res->ai_addr;
606376404edcSAsim Jamshed                             tmp = gen_host6(&sin6->sin6_addr, &mask128, tproto6, dir, q.addr);
606476404edcSAsim Jamshed                             break;
606576404edcSAsim Jamshed                         default:
606676404edcSAsim Jamshed                             continue;
606776404edcSAsim Jamshed                     }
606876404edcSAsim Jamshed                     if (b)
606976404edcSAsim Jamshed                         gen_or(b, tmp);
607076404edcSAsim Jamshed                     b = tmp;
607176404edcSAsim Jamshed                 }
607276404edcSAsim Jamshed                 ai = NULL;
607376404edcSAsim Jamshed                 freeaddrinfo(res0);
607476404edcSAsim Jamshed                 if (b == NULL)
607576404edcSAsim Jamshed                 {
607676404edcSAsim Jamshed                     bpf_error("unknown host '%s'%s", name,
607776404edcSAsim Jamshed                               (proto == Q_DEFAULT) ? "" : " for specified address family");
607876404edcSAsim Jamshed                 }
607976404edcSAsim Jamshed                 return b;
608076404edcSAsim Jamshed #endif /*INET6 */
608176404edcSAsim Jamshed             }
608276404edcSAsim Jamshed 
608376404edcSAsim Jamshed         case Q_PORT:
608476404edcSAsim Jamshed             if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
608576404edcSAsim Jamshed                 bpf_error("illegal qualifier of 'port'");
608676404edcSAsim Jamshed             if (pcap_nametoport(name, &port, &real_proto) == 0)
608776404edcSAsim Jamshed                 bpf_error("unknown port '%s'", name);
608876404edcSAsim Jamshed             if (proto == Q_UDP)
608976404edcSAsim Jamshed             {
609076404edcSAsim Jamshed                 if (real_proto == IPPROTO_TCP)
609176404edcSAsim Jamshed                     bpf_error("port '%s' is tcp", name);
609276404edcSAsim Jamshed                 else if (real_proto == IPPROTO_SCTP)
609376404edcSAsim Jamshed                     bpf_error("port '%s' is sctp", name);
609476404edcSAsim Jamshed                 else
609576404edcSAsim Jamshed                     /* override PROTO_UNDEF */
609676404edcSAsim Jamshed                     real_proto = IPPROTO_UDP;
609776404edcSAsim Jamshed             }
609876404edcSAsim Jamshed             if (proto == Q_TCP)
609976404edcSAsim Jamshed             {
610076404edcSAsim Jamshed                 if (real_proto == IPPROTO_UDP)
610176404edcSAsim Jamshed                     bpf_error("port '%s' is udp", name);
610276404edcSAsim Jamshed 
610376404edcSAsim Jamshed                 else if (real_proto == IPPROTO_SCTP)
610476404edcSAsim Jamshed                     bpf_error("port '%s' is sctp", name);
610576404edcSAsim Jamshed                 else
610676404edcSAsim Jamshed                     /* override PROTO_UNDEF */
610776404edcSAsim Jamshed                     real_proto = IPPROTO_TCP;
610876404edcSAsim Jamshed             }
610976404edcSAsim Jamshed             if (proto == Q_SCTP)
611076404edcSAsim Jamshed             {
611176404edcSAsim Jamshed                 if (real_proto == IPPROTO_UDP)
611276404edcSAsim Jamshed                     bpf_error("port '%s' is udp", name);
611376404edcSAsim Jamshed 
611476404edcSAsim Jamshed                 else if (real_proto == IPPROTO_TCP)
611576404edcSAsim Jamshed                     bpf_error("port '%s' is tcp", name);
611676404edcSAsim Jamshed                 else
611776404edcSAsim Jamshed                     /* override PROTO_UNDEF */
611876404edcSAsim Jamshed                     real_proto = IPPROTO_SCTP;
611976404edcSAsim Jamshed             }
612076404edcSAsim Jamshed #ifndef INET6
612176404edcSAsim Jamshed             return gen_port(port, real_proto, dir);
612276404edcSAsim Jamshed #else
612376404edcSAsim Jamshed             b = gen_port(port, real_proto, dir);
612476404edcSAsim Jamshed             gen_or(gen_port6(port, real_proto, dir), b);
612576404edcSAsim Jamshed             return b;
612676404edcSAsim Jamshed #endif /* INET6 */
612776404edcSAsim Jamshed 
612876404edcSAsim Jamshed         case Q_PORTRANGE:
612976404edcSAsim Jamshed             if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
613076404edcSAsim Jamshed                 bpf_error("illegal qualifier of 'portrange'");
613176404edcSAsim Jamshed             if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0)
613276404edcSAsim Jamshed                 bpf_error("unknown port in range '%s'", name);
613376404edcSAsim Jamshed             if (proto == Q_UDP)
613476404edcSAsim Jamshed             {
613576404edcSAsim Jamshed                 if (real_proto == IPPROTO_TCP)
613676404edcSAsim Jamshed                     bpf_error("port in range '%s' is tcp", name);
613776404edcSAsim Jamshed                 else if (real_proto == IPPROTO_SCTP)
613876404edcSAsim Jamshed                     bpf_error("port in range '%s' is sctp", name);
613976404edcSAsim Jamshed                 else
614076404edcSAsim Jamshed                     /* override PROTO_UNDEF */
614176404edcSAsim Jamshed                     real_proto = IPPROTO_UDP;
614276404edcSAsim Jamshed             }
614376404edcSAsim Jamshed             if (proto == Q_TCP)
614476404edcSAsim Jamshed             {
614576404edcSAsim Jamshed                 if (real_proto == IPPROTO_UDP)
614676404edcSAsim Jamshed                     bpf_error("port in range '%s' is udp", name);
614776404edcSAsim Jamshed                 else if (real_proto == IPPROTO_SCTP)
614876404edcSAsim Jamshed                     bpf_error("port in range '%s' is sctp", name);
614976404edcSAsim Jamshed                 else
615076404edcSAsim Jamshed                     /* override PROTO_UNDEF */
615176404edcSAsim Jamshed                     real_proto = IPPROTO_TCP;
615276404edcSAsim Jamshed             }
615376404edcSAsim Jamshed             if (proto == Q_SCTP)
615476404edcSAsim Jamshed             {
615576404edcSAsim Jamshed                 if (real_proto == IPPROTO_UDP)
615676404edcSAsim Jamshed                     bpf_error("port in range '%s' is udp", name);
615776404edcSAsim Jamshed                 else if (real_proto == IPPROTO_TCP)
615876404edcSAsim Jamshed                     bpf_error("port in range '%s' is tcp", name);
615976404edcSAsim Jamshed                 else
616076404edcSAsim Jamshed                     /* override PROTO_UNDEF */
616176404edcSAsim Jamshed                     real_proto = IPPROTO_SCTP;
616276404edcSAsim Jamshed             }
616376404edcSAsim Jamshed #ifndef INET6
616476404edcSAsim Jamshed             return gen_portrange(port1, port2, real_proto, dir);
616576404edcSAsim Jamshed #else
616676404edcSAsim Jamshed             b = gen_portrange(port1, port2, real_proto, dir);
616776404edcSAsim Jamshed             gen_or(gen_portrange6(port1, port2, real_proto, dir), b);
616876404edcSAsim Jamshed             return b;
616976404edcSAsim Jamshed #endif /* INET6 */
617076404edcSAsim Jamshed 
617176404edcSAsim Jamshed         case Q_GATEWAY:
617276404edcSAsim Jamshed #ifndef INET6
617376404edcSAsim Jamshed             eaddr = pcap_ether_hostton(name);
617476404edcSAsim Jamshed             if (eaddr == NULL)
617576404edcSAsim Jamshed                 bpf_error("unknown ether host: %s", name);
617676404edcSAsim Jamshed 
617776404edcSAsim Jamshed             alist = pcap_nametoaddr(name);
617876404edcSAsim Jamshed             if (alist == NULL || *alist == NULL)
617976404edcSAsim Jamshed                 bpf_error("unknown host '%s'", name);
618076404edcSAsim Jamshed             b = gen_gateway(eaddr, alist, proto, dir);
618176404edcSAsim Jamshed             free(eaddr);
618276404edcSAsim Jamshed             return b;
618376404edcSAsim Jamshed #else
618476404edcSAsim Jamshed             bpf_error("'gateway' not supported in this configuration");
618576404edcSAsim Jamshed #endif /*INET6 */
618676404edcSAsim Jamshed 
618776404edcSAsim Jamshed         case Q_PROTO:
618876404edcSAsim Jamshed             real_proto = lookup_proto(name, proto);
618976404edcSAsim Jamshed             if (real_proto >= 0)
619076404edcSAsim Jamshed                 return gen_proto(real_proto, proto, dir);
619176404edcSAsim Jamshed             else
619276404edcSAsim Jamshed                 bpf_error("unknown protocol: %s", name);
619376404edcSAsim Jamshed 
619476404edcSAsim Jamshed         case Q_PROTOCHAIN:
619576404edcSAsim Jamshed             real_proto = lookup_proto(name, proto);
619676404edcSAsim Jamshed             if (real_proto >= 0)
619776404edcSAsim Jamshed                 return gen_protochain(real_proto, proto, dir);
619876404edcSAsim Jamshed             else
619976404edcSAsim Jamshed                 bpf_error("unknown protocol: %s", name);
620076404edcSAsim Jamshed 
620176404edcSAsim Jamshed         case Q_UNDEF:
620276404edcSAsim Jamshed             syntax();
620376404edcSAsim Jamshed             /* NOTREACHED */
620476404edcSAsim Jamshed     }
620576404edcSAsim Jamshed     abort();
620676404edcSAsim Jamshed     /* NOTREACHED */
620776404edcSAsim Jamshed }
620876404edcSAsim Jamshed 
gen_mcode(s1,s2,masklen,q)620976404edcSAsim Jamshed struct block *gen_mcode(s1, s2, masklen, q)
621076404edcSAsim Jamshed      register const char *s1, *s2;
621176404edcSAsim Jamshed      register int masklen;
621276404edcSAsim Jamshed      struct qual q;
621376404edcSAsim Jamshed {
621476404edcSAsim Jamshed     register int nlen, mlen;
621576404edcSAsim Jamshed     bpf_u_int32 n, m;
621676404edcSAsim Jamshed 
621776404edcSAsim Jamshed     nlen = __pcap_atoin(s1, &n);
621876404edcSAsim Jamshed     /* Promote short ipaddr */
621976404edcSAsim Jamshed     n <<= 32 - nlen;
622076404edcSAsim Jamshed 
622176404edcSAsim Jamshed     if (s2 != NULL)
622276404edcSAsim Jamshed     {
622376404edcSAsim Jamshed         mlen = __pcap_atoin(s2, &m);
622476404edcSAsim Jamshed         /* Promote short ipaddr */
622576404edcSAsim Jamshed         m <<= 32 - mlen;
622676404edcSAsim Jamshed         if ((n & ~m) != 0)
622776404edcSAsim Jamshed             bpf_error("non-network bits set in \"%s mask %s\"", s1, s2);
622876404edcSAsim Jamshed     }
622976404edcSAsim Jamshed     else
623076404edcSAsim Jamshed     {
623176404edcSAsim Jamshed         /* Convert mask len to mask */
623276404edcSAsim Jamshed         if (masklen > 32)
623376404edcSAsim Jamshed             bpf_error("mask length must be <= 32");
623476404edcSAsim Jamshed         if (masklen == 0)
623576404edcSAsim Jamshed         {
623676404edcSAsim Jamshed             /*
623776404edcSAsim Jamshed              * X << 32 is not guaranteed by C to be 0; it's
623876404edcSAsim Jamshed              * undefined.
623976404edcSAsim Jamshed              */
624076404edcSAsim Jamshed             m = 0;
624176404edcSAsim Jamshed         }
624276404edcSAsim Jamshed         else
624376404edcSAsim Jamshed             m = 0xffffffff << (32 - masklen);
624476404edcSAsim Jamshed         if ((n & ~m) != 0)
624576404edcSAsim Jamshed             bpf_error("non-network bits set in \"%s/%d\"", s1, masklen);
624676404edcSAsim Jamshed     }
624776404edcSAsim Jamshed 
624876404edcSAsim Jamshed     switch (q.addr)
624976404edcSAsim Jamshed     {
625076404edcSAsim Jamshed 
625176404edcSAsim Jamshed         case Q_NET:
625276404edcSAsim Jamshed             return gen_host(n, m, q.proto, q.dir, q.addr);
625376404edcSAsim Jamshed 
625476404edcSAsim Jamshed         default:
625576404edcSAsim Jamshed             bpf_error("Mask syntax for networks only");
625676404edcSAsim Jamshed             /* NOTREACHED */
625776404edcSAsim Jamshed     }
625876404edcSAsim Jamshed     /* NOTREACHED */
625976404edcSAsim Jamshed     return NULL;
626076404edcSAsim Jamshed }
626176404edcSAsim Jamshed 
gen_ncode(s,v,q)626276404edcSAsim Jamshed struct block *gen_ncode(s, v, q)
626376404edcSAsim Jamshed      register const char *s;
626476404edcSAsim Jamshed      bpf_u_int32 v;
626576404edcSAsim Jamshed      struct qual q;
626676404edcSAsim Jamshed {
626776404edcSAsim Jamshed     bpf_u_int32 mask;
626876404edcSAsim Jamshed     int proto = q.proto;
626976404edcSAsim Jamshed     int dir = q.dir;
627076404edcSAsim Jamshed     register int vlen;
627176404edcSAsim Jamshed 
627276404edcSAsim Jamshed     if (s == NULL)
627376404edcSAsim Jamshed         vlen = 32;
627476404edcSAsim Jamshed     else if (q.proto == Q_DECNET)
627576404edcSAsim Jamshed         vlen = __pcap_atodn(s, &v);
627676404edcSAsim Jamshed     else
627776404edcSAsim Jamshed         vlen = __pcap_atoin(s, &v);
627876404edcSAsim Jamshed 
627976404edcSAsim Jamshed     switch (q.addr)
628076404edcSAsim Jamshed     {
628176404edcSAsim Jamshed 
628276404edcSAsim Jamshed         case Q_DEFAULT:
628376404edcSAsim Jamshed         case Q_HOST:
628476404edcSAsim Jamshed         case Q_NET:
628576404edcSAsim Jamshed             if (proto == Q_DECNET)
628676404edcSAsim Jamshed                 return gen_host(v, 0, proto, dir, q.addr);
628776404edcSAsim Jamshed             else if (proto == Q_LINK)
628876404edcSAsim Jamshed             {
628976404edcSAsim Jamshed                 bpf_error("illegal link layer address");
629076404edcSAsim Jamshed             }
629176404edcSAsim Jamshed             else
629276404edcSAsim Jamshed             {
629376404edcSAsim Jamshed                 mask = 0xffffffff;
629476404edcSAsim Jamshed                 if (s == NULL && q.addr == Q_NET)
629576404edcSAsim Jamshed                 {
629676404edcSAsim Jamshed                     /* Promote short net number */
629776404edcSAsim Jamshed                     while (v && (v & 0xff000000) == 0)
629876404edcSAsim Jamshed                     {
629976404edcSAsim Jamshed                         v <<= 8;
630076404edcSAsim Jamshed                         mask <<= 8;
630176404edcSAsim Jamshed                     }
630276404edcSAsim Jamshed                 }
630376404edcSAsim Jamshed                 else
630476404edcSAsim Jamshed                 {
630576404edcSAsim Jamshed                     /* Promote short ipaddr */
630676404edcSAsim Jamshed                     v <<= 32 - vlen;
630776404edcSAsim Jamshed                     mask <<= 32 - vlen;
630876404edcSAsim Jamshed                 }
630976404edcSAsim Jamshed                 return gen_host(v, mask, proto, dir, q.addr);
631076404edcSAsim Jamshed             }
631176404edcSAsim Jamshed 
631276404edcSAsim Jamshed         case Q_PORT:
631376404edcSAsim Jamshed             if (proto == Q_UDP)
631476404edcSAsim Jamshed                 proto = IPPROTO_UDP;
631576404edcSAsim Jamshed             else if (proto == Q_TCP)
631676404edcSAsim Jamshed                 proto = IPPROTO_TCP;
631776404edcSAsim Jamshed             else if (proto == Q_SCTP)
631876404edcSAsim Jamshed                 proto = IPPROTO_SCTP;
631976404edcSAsim Jamshed             else if (proto == Q_DEFAULT)
632076404edcSAsim Jamshed                 proto = PROTO_UNDEF;
632176404edcSAsim Jamshed             else
632276404edcSAsim Jamshed                 bpf_error("illegal qualifier of 'port'");
632376404edcSAsim Jamshed 
632476404edcSAsim Jamshed #ifndef INET6
632576404edcSAsim Jamshed             return gen_port((int) v, proto, dir);
632676404edcSAsim Jamshed #else
632776404edcSAsim Jamshed             {
632876404edcSAsim Jamshed                 struct block *b;
632976404edcSAsim Jamshed                 b = gen_port((int) v, proto, dir);
633076404edcSAsim Jamshed                 gen_or(gen_port6((int) v, proto, dir), b);
633176404edcSAsim Jamshed                 return b;
633276404edcSAsim Jamshed             }
633376404edcSAsim Jamshed #endif /* INET6 */
633476404edcSAsim Jamshed 
633576404edcSAsim Jamshed         case Q_PORTRANGE:
633676404edcSAsim Jamshed             if (proto == Q_UDP)
633776404edcSAsim Jamshed                 proto = IPPROTO_UDP;
633876404edcSAsim Jamshed             else if (proto == Q_TCP)
633976404edcSAsim Jamshed                 proto = IPPROTO_TCP;
634076404edcSAsim Jamshed             else if (proto == Q_SCTP)
634176404edcSAsim Jamshed                 proto = IPPROTO_SCTP;
634276404edcSAsim Jamshed             else if (proto == Q_DEFAULT)
634376404edcSAsim Jamshed                 proto = PROTO_UNDEF;
634476404edcSAsim Jamshed             else
634576404edcSAsim Jamshed                 bpf_error("illegal qualifier of 'portrange'");
634676404edcSAsim Jamshed 
634776404edcSAsim Jamshed #ifndef INET6
634876404edcSAsim Jamshed             return gen_portrange((int) v, (int) v, proto, dir);
634976404edcSAsim Jamshed #else
635076404edcSAsim Jamshed             {
635176404edcSAsim Jamshed                 struct block *b;
635276404edcSAsim Jamshed                 b = gen_portrange((int) v, (int) v, proto, dir);
635376404edcSAsim Jamshed                 gen_or(gen_portrange6((int) v, (int) v, proto, dir), b);
635476404edcSAsim Jamshed                 return b;
635576404edcSAsim Jamshed             }
635676404edcSAsim Jamshed #endif /* INET6 */
635776404edcSAsim Jamshed 
635876404edcSAsim Jamshed         case Q_GATEWAY:
635976404edcSAsim Jamshed             bpf_error("'gateway' requires a name");
636076404edcSAsim Jamshed             /* NOTREACHED */
636176404edcSAsim Jamshed 
636276404edcSAsim Jamshed         case Q_PROTO:
636376404edcSAsim Jamshed             return gen_proto((int) v, proto, dir);
636476404edcSAsim Jamshed 
636576404edcSAsim Jamshed         case Q_PROTOCHAIN:
636676404edcSAsim Jamshed             return gen_protochain((int) v, proto, dir);
636776404edcSAsim Jamshed 
636876404edcSAsim Jamshed         case Q_UNDEF:
636976404edcSAsim Jamshed             syntax();
637076404edcSAsim Jamshed             /* NOTREACHED */
637176404edcSAsim Jamshed 
637276404edcSAsim Jamshed         default:
637376404edcSAsim Jamshed             abort();
637476404edcSAsim Jamshed             /* NOTREACHED */
637576404edcSAsim Jamshed     }
637676404edcSAsim Jamshed     /* NOTREACHED */
637776404edcSAsim Jamshed }
637876404edcSAsim Jamshed 
637976404edcSAsim Jamshed #ifdef INET6
gen_mcode6(s1,s2,masklen,q)638076404edcSAsim Jamshed struct block *gen_mcode6(s1, s2, masklen, q)
638176404edcSAsim Jamshed      register const char *s1, *s2;
638276404edcSAsim Jamshed      register int masklen;
638376404edcSAsim Jamshed      struct qual q;
638476404edcSAsim Jamshed {
638576404edcSAsim Jamshed     struct addrinfo *res;
638676404edcSAsim Jamshed     struct in6_addr *addr;
638776404edcSAsim Jamshed     struct in6_addr mask;
638876404edcSAsim Jamshed     struct block *b;
638976404edcSAsim Jamshed     u_int32_t *a, *m;
639076404edcSAsim Jamshed 
639176404edcSAsim Jamshed     if (s2)
639276404edcSAsim Jamshed         bpf_error("no mask %s supported", s2);
639376404edcSAsim Jamshed 
639476404edcSAsim Jamshed     res = pcap_nametoaddrinfo(s1);
639576404edcSAsim Jamshed     if (!res)
639676404edcSAsim Jamshed         bpf_error("invalid ip6 address %s", s1);
639776404edcSAsim Jamshed     ai = res;
639876404edcSAsim Jamshed     if (res->ai_next)
639976404edcSAsim Jamshed         bpf_error("%s resolved to multiple address", s1);
640076404edcSAsim Jamshed     addr = &((struct sockaddr_in6 *) res->ai_addr)->sin6_addr;
640176404edcSAsim Jamshed 
640276404edcSAsim Jamshed     if (sizeof(mask) * 8 < masklen)
640376404edcSAsim Jamshed         bpf_error("mask length must be <= %u", (unsigned int) (sizeof(mask) * 8));
640476404edcSAsim Jamshed     memset(&mask, 0, sizeof(mask));
640576404edcSAsim Jamshed     memset(&mask, 0xff, masklen / 8);
640676404edcSAsim Jamshed     if (masklen % 8)
640776404edcSAsim Jamshed     {
640876404edcSAsim Jamshed         mask.s6_addr[masklen / 8] = (0xff << (8 - masklen % 8)) & 0xff;
640976404edcSAsim Jamshed     }
641076404edcSAsim Jamshed 
641176404edcSAsim Jamshed     a = (u_int32_t *) addr;
641276404edcSAsim Jamshed     m = (u_int32_t *) & mask;
641376404edcSAsim Jamshed     if ((a[0] & ~m[0]) || (a[1] & ~m[1]) || (a[2] & ~m[2]) || (a[3] & ~m[3]))
641476404edcSAsim Jamshed     {
641576404edcSAsim Jamshed         bpf_error("non-network bits set in \"%s/%d\"", s1, masklen);
641676404edcSAsim Jamshed     }
641776404edcSAsim Jamshed 
641876404edcSAsim Jamshed     switch (q.addr)
641976404edcSAsim Jamshed     {
642076404edcSAsim Jamshed 
642176404edcSAsim Jamshed         case Q_DEFAULT:
642276404edcSAsim Jamshed         case Q_HOST:
642376404edcSAsim Jamshed             if (masklen != 128)
642476404edcSAsim Jamshed                 bpf_error("Mask syntax for networks only");
642576404edcSAsim Jamshed             /* FALLTHROUGH */
642676404edcSAsim Jamshed 
642776404edcSAsim Jamshed         case Q_NET:
642876404edcSAsim Jamshed             b = gen_host6(addr, &mask, q.proto, q.dir, q.addr);
642976404edcSAsim Jamshed             ai = NULL;
643076404edcSAsim Jamshed             freeaddrinfo(res);
643176404edcSAsim Jamshed             return b;
643276404edcSAsim Jamshed 
643376404edcSAsim Jamshed         default:
643476404edcSAsim Jamshed             bpf_error("invalid qualifier against IPv6 address");
643576404edcSAsim Jamshed             /* NOTREACHED */
643676404edcSAsim Jamshed     }
643776404edcSAsim Jamshed     return NULL;
643876404edcSAsim Jamshed }
643976404edcSAsim Jamshed #endif /*INET6 */
644076404edcSAsim Jamshed 
gen_ecode(eaddr,q)644176404edcSAsim Jamshed struct block *gen_ecode(eaddr, q)
644276404edcSAsim Jamshed      register const u_char *eaddr;
644376404edcSAsim Jamshed      struct qual q;
644476404edcSAsim Jamshed {
644576404edcSAsim Jamshed     struct block *b, *tmp;
644676404edcSAsim Jamshed 
644776404edcSAsim Jamshed     if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK)
644876404edcSAsim Jamshed     {
644976404edcSAsim Jamshed         switch (linktype)
645076404edcSAsim Jamshed         {
645176404edcSAsim Jamshed             case DLT_EN10MB:
645276404edcSAsim Jamshed                 return gen_ehostop(eaddr, (int) q.dir);
645376404edcSAsim Jamshed             case DLT_FDDI:
645476404edcSAsim Jamshed                 return gen_fhostop(eaddr, (int) q.dir);
645576404edcSAsim Jamshed             case DLT_IEEE802:
645676404edcSAsim Jamshed                 return gen_thostop(eaddr, (int) q.dir);
645776404edcSAsim Jamshed             case DLT_IEEE802_11:
645876404edcSAsim Jamshed             case DLT_PRISM_HEADER:
645976404edcSAsim Jamshed             case DLT_IEEE802_11_RADIO_AVS:
646076404edcSAsim Jamshed             case DLT_IEEE802_11_RADIO:
646176404edcSAsim Jamshed             case DLT_PPI:
646276404edcSAsim Jamshed                 return gen_wlanhostop(eaddr, (int) q.dir);
646376404edcSAsim Jamshed             case DLT_SUNATM:
646476404edcSAsim Jamshed                 if (is_lane)
646576404edcSAsim Jamshed                 {
646676404edcSAsim Jamshed                     /*
646776404edcSAsim Jamshed                      * Check that the packet doesn't begin with an
646876404edcSAsim Jamshed                      * LE Control marker.  (We've already generated
646976404edcSAsim Jamshed                      * a test for LANE.)
647076404edcSAsim Jamshed                      */
647176404edcSAsim Jamshed                     tmp = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
647276404edcSAsim Jamshed                     gen_not(tmp);
647376404edcSAsim Jamshed 
647476404edcSAsim Jamshed                     /*
647576404edcSAsim Jamshed                      * Now check the MAC address.
647676404edcSAsim Jamshed                      */
647776404edcSAsim Jamshed                     b = gen_ehostop(eaddr, (int) q.dir);
647876404edcSAsim Jamshed                     gen_and(tmp, b);
647976404edcSAsim Jamshed                     return b;
648076404edcSAsim Jamshed                 }
648176404edcSAsim Jamshed                 break;
648276404edcSAsim Jamshed             case DLT_IP_OVER_FC:
648376404edcSAsim Jamshed                 return gen_ipfchostop(eaddr, (int) q.dir);
648476404edcSAsim Jamshed             default:
648576404edcSAsim Jamshed                 bpf_error
648676404edcSAsim Jamshed                     ("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
648776404edcSAsim Jamshed                 break;
648876404edcSAsim Jamshed         }
648976404edcSAsim Jamshed     }
649076404edcSAsim Jamshed     bpf_error("ethernet address used in non-ether expression");
649176404edcSAsim Jamshed     /* NOTREACHED */
649276404edcSAsim Jamshed     return NULL;
649376404edcSAsim Jamshed }
649476404edcSAsim Jamshed 
sappend(s0,s1)649576404edcSAsim Jamshed void sappend(s0, s1)
649676404edcSAsim Jamshed      struct slist *s0, *s1;
649776404edcSAsim Jamshed {
649876404edcSAsim Jamshed     /*
649976404edcSAsim Jamshed      * This is definitely not the best way to do this, but the
650076404edcSAsim Jamshed      * lists will rarely get long.
650176404edcSAsim Jamshed      */
650276404edcSAsim Jamshed     while (s0->next)
650376404edcSAsim Jamshed         s0 = s0->next;
650476404edcSAsim Jamshed     s0->next = s1;
650576404edcSAsim Jamshed }
650676404edcSAsim Jamshed 
xfer_to_x(a)650776404edcSAsim Jamshed static struct slist *xfer_to_x(a)
650876404edcSAsim Jamshed      struct arth *a;
650976404edcSAsim Jamshed {
651076404edcSAsim Jamshed     struct slist *s;
651176404edcSAsim Jamshed 
651276404edcSAsim Jamshed     s = new_stmt(BPF_LDX | BPF_MEM);
651376404edcSAsim Jamshed     s->s.k = a->regno;
651476404edcSAsim Jamshed     return s;
651576404edcSAsim Jamshed }
651676404edcSAsim Jamshed 
xfer_to_a(a)651776404edcSAsim Jamshed static struct slist *xfer_to_a(a)
651876404edcSAsim Jamshed      struct arth *a;
651976404edcSAsim Jamshed {
652076404edcSAsim Jamshed     struct slist *s;
652176404edcSAsim Jamshed 
652276404edcSAsim Jamshed     s = new_stmt(BPF_LD | BPF_MEM);
652376404edcSAsim Jamshed     s->s.k = a->regno;
652476404edcSAsim Jamshed     return s;
652576404edcSAsim Jamshed }
652676404edcSAsim Jamshed 
652776404edcSAsim Jamshed /*
652876404edcSAsim Jamshed  * Modify "index" to use the value stored into its register as an
652976404edcSAsim Jamshed  * offset relative to the beginning of the header for the protocol
653076404edcSAsim Jamshed  * "proto", and allocate a register and put an item "size" bytes long
653176404edcSAsim Jamshed  * (1, 2, or 4) at that offset into that register, making it the register
653276404edcSAsim Jamshed  * for "index".
653376404edcSAsim Jamshed  */
gen_load(proto,inst,size)653476404edcSAsim Jamshed struct arth *gen_load(proto, inst, size)
653576404edcSAsim Jamshed      int proto;
653676404edcSAsim Jamshed      struct arth *inst;
653776404edcSAsim Jamshed      int size;
653876404edcSAsim Jamshed {
653976404edcSAsim Jamshed     struct slist *s, *tmp;
654076404edcSAsim Jamshed     struct block *b;
654176404edcSAsim Jamshed     int regno = alloc_reg();
654276404edcSAsim Jamshed 
654376404edcSAsim Jamshed     free_reg(inst->regno);
654476404edcSAsim Jamshed     switch (size)
654576404edcSAsim Jamshed     {
654676404edcSAsim Jamshed 
654776404edcSAsim Jamshed         default:
654876404edcSAsim Jamshed             bpf_error("data size must be 1, 2, or 4");
654976404edcSAsim Jamshed 
655076404edcSAsim Jamshed         case 1:
655176404edcSAsim Jamshed             size = BPF_B;
655276404edcSAsim Jamshed             break;
655376404edcSAsim Jamshed 
655476404edcSAsim Jamshed         case 2:
655576404edcSAsim Jamshed             size = BPF_H;
655676404edcSAsim Jamshed             break;
655776404edcSAsim Jamshed 
655876404edcSAsim Jamshed         case 4:
655976404edcSAsim Jamshed             size = BPF_W;
656076404edcSAsim Jamshed             break;
656176404edcSAsim Jamshed     }
656276404edcSAsim Jamshed     switch (proto)
656376404edcSAsim Jamshed     {
656476404edcSAsim Jamshed         default:
656576404edcSAsim Jamshed             bpf_error("unsupported index operation");
656676404edcSAsim Jamshed 
656776404edcSAsim Jamshed         case Q_RADIO:
656876404edcSAsim Jamshed             /*
656976404edcSAsim Jamshed              * The offset is relative to the beginning of the packet
657076404edcSAsim Jamshed              * data, if we have a radio header.  (If we don't, this
657176404edcSAsim Jamshed              * is an error.)
657276404edcSAsim Jamshed              */
657376404edcSAsim Jamshed             if (linktype != DLT_IEEE802_11_RADIO_AVS &&
657476404edcSAsim Jamshed                 linktype != DLT_IEEE802_11_RADIO && linktype != DLT_PRISM_HEADER)
657576404edcSAsim Jamshed                 bpf_error("radio information not present in capture");
657676404edcSAsim Jamshed 
657776404edcSAsim Jamshed             /*
657876404edcSAsim Jamshed              * Load into the X register the offset computed into the
657976404edcSAsim Jamshed              * register specifed by "index".
658076404edcSAsim Jamshed              */
658176404edcSAsim Jamshed             s = xfer_to_x(inst);
658276404edcSAsim Jamshed 
658376404edcSAsim Jamshed             /*
658476404edcSAsim Jamshed              * Load the item at that offset.
658576404edcSAsim Jamshed              */
658676404edcSAsim Jamshed             tmp = new_stmt(BPF_LD | BPF_IND | size);
658776404edcSAsim Jamshed             sappend(s, tmp);
658876404edcSAsim Jamshed             sappend(inst->s, s);
658976404edcSAsim Jamshed             break;
659076404edcSAsim Jamshed 
659176404edcSAsim Jamshed         case Q_LINK:
659276404edcSAsim Jamshed             /*
659376404edcSAsim Jamshed              * The offset is relative to the beginning of
659476404edcSAsim Jamshed              * the link-layer header.
659576404edcSAsim Jamshed              *
659676404edcSAsim Jamshed              * XXX - what about ATM LANE?  Should the index be
659776404edcSAsim Jamshed              * relative to the beginning of the AAL5 frame, so
659876404edcSAsim Jamshed              * that 0 refers to the beginning of the LE Control
659976404edcSAsim Jamshed              * field, or relative to the beginning of the LAN
660076404edcSAsim Jamshed              * frame, so that 0 refers, for Ethernet LANE, to
660176404edcSAsim Jamshed              * the beginning of the destination address?
660276404edcSAsim Jamshed              */
660376404edcSAsim Jamshed             s = gen_llprefixlen();
660476404edcSAsim Jamshed 
660576404edcSAsim Jamshed             /*
660676404edcSAsim Jamshed              * If "s" is non-null, it has code to arrange that the
660776404edcSAsim Jamshed              * X register contains the length of the prefix preceding
660876404edcSAsim Jamshed              * the link-layer header.  Add to it the offset computed
660976404edcSAsim Jamshed              * into the register specified by "index", and move that
661076404edcSAsim Jamshed              * into the X register.  Otherwise, just load into the X
661176404edcSAsim Jamshed              * register the offset computed into the register specifed
661276404edcSAsim Jamshed              * by "index".
661376404edcSAsim Jamshed              */
661476404edcSAsim Jamshed             if (s != NULL)
661576404edcSAsim Jamshed             {
661676404edcSAsim Jamshed                 sappend(s, xfer_to_a(inst));
661776404edcSAsim Jamshed                 sappend(s, new_stmt(BPF_ALU | BPF_ADD | BPF_X));
661876404edcSAsim Jamshed                 sappend(s, new_stmt(BPF_MISC | BPF_TAX));
661976404edcSAsim Jamshed             }
662076404edcSAsim Jamshed             else
662176404edcSAsim Jamshed                 s = xfer_to_x(inst);
662276404edcSAsim Jamshed 
662376404edcSAsim Jamshed             /*
662476404edcSAsim Jamshed              * Load the item at the sum of the offset we've put in the
662576404edcSAsim Jamshed              * X register and the offset of the start of the link
662676404edcSAsim Jamshed              * layer header (which is 0 if the radio header is
662776404edcSAsim Jamshed              * variable-length; that header length is what we put
662876404edcSAsim Jamshed              * into the X register and then added to the index).
662976404edcSAsim Jamshed              */
663076404edcSAsim Jamshed             tmp = new_stmt(BPF_LD | BPF_IND | size);
663176404edcSAsim Jamshed             tmp->s.k = off_ll;
663276404edcSAsim Jamshed             sappend(s, tmp);
663376404edcSAsim Jamshed             sappend(inst->s, s);
663476404edcSAsim Jamshed             break;
663576404edcSAsim Jamshed 
663676404edcSAsim Jamshed         case Q_IP:
663776404edcSAsim Jamshed         case Q_ARP:
663876404edcSAsim Jamshed         case Q_RARP:
663976404edcSAsim Jamshed         case Q_ATALK:
664076404edcSAsim Jamshed         case Q_DECNET:
664176404edcSAsim Jamshed         case Q_SCA:
664276404edcSAsim Jamshed         case Q_LAT:
664376404edcSAsim Jamshed         case Q_MOPRC:
664476404edcSAsim Jamshed         case Q_MOPDL:
664576404edcSAsim Jamshed #ifdef INET6
664676404edcSAsim Jamshed         case Q_IPV6:
664776404edcSAsim Jamshed #endif
664876404edcSAsim Jamshed             /*
664976404edcSAsim Jamshed              * The offset is relative to the beginning of
665076404edcSAsim Jamshed              * the network-layer header.
665176404edcSAsim Jamshed              * XXX - are there any cases where we want
665276404edcSAsim Jamshed              * off_nl_nosnap?
665376404edcSAsim Jamshed              */
665476404edcSAsim Jamshed             s = gen_off_macpl();
665576404edcSAsim Jamshed 
665676404edcSAsim Jamshed             /*
665776404edcSAsim Jamshed              * If "s" is non-null, it has code to arrange that the
665876404edcSAsim Jamshed              * X register contains the offset of the MAC-layer
665976404edcSAsim Jamshed              * payload.  Add to it the offset computed into the
666076404edcSAsim Jamshed              * register specified by "index", and move that into
666176404edcSAsim Jamshed              * the X register.  Otherwise, just load into the X
666276404edcSAsim Jamshed              * register the offset computed into the register specifed
666376404edcSAsim Jamshed              * by "index".
666476404edcSAsim Jamshed              */
666576404edcSAsim Jamshed             if (s != NULL)
666676404edcSAsim Jamshed             {
666776404edcSAsim Jamshed                 sappend(s, xfer_to_a(inst));
666876404edcSAsim Jamshed                 sappend(s, new_stmt(BPF_ALU | BPF_ADD | BPF_X));
666976404edcSAsim Jamshed                 sappend(s, new_stmt(BPF_MISC | BPF_TAX));
667076404edcSAsim Jamshed             }
667176404edcSAsim Jamshed             else
667276404edcSAsim Jamshed                 s = xfer_to_x(inst);
667376404edcSAsim Jamshed 
667476404edcSAsim Jamshed             /*
667576404edcSAsim Jamshed              * Load the item at the sum of the offset we've put in the
667676404edcSAsim Jamshed              * X register, the offset of the start of the network
667776404edcSAsim Jamshed              * layer header from the beginning of the MAC-layer
667876404edcSAsim Jamshed              * payload, and the purported offset of the start of the
667976404edcSAsim Jamshed              * MAC-layer payload (which might be 0 if there's a
668076404edcSAsim Jamshed              * variable-length prefix before the link-layer header
668176404edcSAsim Jamshed              * or the link-layer header itself is variable-length;
668276404edcSAsim Jamshed              * the variable-length offset of the start of the
668376404edcSAsim Jamshed              * MAC-layer payload is what we put into the X register
668476404edcSAsim Jamshed              * and then added to the index).
668576404edcSAsim Jamshed              */
668676404edcSAsim Jamshed             tmp = new_stmt(BPF_LD | BPF_IND | size);
668776404edcSAsim Jamshed             tmp->s.k = off_macpl + off_nl;
668876404edcSAsim Jamshed             sappend(s, tmp);
668976404edcSAsim Jamshed             sappend(inst->s, s);
669076404edcSAsim Jamshed 
669176404edcSAsim Jamshed             /*
669276404edcSAsim Jamshed              * Do the computation only if the packet contains
669376404edcSAsim Jamshed              * the protocol in question.
669476404edcSAsim Jamshed              */
669576404edcSAsim Jamshed             b = gen_proto_abbrev(proto);
669676404edcSAsim Jamshed             if (inst->b)
669776404edcSAsim Jamshed                 gen_and(inst->b, b);
669876404edcSAsim Jamshed             inst->b = b;
669976404edcSAsim Jamshed             break;
670076404edcSAsim Jamshed 
670176404edcSAsim Jamshed         case Q_SCTP:
670276404edcSAsim Jamshed         case Q_TCP:
670376404edcSAsim Jamshed         case Q_UDP:
670476404edcSAsim Jamshed         case Q_ICMP:
670576404edcSAsim Jamshed         case Q_IGMP:
670676404edcSAsim Jamshed         case Q_IGRP:
670776404edcSAsim Jamshed         case Q_PIM:
670876404edcSAsim Jamshed         case Q_VRRP:
670976404edcSAsim Jamshed             /*
671076404edcSAsim Jamshed              * The offset is relative to the beginning of
671176404edcSAsim Jamshed              * the transport-layer header.
671276404edcSAsim Jamshed              *
671376404edcSAsim Jamshed              * Load the X register with the length of the IPv4 header
671476404edcSAsim Jamshed              * (plus the offset of the link-layer header, if it's
671576404edcSAsim Jamshed              * a variable-length header), in bytes.
671676404edcSAsim Jamshed              *
671776404edcSAsim Jamshed              * XXX - are there any cases where we want
671876404edcSAsim Jamshed              * off_nl_nosnap?
671976404edcSAsim Jamshed              * XXX - we should, if we're built with
672076404edcSAsim Jamshed              * IPv6 support, generate code to load either
672176404edcSAsim Jamshed              * IPv4, IPv6, or both, as appropriate.
672276404edcSAsim Jamshed              */
672376404edcSAsim Jamshed             s = gen_loadx_iphdrlen();
672476404edcSAsim Jamshed 
672576404edcSAsim Jamshed             /*
672676404edcSAsim Jamshed              * The X register now contains the sum of the length
672776404edcSAsim Jamshed              * of any variable-length header preceding the link-layer
672876404edcSAsim Jamshed              * header, any variable-length link-layer header, and the
672976404edcSAsim Jamshed              * length of the network-layer header.
673076404edcSAsim Jamshed              *
673176404edcSAsim Jamshed              * Load into the A register the offset relative to
673276404edcSAsim Jamshed              * the beginning of the transport layer header,
673376404edcSAsim Jamshed              * add the X register to that, move that to the
673476404edcSAsim Jamshed              * X register, and load with an offset from the
673576404edcSAsim Jamshed              * X register equal to the offset of the network
673676404edcSAsim Jamshed              * layer header relative to the beginning of
673776404edcSAsim Jamshed              * the MAC-layer payload plus the fixed-length
673876404edcSAsim Jamshed              * portion of the offset of the MAC-layer payload
673976404edcSAsim Jamshed              * from the beginning of the raw packet data.
674076404edcSAsim Jamshed              */
674176404edcSAsim Jamshed             sappend(s, xfer_to_a(inst));
674276404edcSAsim Jamshed             sappend(s, new_stmt(BPF_ALU | BPF_ADD | BPF_X));
674376404edcSAsim Jamshed             sappend(s, new_stmt(BPF_MISC | BPF_TAX));
674476404edcSAsim Jamshed             sappend(s, tmp = new_stmt(BPF_LD | BPF_IND | size));
674576404edcSAsim Jamshed             tmp->s.k = off_macpl + off_nl;
674676404edcSAsim Jamshed             sappend(inst->s, s);
674776404edcSAsim Jamshed 
674876404edcSAsim Jamshed             /*
674976404edcSAsim Jamshed              * Do the computation only if the packet contains
675076404edcSAsim Jamshed              * the protocol in question - which is true only
675176404edcSAsim Jamshed              * if this is an IP datagram and is the first or
675276404edcSAsim Jamshed              * only fragment of that datagram.
675376404edcSAsim Jamshed              */
675476404edcSAsim Jamshed             gen_and(gen_proto_abbrev(proto), b = gen_ipfrag());
675576404edcSAsim Jamshed             if (inst->b)
675676404edcSAsim Jamshed                 gen_and(inst->b, b);
675776404edcSAsim Jamshed #ifdef INET6
675876404edcSAsim Jamshed             gen_and(gen_proto_abbrev(Q_IP), b);
675976404edcSAsim Jamshed #endif
676076404edcSAsim Jamshed             inst->b = b;
676176404edcSAsim Jamshed             break;
676276404edcSAsim Jamshed #ifdef INET6
676376404edcSAsim Jamshed         case Q_ICMPV6:
676476404edcSAsim Jamshed             bpf_error("IPv6 upper-layer protocol is not supported by proto[x]");
676576404edcSAsim Jamshed              /*NOTREACHED*/
676676404edcSAsim Jamshed #endif
676776404edcSAsim Jamshed     }
676876404edcSAsim Jamshed     inst->regno = regno;
676976404edcSAsim Jamshed     s = new_stmt(BPF_ST);
677076404edcSAsim Jamshed     s->s.k = regno;
677176404edcSAsim Jamshed     sappend(inst->s, s);
677276404edcSAsim Jamshed 
677376404edcSAsim Jamshed     return inst;
677476404edcSAsim Jamshed }
677576404edcSAsim Jamshed 
gen_relation(code,a0,a1,reversed)677676404edcSAsim Jamshed struct block *gen_relation(code, a0, a1, reversed)
677776404edcSAsim Jamshed      int code;
677876404edcSAsim Jamshed      struct arth *a0, *a1;
677976404edcSAsim Jamshed      int reversed;
678076404edcSAsim Jamshed {
678176404edcSAsim Jamshed     struct slist *s0, *s1, *s2;
678276404edcSAsim Jamshed     struct block *b, *tmp;
678376404edcSAsim Jamshed 
678476404edcSAsim Jamshed     s0 = xfer_to_x(a1);
678576404edcSAsim Jamshed     s1 = xfer_to_a(a0);
678676404edcSAsim Jamshed     if (code == BPF_JEQ)
678776404edcSAsim Jamshed     {
678876404edcSAsim Jamshed         s2 = new_stmt(BPF_ALU | BPF_SUB | BPF_X);
678976404edcSAsim Jamshed         b = new_block(JMP(code));
679076404edcSAsim Jamshed         sappend(s1, s2);
679176404edcSAsim Jamshed     }
679276404edcSAsim Jamshed     else
679376404edcSAsim Jamshed         b = new_block(BPF_JMP | code | BPF_X);
679476404edcSAsim Jamshed     if (reversed)
679576404edcSAsim Jamshed         gen_not(b);
679676404edcSAsim Jamshed 
679776404edcSAsim Jamshed     sappend(s0, s1);
679876404edcSAsim Jamshed     sappend(a1->s, s0);
679976404edcSAsim Jamshed     sappend(a0->s, a1->s);
680076404edcSAsim Jamshed 
680176404edcSAsim Jamshed     b->stmts = a0->s;
680276404edcSAsim Jamshed 
680376404edcSAsim Jamshed     free_reg(a0->regno);
680476404edcSAsim Jamshed     free_reg(a1->regno);
680576404edcSAsim Jamshed 
680676404edcSAsim Jamshed     /* 'and' together protocol checks */
680776404edcSAsim Jamshed     if (a0->b)
680876404edcSAsim Jamshed     {
680976404edcSAsim Jamshed         if (a1->b)
681076404edcSAsim Jamshed         {
681176404edcSAsim Jamshed             gen_and(a0->b, tmp = a1->b);
681276404edcSAsim Jamshed         }
681376404edcSAsim Jamshed         else
681476404edcSAsim Jamshed             tmp = a0->b;
681576404edcSAsim Jamshed     }
681676404edcSAsim Jamshed     else
681776404edcSAsim Jamshed         tmp = a1->b;
681876404edcSAsim Jamshed 
681976404edcSAsim Jamshed     if (tmp)
682076404edcSAsim Jamshed         gen_and(tmp, b);
682176404edcSAsim Jamshed 
682276404edcSAsim Jamshed     return b;
682376404edcSAsim Jamshed }
682476404edcSAsim Jamshed 
gen_loadlen()682576404edcSAsim Jamshed struct arth *gen_loadlen()
682676404edcSAsim Jamshed {
682776404edcSAsim Jamshed     int regno = alloc_reg();
682876404edcSAsim Jamshed     struct arth *a = (struct arth *) newchunk(sizeof(*a));
682976404edcSAsim Jamshed     struct slist *s;
683076404edcSAsim Jamshed 
683176404edcSAsim Jamshed     s = new_stmt(BPF_LD | BPF_LEN);
683276404edcSAsim Jamshed     s->next = new_stmt(BPF_ST);
683376404edcSAsim Jamshed     s->next->s.k = regno;
683476404edcSAsim Jamshed     a->s = s;
683576404edcSAsim Jamshed     a->regno = regno;
683676404edcSAsim Jamshed 
683776404edcSAsim Jamshed     return a;
683876404edcSAsim Jamshed }
683976404edcSAsim Jamshed 
gen_loadi(val)684076404edcSAsim Jamshed struct arth *gen_loadi(val)
684176404edcSAsim Jamshed      int val;
684276404edcSAsim Jamshed {
684376404edcSAsim Jamshed     struct arth *a;
684476404edcSAsim Jamshed     struct slist *s;
684576404edcSAsim Jamshed     int reg;
684676404edcSAsim Jamshed 
684776404edcSAsim Jamshed     a = (struct arth *) newchunk(sizeof(*a));
684876404edcSAsim Jamshed 
684976404edcSAsim Jamshed     reg = alloc_reg();
685076404edcSAsim Jamshed 
685176404edcSAsim Jamshed     s = new_stmt(BPF_LD | BPF_IMM);
685276404edcSAsim Jamshed     s->s.k = val;
685376404edcSAsim Jamshed     s->next = new_stmt(BPF_ST);
685476404edcSAsim Jamshed     s->next->s.k = reg;
685576404edcSAsim Jamshed     a->s = s;
685676404edcSAsim Jamshed     a->regno = reg;
685776404edcSAsim Jamshed 
685876404edcSAsim Jamshed     return a;
685976404edcSAsim Jamshed }
686076404edcSAsim Jamshed 
gen_neg(a)686176404edcSAsim Jamshed struct arth *gen_neg(a)
686276404edcSAsim Jamshed      struct arth *a;
686376404edcSAsim Jamshed {
686476404edcSAsim Jamshed     struct slist *s;
686576404edcSAsim Jamshed 
686676404edcSAsim Jamshed     s = xfer_to_a(a);
686776404edcSAsim Jamshed     sappend(a->s, s);
686876404edcSAsim Jamshed     s = new_stmt(BPF_ALU | BPF_NEG);
686976404edcSAsim Jamshed     s->s.k = 0;
687076404edcSAsim Jamshed     sappend(a->s, s);
687176404edcSAsim Jamshed     s = new_stmt(BPF_ST);
687276404edcSAsim Jamshed     s->s.k = a->regno;
687376404edcSAsim Jamshed     sappend(a->s, s);
687476404edcSAsim Jamshed 
687576404edcSAsim Jamshed     return a;
687676404edcSAsim Jamshed }
687776404edcSAsim Jamshed 
gen_arth(code,a0,a1)687876404edcSAsim Jamshed struct arth *gen_arth(code, a0, a1)
687976404edcSAsim Jamshed      int code;
688076404edcSAsim Jamshed      struct arth *a0, *a1;
688176404edcSAsim Jamshed {
688276404edcSAsim Jamshed     struct slist *s0, *s1, *s2;
688376404edcSAsim Jamshed 
688476404edcSAsim Jamshed     s0 = xfer_to_x(a1);
688576404edcSAsim Jamshed     s1 = xfer_to_a(a0);
688676404edcSAsim Jamshed     s2 = new_stmt(BPF_ALU | BPF_X | code);
688776404edcSAsim Jamshed 
688876404edcSAsim Jamshed     sappend(s1, s2);
688976404edcSAsim Jamshed     sappend(s0, s1);
689076404edcSAsim Jamshed     sappend(a1->s, s0);
689176404edcSAsim Jamshed     sappend(a0->s, a1->s);
689276404edcSAsim Jamshed 
689376404edcSAsim Jamshed     free_reg(a0->regno);
689476404edcSAsim Jamshed     free_reg(a1->regno);
689576404edcSAsim Jamshed 
689676404edcSAsim Jamshed     s0 = new_stmt(BPF_ST);
689776404edcSAsim Jamshed     a0->regno = s0->s.k = alloc_reg();
689876404edcSAsim Jamshed     sappend(a0->s, s0);
689976404edcSAsim Jamshed 
690076404edcSAsim Jamshed     return a0;
690176404edcSAsim Jamshed }
690276404edcSAsim Jamshed 
690376404edcSAsim Jamshed /*
690476404edcSAsim Jamshed  * Here we handle simple allocation of the scratch registers.
690576404edcSAsim Jamshed  * If too many registers are alloc'd, the allocator punts.
690676404edcSAsim Jamshed  */
690776404edcSAsim Jamshed static __thread int regused[BPF_MEMWORDS];
690876404edcSAsim Jamshed static __thread int curreg;
690976404edcSAsim Jamshed 
691076404edcSAsim Jamshed /*
691176404edcSAsim Jamshed  * Initialize the table of used registers and the current register.
691276404edcSAsim Jamshed  */
init_regs()691376404edcSAsim Jamshed static void init_regs()
691476404edcSAsim Jamshed {
691576404edcSAsim Jamshed     curreg = 0;
691676404edcSAsim Jamshed     memset(regused, 0, sizeof regused);
691776404edcSAsim Jamshed }
691876404edcSAsim Jamshed 
691976404edcSAsim Jamshed /*
692076404edcSAsim Jamshed  * Return the next free register.
692176404edcSAsim Jamshed  */
alloc_reg()692276404edcSAsim Jamshed static int alloc_reg()
692376404edcSAsim Jamshed {
692476404edcSAsim Jamshed     int n = BPF_MEMWORDS;
692576404edcSAsim Jamshed 
692676404edcSAsim Jamshed     while (--n >= 0)
692776404edcSAsim Jamshed     {
692876404edcSAsim Jamshed         if (regused[curreg])
692976404edcSAsim Jamshed             curreg = (curreg + 1) % BPF_MEMWORDS;
693076404edcSAsim Jamshed         else
693176404edcSAsim Jamshed         {
693276404edcSAsim Jamshed             regused[curreg] = 1;
693376404edcSAsim Jamshed             return curreg;
693476404edcSAsim Jamshed         }
693576404edcSAsim Jamshed     }
693676404edcSAsim Jamshed     bpf_error("too many registers needed to evaluate expression");
693776404edcSAsim Jamshed     /* NOTREACHED */
693876404edcSAsim Jamshed     return 0;
693976404edcSAsim Jamshed }
694076404edcSAsim Jamshed 
694176404edcSAsim Jamshed /*
694276404edcSAsim Jamshed  * Return a register to the table so it can
694376404edcSAsim Jamshed  * be used later.
694476404edcSAsim Jamshed  */
free_reg(n)694576404edcSAsim Jamshed static void free_reg(n)
694676404edcSAsim Jamshed      int n;
694776404edcSAsim Jamshed {
694876404edcSAsim Jamshed     regused[n] = 0;
694976404edcSAsim Jamshed }
695076404edcSAsim Jamshed 
gen_len(jmp,n)695176404edcSAsim Jamshed static struct block *gen_len(jmp, n)
695276404edcSAsim Jamshed      int jmp, n;
695376404edcSAsim Jamshed {
695476404edcSAsim Jamshed     struct slist *s;
695576404edcSAsim Jamshed     struct block *b;
695676404edcSAsim Jamshed 
695776404edcSAsim Jamshed     s = new_stmt(BPF_LD | BPF_LEN);
695876404edcSAsim Jamshed     b = new_block(JMP(jmp));
695976404edcSAsim Jamshed     b->stmts = s;
696076404edcSAsim Jamshed     b->s.k = n;
696176404edcSAsim Jamshed 
696276404edcSAsim Jamshed     return b;
696376404edcSAsim Jamshed }
696476404edcSAsim Jamshed 
gen_greater(n)696576404edcSAsim Jamshed struct block *gen_greater(n)
696676404edcSAsim Jamshed      int n;
696776404edcSAsim Jamshed {
696876404edcSAsim Jamshed     return gen_len(BPF_JGE, n);
696976404edcSAsim Jamshed }
697076404edcSAsim Jamshed 
697176404edcSAsim Jamshed /*
697276404edcSAsim Jamshed  * Actually, this is less than or equal.
697376404edcSAsim Jamshed  */
gen_less(n)697476404edcSAsim Jamshed struct block *gen_less(n)
697576404edcSAsim Jamshed      int n;
697676404edcSAsim Jamshed {
697776404edcSAsim Jamshed     struct block *b;
697876404edcSAsim Jamshed 
697976404edcSAsim Jamshed     b = gen_len(BPF_JGT, n);
698076404edcSAsim Jamshed     gen_not(b);
698176404edcSAsim Jamshed 
698276404edcSAsim Jamshed     return b;
698376404edcSAsim Jamshed }
698476404edcSAsim Jamshed 
698576404edcSAsim Jamshed /*
698676404edcSAsim Jamshed  * This is for "byte {idx} {op} {val}"; "idx" is treated as relative to
698776404edcSAsim Jamshed  * the beginning of the link-layer header.
698876404edcSAsim Jamshed  * XXX - that means you can't test values in the radiotap header, but
698976404edcSAsim Jamshed  * as that header is difficult if not impossible to parse generally
699076404edcSAsim Jamshed  * without a loop, that might not be a severe problem.  A new keyword
699176404edcSAsim Jamshed  * "radio" could be added for that, although what you'd really want
699276404edcSAsim Jamshed  * would be a way of testing particular radio header values, which
699376404edcSAsim Jamshed  * would generate code appropriate to the radio header in question.
699476404edcSAsim Jamshed  */
gen_byteop(op,idx,val)699576404edcSAsim Jamshed struct block *gen_byteop(op, idx, val)
699676404edcSAsim Jamshed      int op, idx, val;
699776404edcSAsim Jamshed {
699876404edcSAsim Jamshed     struct block *b;
699976404edcSAsim Jamshed     struct slist *s;
700076404edcSAsim Jamshed 
700176404edcSAsim Jamshed     switch (op)
700276404edcSAsim Jamshed     {
700376404edcSAsim Jamshed         default:
700476404edcSAsim Jamshed             abort();
700576404edcSAsim Jamshed 
700676404edcSAsim Jamshed         case '=':
700776404edcSAsim Jamshed             return gen_cmp(OR_LINK, (u_int) idx, BPF_B, (bpf_int32) val);
700876404edcSAsim Jamshed 
700976404edcSAsim Jamshed         case '<':
701076404edcSAsim Jamshed             b = gen_cmp_lt(OR_LINK, (u_int) idx, BPF_B, (bpf_int32) val);
701176404edcSAsim Jamshed             return b;
701276404edcSAsim Jamshed 
701376404edcSAsim Jamshed         case '>':
701476404edcSAsim Jamshed             b = gen_cmp_gt(OR_LINK, (u_int) idx, BPF_B, (bpf_int32) val);
701576404edcSAsim Jamshed             return b;
701676404edcSAsim Jamshed 
701776404edcSAsim Jamshed         case '|':
701876404edcSAsim Jamshed             s = new_stmt(BPF_ALU | BPF_OR | BPF_K);
701976404edcSAsim Jamshed             break;
702076404edcSAsim Jamshed 
702176404edcSAsim Jamshed         case '&':
702276404edcSAsim Jamshed             s = new_stmt(BPF_ALU | BPF_AND | BPF_K);
702376404edcSAsim Jamshed             break;
702476404edcSAsim Jamshed     }
702576404edcSAsim Jamshed     s->s.k = val;
702676404edcSAsim Jamshed     b = new_block(JMP(BPF_JEQ));
702776404edcSAsim Jamshed     b->stmts = s;
702876404edcSAsim Jamshed     gen_not(b);
702976404edcSAsim Jamshed 
703076404edcSAsim Jamshed     return b;
703176404edcSAsim Jamshed }
703276404edcSAsim Jamshed 
703376404edcSAsim Jamshed static __thread u_char abroadcast[] = { 0x0 };
703476404edcSAsim Jamshed 
gen_broadcast(proto)703576404edcSAsim Jamshed struct block *gen_broadcast(proto)
703676404edcSAsim Jamshed      int proto;
703776404edcSAsim Jamshed {
703876404edcSAsim Jamshed     bpf_u_int32 hostmask;
703976404edcSAsim Jamshed     struct block *b0, *b1, *b2;
704076404edcSAsim Jamshed     static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
704176404edcSAsim Jamshed 
704276404edcSAsim Jamshed     switch (proto)
704376404edcSAsim Jamshed     {
704476404edcSAsim Jamshed 
704576404edcSAsim Jamshed         case Q_DEFAULT:
704676404edcSAsim Jamshed         case Q_LINK:
704776404edcSAsim Jamshed             switch (linktype)
704876404edcSAsim Jamshed             {
704976404edcSAsim Jamshed                 case DLT_ARCNET:
705076404edcSAsim Jamshed                 case DLT_ARCNET_LINUX:
705176404edcSAsim Jamshed                     return gen_ahostop(abroadcast, Q_DST);
705276404edcSAsim Jamshed                 case DLT_EN10MB:
705376404edcSAsim Jamshed                     return gen_ehostop(ebroadcast, Q_DST);
705476404edcSAsim Jamshed                 case DLT_FDDI:
705576404edcSAsim Jamshed                     return gen_fhostop(ebroadcast, Q_DST);
705676404edcSAsim Jamshed                 case DLT_IEEE802:
705776404edcSAsim Jamshed                     return gen_thostop(ebroadcast, Q_DST);
705876404edcSAsim Jamshed                 case DLT_IEEE802_11:
705976404edcSAsim Jamshed                 case DLT_PRISM_HEADER:
706076404edcSAsim Jamshed                 case DLT_IEEE802_11_RADIO_AVS:
706176404edcSAsim Jamshed                 case DLT_IEEE802_11_RADIO:
706276404edcSAsim Jamshed                 case DLT_PPI:
706376404edcSAsim Jamshed                     return gen_wlanhostop(ebroadcast, Q_DST);
706476404edcSAsim Jamshed                 case DLT_IP_OVER_FC:
706576404edcSAsim Jamshed                     return gen_ipfchostop(ebroadcast, Q_DST);
706676404edcSAsim Jamshed                 case DLT_SUNATM:
706776404edcSAsim Jamshed                     if (is_lane)
706876404edcSAsim Jamshed                     {
706976404edcSAsim Jamshed                         /*
707076404edcSAsim Jamshed                          * Check that the packet doesn't begin with an
707176404edcSAsim Jamshed                          * LE Control marker.  (We've already generated
707276404edcSAsim Jamshed                          * a test for LANE.)
707376404edcSAsim Jamshed                          */
707476404edcSAsim Jamshed                         b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
707576404edcSAsim Jamshed                         gen_not(b1);
707676404edcSAsim Jamshed 
707776404edcSAsim Jamshed                         /*
707876404edcSAsim Jamshed                          * Now check the MAC address.
707976404edcSAsim Jamshed                          */
708076404edcSAsim Jamshed                         b0 = gen_ehostop(ebroadcast, Q_DST);
708176404edcSAsim Jamshed                         gen_and(b1, b0);
708276404edcSAsim Jamshed                         return b0;
708376404edcSAsim Jamshed                     }
708476404edcSAsim Jamshed                     break;
708576404edcSAsim Jamshed                 default:
708676404edcSAsim Jamshed                     bpf_error("not a broadcast link");
708776404edcSAsim Jamshed             }
708876404edcSAsim Jamshed             break;
708976404edcSAsim Jamshed 
709076404edcSAsim Jamshed         case Q_IP:
709176404edcSAsim Jamshed             /*
709276404edcSAsim Jamshed              * We treat a netmask of PCAP_NETMASK_UNKNOWN (0xffffffff)
709376404edcSAsim Jamshed              * as an indication that we don't know the netmask, and fail
709476404edcSAsim Jamshed              * in that case.
709576404edcSAsim Jamshed              */
709676404edcSAsim Jamshed             if (netmask == PCAP_NETMASK_UNKNOWN)
709776404edcSAsim Jamshed                 bpf_error("netmask not known, so 'ip broadcast' not supported");
709876404edcSAsim Jamshed             b0 = gen_linktype(ETHERTYPE_IP);
709976404edcSAsim Jamshed             hostmask = ~netmask;
710076404edcSAsim Jamshed             b1 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32) 0, hostmask);
710176404edcSAsim Jamshed             b2 = gen_mcmp(OR_NET, 16, BPF_W, (bpf_int32) (~0 & hostmask), hostmask);
710276404edcSAsim Jamshed             gen_or(b1, b2);
710376404edcSAsim Jamshed             gen_and(b0, b2);
710476404edcSAsim Jamshed             return b2;
710576404edcSAsim Jamshed     }
710676404edcSAsim Jamshed     bpf_error("only link-layer/IP broadcast filters supported");
710776404edcSAsim Jamshed     /* NOTREACHED */
710876404edcSAsim Jamshed     return NULL;
710976404edcSAsim Jamshed }
711076404edcSAsim Jamshed 
711176404edcSAsim Jamshed /*
711276404edcSAsim Jamshed  * Generate code to test the low-order bit of a MAC address (that's
711376404edcSAsim Jamshed  * the bottom bit of the *first* byte).
711476404edcSAsim Jamshed  */
gen_mac_multicast(offset)711576404edcSAsim Jamshed static struct block *gen_mac_multicast(offset)
711676404edcSAsim Jamshed      int offset;
711776404edcSAsim Jamshed {
711876404edcSAsim Jamshed     register struct block *b0;
711976404edcSAsim Jamshed     register struct slist *s;
712076404edcSAsim Jamshed 
712176404edcSAsim Jamshed     /* link[offset] & 1 != 0 */
712276404edcSAsim Jamshed     s = gen_load_a(OR_LINK, offset, BPF_B);
712376404edcSAsim Jamshed     b0 = new_block(JMP(BPF_JSET));
712476404edcSAsim Jamshed     b0->s.k = 1;
712576404edcSAsim Jamshed     b0->stmts = s;
712676404edcSAsim Jamshed     return b0;
712776404edcSAsim Jamshed }
712876404edcSAsim Jamshed 
gen_multicast(proto)712976404edcSAsim Jamshed struct block *gen_multicast(proto)
713076404edcSAsim Jamshed      int proto;
713176404edcSAsim Jamshed {
713276404edcSAsim Jamshed     register struct block *b0, *b1, *b2;
713376404edcSAsim Jamshed     register struct slist *s;
713476404edcSAsim Jamshed 
713576404edcSAsim Jamshed     switch (proto)
713676404edcSAsim Jamshed     {
713776404edcSAsim Jamshed 
713876404edcSAsim Jamshed         case Q_DEFAULT:
713976404edcSAsim Jamshed         case Q_LINK:
714076404edcSAsim Jamshed             switch (linktype)
714176404edcSAsim Jamshed             {
714276404edcSAsim Jamshed                 case DLT_ARCNET:
714376404edcSAsim Jamshed                 case DLT_ARCNET_LINUX:
714476404edcSAsim Jamshed                     /* all ARCnet multicasts use the same address */
714576404edcSAsim Jamshed                     return gen_ahostop(abroadcast, Q_DST);
714676404edcSAsim Jamshed                 case DLT_EN10MB:
714776404edcSAsim Jamshed                     /* ether[0] & 1 != 0 */
714876404edcSAsim Jamshed                     return gen_mac_multicast(0);
714976404edcSAsim Jamshed                 case DLT_FDDI:
715076404edcSAsim Jamshed                     /*
715176404edcSAsim Jamshed                      * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX
715276404edcSAsim Jamshed                      *
715376404edcSAsim Jamshed                      * XXX - was that referring to bit-order issues?
715476404edcSAsim Jamshed                      */
715576404edcSAsim Jamshed                     /* fddi[1] & 1 != 0 */
715676404edcSAsim Jamshed                     return gen_mac_multicast(1);
715776404edcSAsim Jamshed                 case DLT_IEEE802:
715876404edcSAsim Jamshed                     /* tr[2] & 1 != 0 */
715976404edcSAsim Jamshed                     return gen_mac_multicast(2);
716076404edcSAsim Jamshed                 case DLT_IEEE802_11:
716176404edcSAsim Jamshed                 case DLT_PRISM_HEADER:
716276404edcSAsim Jamshed                 case DLT_IEEE802_11_RADIO_AVS:
716376404edcSAsim Jamshed                 case DLT_IEEE802_11_RADIO:
716476404edcSAsim Jamshed                 case DLT_PPI:
716576404edcSAsim Jamshed                     /*
716676404edcSAsim Jamshed                      * Oh, yuk.
716776404edcSAsim Jamshed                      *
716876404edcSAsim Jamshed                      *  For control frames, there is no DA.
716976404edcSAsim Jamshed                      *
717076404edcSAsim Jamshed                      *  For management frames, DA is at an
717176404edcSAsim Jamshed                      *  offset of 4 from the beginning of
717276404edcSAsim Jamshed                      *  the packet.
717376404edcSAsim Jamshed                      *
717476404edcSAsim Jamshed                      *  For data frames, DA is at an offset
717576404edcSAsim Jamshed                      *  of 4 from the beginning of the packet
717676404edcSAsim Jamshed                      *  if To DS is clear and at an offset of
717776404edcSAsim Jamshed                      *  16 from the beginning of the packet
717876404edcSAsim Jamshed                      *  if To DS is set.
717976404edcSAsim Jamshed                      */
718076404edcSAsim Jamshed 
718176404edcSAsim Jamshed                     /*
718276404edcSAsim Jamshed                      * Generate the tests to be done for data frames.
718376404edcSAsim Jamshed                      *
718476404edcSAsim Jamshed                      * First, check for To DS set, i.e. "link[1] & 0x01".
718576404edcSAsim Jamshed                      */
718676404edcSAsim Jamshed                     s = gen_load_a(OR_LINK, 1, BPF_B);
718776404edcSAsim Jamshed                     b1 = new_block(JMP(BPF_JSET));
718876404edcSAsim Jamshed                     b1->s.k = 0x01; /* To DS */
718976404edcSAsim Jamshed                     b1->stmts = s;
719076404edcSAsim Jamshed 
719176404edcSAsim Jamshed                     /*
719276404edcSAsim Jamshed                      * If To DS is set, the DA is at 16.
719376404edcSAsim Jamshed                      */
719476404edcSAsim Jamshed                     b0 = gen_mac_multicast(16);
719576404edcSAsim Jamshed                     gen_and(b1, b0);
719676404edcSAsim Jamshed 
719776404edcSAsim Jamshed                     /*
719876404edcSAsim Jamshed                      * Now, check for To DS not set, i.e. check
719976404edcSAsim Jamshed                      * "!(link[1] & 0x01)".
720076404edcSAsim Jamshed                      */
720176404edcSAsim Jamshed                     s = gen_load_a(OR_LINK, 1, BPF_B);
720276404edcSAsim Jamshed                     b2 = new_block(JMP(BPF_JSET));
720376404edcSAsim Jamshed                     b2->s.k = 0x01; /* To DS */
720476404edcSAsim Jamshed                     b2->stmts = s;
720576404edcSAsim Jamshed                     gen_not(b2);
720676404edcSAsim Jamshed 
720776404edcSAsim Jamshed                     /*
720876404edcSAsim Jamshed                      * If To DS is not set, the DA is at 4.
720976404edcSAsim Jamshed                      */
721076404edcSAsim Jamshed                     b1 = gen_mac_multicast(4);
721176404edcSAsim Jamshed                     gen_and(b2, b1);
721276404edcSAsim Jamshed 
721376404edcSAsim Jamshed                     /*
721476404edcSAsim Jamshed                      * Now OR together the last two checks.  That gives
721576404edcSAsim Jamshed                      * the complete set of checks for data frames.
721676404edcSAsim Jamshed                      */
721776404edcSAsim Jamshed                     gen_or(b1, b0);
721876404edcSAsim Jamshed 
721976404edcSAsim Jamshed                     /*
722076404edcSAsim Jamshed                      * Now check for a data frame.
722176404edcSAsim Jamshed                      * I.e, check "link[0] & 0x08".
722276404edcSAsim Jamshed                      */
722376404edcSAsim Jamshed                     s = gen_load_a(OR_LINK, 0, BPF_B);
722476404edcSAsim Jamshed                     b1 = new_block(JMP(BPF_JSET));
722576404edcSAsim Jamshed                     b1->s.k = 0x08;
722676404edcSAsim Jamshed                     b1->stmts = s;
722776404edcSAsim Jamshed 
722876404edcSAsim Jamshed                     /*
722976404edcSAsim Jamshed                      * AND that with the checks done for data frames.
723076404edcSAsim Jamshed                      */
723176404edcSAsim Jamshed                     gen_and(b1, b0);
723276404edcSAsim Jamshed 
723376404edcSAsim Jamshed                     /*
723476404edcSAsim Jamshed                      * If the high-order bit of the type value is 0, this
723576404edcSAsim Jamshed                      * is a management frame.
723676404edcSAsim Jamshed                      * I.e, check "!(link[0] & 0x08)".
723776404edcSAsim Jamshed                      */
723876404edcSAsim Jamshed                     s = gen_load_a(OR_LINK, 0, BPF_B);
723976404edcSAsim Jamshed                     b2 = new_block(JMP(BPF_JSET));
724076404edcSAsim Jamshed                     b2->s.k = 0x08;
724176404edcSAsim Jamshed                     b2->stmts = s;
724276404edcSAsim Jamshed                     gen_not(b2);
724376404edcSAsim Jamshed 
724476404edcSAsim Jamshed                     /*
724576404edcSAsim Jamshed                      * For management frames, the DA is at 4.
724676404edcSAsim Jamshed                      */
724776404edcSAsim Jamshed                     b1 = gen_mac_multicast(4);
724876404edcSAsim Jamshed                     gen_and(b2, b1);
724976404edcSAsim Jamshed 
725076404edcSAsim Jamshed                     /*
725176404edcSAsim Jamshed                      * OR that with the checks done for data frames.
725276404edcSAsim Jamshed                      * That gives the checks done for management and
725376404edcSAsim Jamshed                      * data frames.
725476404edcSAsim Jamshed                      */
725576404edcSAsim Jamshed                     gen_or(b1, b0);
725676404edcSAsim Jamshed 
725776404edcSAsim Jamshed                     /*
725876404edcSAsim Jamshed                      * If the low-order bit of the type value is 1,
725976404edcSAsim Jamshed                      * this is either a control frame or a frame
726076404edcSAsim Jamshed                      * with a reserved type, and thus not a
726176404edcSAsim Jamshed                      * frame with an SA.
726276404edcSAsim Jamshed                      *
726376404edcSAsim Jamshed                      * I.e., check "!(link[0] & 0x04)".
726476404edcSAsim Jamshed                      */
726576404edcSAsim Jamshed                     s = gen_load_a(OR_LINK, 0, BPF_B);
726676404edcSAsim Jamshed                     b1 = new_block(JMP(BPF_JSET));
726776404edcSAsim Jamshed                     b1->s.k = 0x04;
726876404edcSAsim Jamshed                     b1->stmts = s;
726976404edcSAsim Jamshed                     gen_not(b1);
727076404edcSAsim Jamshed 
727176404edcSAsim Jamshed                     /*
727276404edcSAsim Jamshed                      * AND that with the checks for data and management
727376404edcSAsim Jamshed                      * frames.
727476404edcSAsim Jamshed                      */
727576404edcSAsim Jamshed                     gen_and(b1, b0);
727676404edcSAsim Jamshed                     return b0;
727776404edcSAsim Jamshed                 case DLT_IP_OVER_FC:
727876404edcSAsim Jamshed                     b0 = gen_mac_multicast(2);
727976404edcSAsim Jamshed                     return b0;
728076404edcSAsim Jamshed                 case DLT_SUNATM:
728176404edcSAsim Jamshed                     if (is_lane)
728276404edcSAsim Jamshed                     {
728376404edcSAsim Jamshed                         /*
728476404edcSAsim Jamshed                          * Check that the packet doesn't begin with an
728576404edcSAsim Jamshed                          * LE Control marker.  (We've already generated
728676404edcSAsim Jamshed                          * a test for LANE.)
728776404edcSAsim Jamshed                          */
728876404edcSAsim Jamshed                         b1 = gen_cmp(OR_LINK, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
728976404edcSAsim Jamshed                         gen_not(b1);
729076404edcSAsim Jamshed 
729176404edcSAsim Jamshed                         /* ether[off_mac] & 1 != 0 */
729276404edcSAsim Jamshed                         b0 = gen_mac_multicast(off_mac);
729376404edcSAsim Jamshed                         gen_and(b1, b0);
729476404edcSAsim Jamshed                         return b0;
729576404edcSAsim Jamshed                     }
729676404edcSAsim Jamshed                     break;
729776404edcSAsim Jamshed                 default:
729876404edcSAsim Jamshed                     break;
729976404edcSAsim Jamshed             }
730076404edcSAsim Jamshed             /* Link not known to support multicasts */
730176404edcSAsim Jamshed             break;
730276404edcSAsim Jamshed 
730376404edcSAsim Jamshed         case Q_IP:
730476404edcSAsim Jamshed             b0 = gen_linktype(ETHERTYPE_IP);
730576404edcSAsim Jamshed             b1 = gen_cmp_ge(OR_NET, 16, BPF_B, (bpf_int32) 224);
730676404edcSAsim Jamshed             gen_and(b0, b1);
730776404edcSAsim Jamshed             return b1;
730876404edcSAsim Jamshed 
730976404edcSAsim Jamshed #ifdef INET6
731076404edcSAsim Jamshed         case Q_IPV6:
731176404edcSAsim Jamshed             b0 = gen_linktype(ETHERTYPE_IPV6);
731276404edcSAsim Jamshed             b1 = gen_cmp(OR_NET, 24, BPF_B, (bpf_int32) 255);
731376404edcSAsim Jamshed             gen_and(b0, b1);
731476404edcSAsim Jamshed             return b1;
731576404edcSAsim Jamshed #endif /* INET6 */
731676404edcSAsim Jamshed     }
731776404edcSAsim Jamshed     bpf_error
731876404edcSAsim Jamshed         ("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
731976404edcSAsim Jamshed     /* NOTREACHED */
732076404edcSAsim Jamshed     return NULL;
732176404edcSAsim Jamshed }
732276404edcSAsim Jamshed 
732376404edcSAsim Jamshed /*
732476404edcSAsim Jamshed  * generate command for inbound/outbound.  It's here so we can
732576404edcSAsim Jamshed  * make it link-type specific.  'dir' = 0 implies "inbound",
732676404edcSAsim Jamshed  * = 1 implies "outbound".
732776404edcSAsim Jamshed  */
gen_inbound(dir)732876404edcSAsim Jamshed struct block *gen_inbound(dir)
732976404edcSAsim Jamshed      int dir;
733076404edcSAsim Jamshed {
733176404edcSAsim Jamshed     register struct block *b0;
733276404edcSAsim Jamshed 
733376404edcSAsim Jamshed     /*
733476404edcSAsim Jamshed      * Only some data link types support inbound/outbound qualifiers.
733576404edcSAsim Jamshed      */
733676404edcSAsim Jamshed     switch (linktype)
733776404edcSAsim Jamshed     {
733876404edcSAsim Jamshed         case DLT_SLIP:
733976404edcSAsim Jamshed             b0 = gen_relation(BPF_JEQ, gen_load(Q_LINK, gen_loadi(0), 1), gen_loadi(0), dir);
734076404edcSAsim Jamshed             break;
734176404edcSAsim Jamshed 
734276404edcSAsim Jamshed         case DLT_IPNET:
734376404edcSAsim Jamshed             if (dir)
734476404edcSAsim Jamshed             {
734576404edcSAsim Jamshed                 /* match outgoing packets */
734676404edcSAsim Jamshed                 b0 = gen_cmp(OR_LINK, 2, BPF_H, IPNET_OUTBOUND);
734776404edcSAsim Jamshed             }
734876404edcSAsim Jamshed             else
734976404edcSAsim Jamshed             {
735076404edcSAsim Jamshed                 /* match incoming packets */
735176404edcSAsim Jamshed                 b0 = gen_cmp(OR_LINK, 2, BPF_H, IPNET_INBOUND);
735276404edcSAsim Jamshed             }
735376404edcSAsim Jamshed             break;
735476404edcSAsim Jamshed 
735576404edcSAsim Jamshed         case DLT_LINUX_SLL:
735676404edcSAsim Jamshed             if (dir)
735776404edcSAsim Jamshed             {
735876404edcSAsim Jamshed                 /*
735976404edcSAsim Jamshed                  * Match packets sent by this machine.
736076404edcSAsim Jamshed                  */
736176404edcSAsim Jamshed                 b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_OUTGOING);
736276404edcSAsim Jamshed             }
736376404edcSAsim Jamshed             else
736476404edcSAsim Jamshed             {
736576404edcSAsim Jamshed                 /*
736676404edcSAsim Jamshed                  * Match packets sent to this machine.
736776404edcSAsim Jamshed                  * (No broadcast or multicast packets, or
736876404edcSAsim Jamshed                  * packets sent to some other machine and
736976404edcSAsim Jamshed                  * received promiscuously.)
737076404edcSAsim Jamshed                  *
737176404edcSAsim Jamshed                  * XXX - packets sent to other machines probably
737276404edcSAsim Jamshed                  * shouldn't be matched, but what about broadcast
737376404edcSAsim Jamshed                  * or multicast packets we received?
737476404edcSAsim Jamshed                  */
737576404edcSAsim Jamshed                 b0 = gen_cmp(OR_LINK, 0, BPF_H, LINUX_SLL_HOST);
737676404edcSAsim Jamshed             }
737776404edcSAsim Jamshed             break;
737876404edcSAsim Jamshed 
737976404edcSAsim Jamshed #ifdef HAVE_NET_PFVAR_H
738076404edcSAsim Jamshed         case DLT_PFLOG:
738176404edcSAsim Jamshed             b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, dir), BPF_B,
738276404edcSAsim Jamshed                          (bpf_int32) ((dir == 0) ? PF_IN : PF_OUT));
738376404edcSAsim Jamshed             break;
738476404edcSAsim Jamshed #endif
738576404edcSAsim Jamshed 
738676404edcSAsim Jamshed         case DLT_PPP_PPPD:
738776404edcSAsim Jamshed             if (dir)
738876404edcSAsim Jamshed             {
738976404edcSAsim Jamshed                 /* match outgoing packets */
739076404edcSAsim Jamshed                 b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_OUT);
739176404edcSAsim Jamshed             }
739276404edcSAsim Jamshed             else
739376404edcSAsim Jamshed             {
739476404edcSAsim Jamshed                 /* match incoming packets */
739576404edcSAsim Jamshed                 b0 = gen_cmp(OR_LINK, 0, BPF_B, PPP_PPPD_IN);
739676404edcSAsim Jamshed             }
739776404edcSAsim Jamshed             break;
739876404edcSAsim Jamshed 
739976404edcSAsim Jamshed         case DLT_JUNIPER_MFR:
740076404edcSAsim Jamshed         case DLT_JUNIPER_MLFR:
740176404edcSAsim Jamshed         case DLT_JUNIPER_MLPPP:
740276404edcSAsim Jamshed         case DLT_JUNIPER_ATM1:
740376404edcSAsim Jamshed         case DLT_JUNIPER_ATM2:
740476404edcSAsim Jamshed         case DLT_JUNIPER_PPPOE:
740576404edcSAsim Jamshed         case DLT_JUNIPER_PPPOE_ATM:
740676404edcSAsim Jamshed         case DLT_JUNIPER_GGSN:
740776404edcSAsim Jamshed         case DLT_JUNIPER_ES:
740876404edcSAsim Jamshed         case DLT_JUNIPER_MONITOR:
740976404edcSAsim Jamshed         case DLT_JUNIPER_SERVICES:
741076404edcSAsim Jamshed         case DLT_JUNIPER_ETHER:
741176404edcSAsim Jamshed         case DLT_JUNIPER_PPP:
741276404edcSAsim Jamshed         case DLT_JUNIPER_FRELAY:
741376404edcSAsim Jamshed         case DLT_JUNIPER_CHDLC:
741476404edcSAsim Jamshed         case DLT_JUNIPER_VP:
741576404edcSAsim Jamshed         case DLT_JUNIPER_ST:
741676404edcSAsim Jamshed         case DLT_JUNIPER_ISM:
741776404edcSAsim Jamshed             /* juniper flags (including direction) are stored
741876404edcSAsim Jamshed              * the byte after the 3-byte magic number */
741976404edcSAsim Jamshed             if (dir)
742076404edcSAsim Jamshed             {
742176404edcSAsim Jamshed                 /* match outgoing packets */
742276404edcSAsim Jamshed                 b0 = gen_mcmp(OR_LINK, 3, BPF_B, 0, 0x01);
742376404edcSAsim Jamshed             }
742476404edcSAsim Jamshed             else
742576404edcSAsim Jamshed             {
742676404edcSAsim Jamshed                 /* match incoming packets */
742776404edcSAsim Jamshed                 b0 = gen_mcmp(OR_LINK, 3, BPF_B, 1, 0x01);
742876404edcSAsim Jamshed             }
742976404edcSAsim Jamshed             break;
743076404edcSAsim Jamshed 
743176404edcSAsim Jamshed         default:
743276404edcSAsim Jamshed             bpf_error("inbound/outbound not supported on linktype %d", linktype);
743376404edcSAsim Jamshed             b0 = NULL;
743476404edcSAsim Jamshed             /* NOTREACHED */
743576404edcSAsim Jamshed     }
743676404edcSAsim Jamshed     return (b0);
743776404edcSAsim Jamshed }
743876404edcSAsim Jamshed 
743976404edcSAsim Jamshed #ifdef HAVE_NET_PFVAR_H
744076404edcSAsim Jamshed /* PF firewall log matched interface */
gen_pf_ifname(const char * ifname)744176404edcSAsim Jamshed struct block *gen_pf_ifname(const char *ifname)
744276404edcSAsim Jamshed {
744376404edcSAsim Jamshed     struct block *b0;
744476404edcSAsim Jamshed     u_int len, off;
744576404edcSAsim Jamshed 
744676404edcSAsim Jamshed     if (linktype != DLT_PFLOG)
744776404edcSAsim Jamshed     {
744876404edcSAsim Jamshed         bpf_error("ifname supported only on PF linktype");
744976404edcSAsim Jamshed         /* NOTREACHED */
745076404edcSAsim Jamshed     }
745176404edcSAsim Jamshed     len = sizeof(((struct pfloghdr *) 0)->ifname);
745276404edcSAsim Jamshed     off = offsetof(struct pfloghdr, ifname);
745376404edcSAsim Jamshed     if (strlen(ifname) >= len)
745476404edcSAsim Jamshed     {
745576404edcSAsim Jamshed         bpf_error("ifname interface names can only be %d characters", len - 1);
745676404edcSAsim Jamshed         /* NOTREACHED */
745776404edcSAsim Jamshed     }
745876404edcSAsim Jamshed     b0 = gen_bcmp(OR_LINK, off, strlen(ifname), (const u_char *) ifname);
745976404edcSAsim Jamshed     return (b0);
746076404edcSAsim Jamshed }
746176404edcSAsim Jamshed 
746276404edcSAsim Jamshed /* PF firewall log ruleset name */
gen_pf_ruleset(char * ruleset)746376404edcSAsim Jamshed struct block *gen_pf_ruleset(char *ruleset)
746476404edcSAsim Jamshed {
746576404edcSAsim Jamshed     struct block *b0;
746676404edcSAsim Jamshed 
746776404edcSAsim Jamshed     if (linktype != DLT_PFLOG)
746876404edcSAsim Jamshed     {
746976404edcSAsim Jamshed         bpf_error("ruleset supported only on PF linktype");
747076404edcSAsim Jamshed         /* NOTREACHED */
747176404edcSAsim Jamshed     }
747276404edcSAsim Jamshed 
747376404edcSAsim Jamshed     if (strlen(ruleset) >= sizeof(((struct pfloghdr *) 0)->ruleset))
747476404edcSAsim Jamshed     {
747576404edcSAsim Jamshed         bpf_error("ruleset names can only be %ld characters",
747676404edcSAsim Jamshed                   (long) (sizeof(((struct pfloghdr *) 0)->ruleset) - 1));
747776404edcSAsim Jamshed         /* NOTREACHED */
747876404edcSAsim Jamshed     }
747976404edcSAsim Jamshed 
748076404edcSAsim Jamshed     b0 = gen_bcmp(OR_LINK, offsetof(struct pfloghdr, ruleset), strlen(ruleset), (const u_char *) ruleset);
748176404edcSAsim Jamshed     return (b0);
748276404edcSAsim Jamshed }
748376404edcSAsim Jamshed 
748476404edcSAsim Jamshed /* PF firewall log rule number */
gen_pf_rnr(int rnr)748576404edcSAsim Jamshed struct block *gen_pf_rnr(int rnr)
748676404edcSAsim Jamshed {
748776404edcSAsim Jamshed     struct block *b0;
748876404edcSAsim Jamshed 
748976404edcSAsim Jamshed     if (linktype != DLT_PFLOG)
749076404edcSAsim Jamshed     {
749176404edcSAsim Jamshed         bpf_error("rnr supported only on PF linktype");
749276404edcSAsim Jamshed         /* NOTREACHED */
749376404edcSAsim Jamshed     }
749476404edcSAsim Jamshed 
749576404edcSAsim Jamshed     b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, rulenr), BPF_W, (bpf_int32) rnr);
749676404edcSAsim Jamshed     return (b0);
749776404edcSAsim Jamshed }
749876404edcSAsim Jamshed 
749976404edcSAsim Jamshed /* PF firewall log sub-rule number */
gen_pf_srnr(int srnr)750076404edcSAsim Jamshed struct block *gen_pf_srnr(int srnr)
750176404edcSAsim Jamshed {
750276404edcSAsim Jamshed     struct block *b0;
750376404edcSAsim Jamshed 
750476404edcSAsim Jamshed     if (linktype != DLT_PFLOG)
750576404edcSAsim Jamshed     {
750676404edcSAsim Jamshed         bpf_error("srnr supported only on PF linktype");
750776404edcSAsim Jamshed         /* NOTREACHED */
750876404edcSAsim Jamshed     }
750976404edcSAsim Jamshed 
751076404edcSAsim Jamshed     b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, subrulenr), BPF_W, (bpf_int32) srnr);
751176404edcSAsim Jamshed     return (b0);
751276404edcSAsim Jamshed }
751376404edcSAsim Jamshed 
751476404edcSAsim Jamshed /* PF firewall log reason code */
gen_pf_reason(int reason)751576404edcSAsim Jamshed struct block *gen_pf_reason(int reason)
751676404edcSAsim Jamshed {
751776404edcSAsim Jamshed     struct block *b0;
751876404edcSAsim Jamshed 
751976404edcSAsim Jamshed     if (linktype != DLT_PFLOG)
752076404edcSAsim Jamshed     {
752176404edcSAsim Jamshed         bpf_error("reason supported only on PF linktype");
752276404edcSAsim Jamshed         /* NOTREACHED */
752376404edcSAsim Jamshed     }
752476404edcSAsim Jamshed 
752576404edcSAsim Jamshed     b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, reason), BPF_B, (bpf_int32) reason);
752676404edcSAsim Jamshed     return (b0);
752776404edcSAsim Jamshed }
752876404edcSAsim Jamshed 
752976404edcSAsim Jamshed /* PF firewall log action */
gen_pf_action(int action)753076404edcSAsim Jamshed struct block *gen_pf_action(int action)
753176404edcSAsim Jamshed {
753276404edcSAsim Jamshed     struct block *b0;
753376404edcSAsim Jamshed 
753476404edcSAsim Jamshed     if (linktype != DLT_PFLOG)
753576404edcSAsim Jamshed     {
753676404edcSAsim Jamshed         bpf_error("action supported only on PF linktype");
753776404edcSAsim Jamshed         /* NOTREACHED */
753876404edcSAsim Jamshed     }
753976404edcSAsim Jamshed 
754076404edcSAsim Jamshed     b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, action), BPF_B, (bpf_int32) action);
754176404edcSAsim Jamshed     return (b0);
754276404edcSAsim Jamshed }
754376404edcSAsim Jamshed #else /* !HAVE_NET_PFVAR_H */
gen_pf_ifname(const char * ifname)754476404edcSAsim Jamshed struct block *gen_pf_ifname(const char *ifname)
754576404edcSAsim Jamshed {
754676404edcSAsim Jamshed     bpf_error("libpcap was compiled without pf support");
754776404edcSAsim Jamshed     /* NOTREACHED */
754876404edcSAsim Jamshed     return (NULL);
754976404edcSAsim Jamshed }
755076404edcSAsim Jamshed 
gen_pf_ruleset(char * ruleset)755176404edcSAsim Jamshed struct block *gen_pf_ruleset(char *ruleset)
755276404edcSAsim Jamshed {
755376404edcSAsim Jamshed     bpf_error("libpcap was compiled on a machine without pf support");
755476404edcSAsim Jamshed     /* NOTREACHED */
755576404edcSAsim Jamshed     return (NULL);
755676404edcSAsim Jamshed }
755776404edcSAsim Jamshed 
gen_pf_rnr(int rnr)755876404edcSAsim Jamshed struct block *gen_pf_rnr(int rnr)
755976404edcSAsim Jamshed {
756076404edcSAsim Jamshed     bpf_error("libpcap was compiled on a machine without pf support");
756176404edcSAsim Jamshed     /* NOTREACHED */
756276404edcSAsim Jamshed     return (NULL);
756376404edcSAsim Jamshed }
756476404edcSAsim Jamshed 
gen_pf_srnr(int srnr)756576404edcSAsim Jamshed struct block *gen_pf_srnr(int srnr)
756676404edcSAsim Jamshed {
756776404edcSAsim Jamshed     bpf_error("libpcap was compiled on a machine without pf support");
756876404edcSAsim Jamshed     /* NOTREACHED */
756976404edcSAsim Jamshed     return (NULL);
757076404edcSAsim Jamshed }
757176404edcSAsim Jamshed 
gen_pf_reason(int reason)757276404edcSAsim Jamshed struct block *gen_pf_reason(int reason)
757376404edcSAsim Jamshed {
757476404edcSAsim Jamshed     bpf_error("libpcap was compiled on a machine without pf support");
757576404edcSAsim Jamshed     /* NOTREACHED */
757676404edcSAsim Jamshed     return (NULL);
757776404edcSAsim Jamshed }
757876404edcSAsim Jamshed 
gen_pf_action(int action)757976404edcSAsim Jamshed struct block *gen_pf_action(int action)
758076404edcSAsim Jamshed {
758176404edcSAsim Jamshed     bpf_error("libpcap was compiled on a machine without pf support");
758276404edcSAsim Jamshed     /* NOTREACHED */
758376404edcSAsim Jamshed     return (NULL);
758476404edcSAsim Jamshed }
758576404edcSAsim Jamshed #endif /* HAVE_NET_PFVAR_H */
758676404edcSAsim Jamshed 
758776404edcSAsim Jamshed /* IEEE 802.11 wireless header */
gen_p80211_type(int type,int mask)758876404edcSAsim Jamshed struct block *gen_p80211_type(int type, int mask)
758976404edcSAsim Jamshed {
759076404edcSAsim Jamshed     struct block *b0;
759176404edcSAsim Jamshed 
759276404edcSAsim Jamshed     switch (linktype)
759376404edcSAsim Jamshed     {
759476404edcSAsim Jamshed 
759576404edcSAsim Jamshed         case DLT_IEEE802_11:
759676404edcSAsim Jamshed         case DLT_PRISM_HEADER:
759776404edcSAsim Jamshed         case DLT_IEEE802_11_RADIO_AVS:
759876404edcSAsim Jamshed         case DLT_IEEE802_11_RADIO:
759976404edcSAsim Jamshed             b0 = gen_mcmp(OR_LINK, 0, BPF_B, (bpf_int32) type, (bpf_int32) mask);
760076404edcSAsim Jamshed             break;
760176404edcSAsim Jamshed 
760276404edcSAsim Jamshed         default:
760376404edcSAsim Jamshed             bpf_error("802.11 link-layer types supported only on 802.11");
760476404edcSAsim Jamshed             /* NOTREACHED */
760576404edcSAsim Jamshed     }
760676404edcSAsim Jamshed 
760776404edcSAsim Jamshed     return (b0);
760876404edcSAsim Jamshed }
760976404edcSAsim Jamshed 
gen_p80211_fcdir(int fcdir)761076404edcSAsim Jamshed struct block *gen_p80211_fcdir(int fcdir)
761176404edcSAsim Jamshed {
761276404edcSAsim Jamshed     struct block *b0;
761376404edcSAsim Jamshed 
761476404edcSAsim Jamshed     switch (linktype)
761576404edcSAsim Jamshed     {
761676404edcSAsim Jamshed 
761776404edcSAsim Jamshed         case DLT_IEEE802_11:
761876404edcSAsim Jamshed         case DLT_PRISM_HEADER:
761976404edcSAsim Jamshed         case DLT_IEEE802_11_RADIO_AVS:
762076404edcSAsim Jamshed         case DLT_IEEE802_11_RADIO:
762176404edcSAsim Jamshed             break;
762276404edcSAsim Jamshed 
762376404edcSAsim Jamshed         default:
762476404edcSAsim Jamshed             bpf_error("frame direction supported only with 802.11 headers");
762576404edcSAsim Jamshed             /* NOTREACHED */
762676404edcSAsim Jamshed     }
762776404edcSAsim Jamshed 
762876404edcSAsim Jamshed     b0 = gen_mcmp(OR_LINK, 1, BPF_B, (bpf_int32) fcdir, (bpf_u_int32) IEEE80211_FC1_DIR_MASK);
762976404edcSAsim Jamshed 
763076404edcSAsim Jamshed     return (b0);
763176404edcSAsim Jamshed }
763276404edcSAsim Jamshed 
gen_acode(eaddr,q)763376404edcSAsim Jamshed struct block *gen_acode(eaddr, q)
763476404edcSAsim Jamshed      register const u_char *eaddr;
763576404edcSAsim Jamshed      struct qual q;
763676404edcSAsim Jamshed {
763776404edcSAsim Jamshed     switch (linktype)
763876404edcSAsim Jamshed     {
763976404edcSAsim Jamshed 
764076404edcSAsim Jamshed         case DLT_ARCNET:
764176404edcSAsim Jamshed         case DLT_ARCNET_LINUX:
764276404edcSAsim Jamshed             if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK)
764376404edcSAsim Jamshed                 return (gen_ahostop(eaddr, (int) q.dir));
764476404edcSAsim Jamshed             else
764576404edcSAsim Jamshed             {
764676404edcSAsim Jamshed                 bpf_error("ARCnet address used in non-arc expression");
764776404edcSAsim Jamshed                 /* NOTREACHED */
764876404edcSAsim Jamshed             }
764976404edcSAsim Jamshed             break;
765076404edcSAsim Jamshed 
765176404edcSAsim Jamshed         default:
765276404edcSAsim Jamshed             bpf_error("aid supported only on ARCnet");
765376404edcSAsim Jamshed             /* NOTREACHED */
765476404edcSAsim Jamshed     }
765576404edcSAsim Jamshed     bpf_error("ARCnet address used in non-arc expression");
765676404edcSAsim Jamshed     /* NOTREACHED */
765776404edcSAsim Jamshed     return NULL;
765876404edcSAsim Jamshed }
765976404edcSAsim Jamshed 
gen_ahostop(eaddr,dir)766076404edcSAsim Jamshed static struct block *gen_ahostop(eaddr, dir)
766176404edcSAsim Jamshed      register const u_char *eaddr;
766276404edcSAsim Jamshed      register int dir;
766376404edcSAsim Jamshed {
766476404edcSAsim Jamshed     register struct block *b0, *b1;
766576404edcSAsim Jamshed 
766676404edcSAsim Jamshed     switch (dir)
766776404edcSAsim Jamshed     {
766876404edcSAsim Jamshed             /* src comes first, different from Ethernet */
766976404edcSAsim Jamshed         case Q_SRC:
767076404edcSAsim Jamshed             return gen_bcmp(OR_LINK, 0, 1, eaddr);
767176404edcSAsim Jamshed 
767276404edcSAsim Jamshed         case Q_DST:
767376404edcSAsim Jamshed             return gen_bcmp(OR_LINK, 1, 1, eaddr);
767476404edcSAsim Jamshed 
767576404edcSAsim Jamshed         case Q_AND:
767676404edcSAsim Jamshed             b0 = gen_ahostop(eaddr, Q_SRC);
767776404edcSAsim Jamshed             b1 = gen_ahostop(eaddr, Q_DST);
767876404edcSAsim Jamshed             gen_and(b0, b1);
767976404edcSAsim Jamshed             return b1;
768076404edcSAsim Jamshed 
768176404edcSAsim Jamshed         case Q_DEFAULT:
768276404edcSAsim Jamshed         case Q_OR:
768376404edcSAsim Jamshed             b0 = gen_ahostop(eaddr, Q_SRC);
768476404edcSAsim Jamshed             b1 = gen_ahostop(eaddr, Q_DST);
768576404edcSAsim Jamshed             gen_or(b0, b1);
768676404edcSAsim Jamshed             return b1;
768776404edcSAsim Jamshed     }
768876404edcSAsim Jamshed     abort();
768976404edcSAsim Jamshed     /* NOTREACHED */
769076404edcSAsim Jamshed }
769176404edcSAsim Jamshed 
769276404edcSAsim Jamshed /*
769376404edcSAsim Jamshed  * support IEEE 802.1Q VLAN trunk over ethernet
769476404edcSAsim Jamshed  */
gen_vlan(vlan_num)769576404edcSAsim Jamshed struct block *gen_vlan(vlan_num)
769676404edcSAsim Jamshed      int vlan_num;
769776404edcSAsim Jamshed {
769876404edcSAsim Jamshed     struct block *b0, *b1;
769976404edcSAsim Jamshed 
770076404edcSAsim Jamshed     /* can't check for VLAN-encapsulated packets inside MPLS */
770176404edcSAsim Jamshed     if (label_stack_depth > 0)
770276404edcSAsim Jamshed         bpf_error("no VLAN match after MPLS");
770376404edcSAsim Jamshed 
770476404edcSAsim Jamshed     /*
770576404edcSAsim Jamshed      * Check for a VLAN packet, and then change the offsets to point
770676404edcSAsim Jamshed      * to the type and data fields within the VLAN packet.  Just
770776404edcSAsim Jamshed      * increment the offsets, so that we can support a hierarchy, e.g.
770876404edcSAsim Jamshed      * "vlan 300 && vlan 200" to capture VLAN 200 encapsulated within
770976404edcSAsim Jamshed      * VLAN 100.
771076404edcSAsim Jamshed      *
771176404edcSAsim Jamshed      * XXX - this is a bit of a kludge.  If we were to split the
771276404edcSAsim Jamshed      * compiler into a parser that parses an expression and
771376404edcSAsim Jamshed      * generates an expression tree, and a code generator that
771476404edcSAsim Jamshed      * takes an expression tree (which could come from our
771576404edcSAsim Jamshed      * parser or from some other parser) and generates BPF code,
771676404edcSAsim Jamshed      * we could perhaps make the offsets parameters of routines
771776404edcSAsim Jamshed      * and, in the handler for an "AND" node, pass to subnodes
771876404edcSAsim Jamshed      * other than the VLAN node the adjusted offsets.
771976404edcSAsim Jamshed      *
772076404edcSAsim Jamshed      * This would mean that "vlan" would, instead of changing the
772176404edcSAsim Jamshed      * behavior of *all* tests after it, change only the behavior
772276404edcSAsim Jamshed      * of tests ANDed with it.  That would change the documented
772376404edcSAsim Jamshed      * semantics of "vlan", which might break some expressions.
772476404edcSAsim Jamshed      * However, it would mean that "(vlan and ip) or ip" would check
772576404edcSAsim Jamshed      * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
772676404edcSAsim Jamshed      * checking only for VLAN-encapsulated IP, so that could still
772776404edcSAsim Jamshed      * be considered worth doing; it wouldn't break expressions
772876404edcSAsim Jamshed      * that are of the form "vlan and ..." or "vlan N and ...",
772976404edcSAsim Jamshed      * which I suspect are the most common expressions involving
773076404edcSAsim Jamshed      * "vlan".  "vlan or ..." doesn't necessarily do what the user
773176404edcSAsim Jamshed      * would really want, now, as all the "or ..." tests would
773276404edcSAsim Jamshed      * be done assuming a VLAN, even though the "or" could be viewed
773376404edcSAsim Jamshed      * as meaning "or, if this isn't a VLAN packet...".
773476404edcSAsim Jamshed      */
773576404edcSAsim Jamshed     orig_nl = off_nl;
773676404edcSAsim Jamshed 
773776404edcSAsim Jamshed     switch (linktype)
773876404edcSAsim Jamshed     {
773976404edcSAsim Jamshed 
774076404edcSAsim Jamshed         case DLT_EN10MB:
774176404edcSAsim Jamshed             /* check for VLAN */
774276404edcSAsim Jamshed             b0 = gen_cmp(OR_LINK, off_linktype, BPF_H, (bpf_int32) ETHERTYPE_8021Q);
774376404edcSAsim Jamshed 
774476404edcSAsim Jamshed             /* If a specific VLAN is requested, check VLAN id */
774576404edcSAsim Jamshed             if (vlan_num >= 0)
774676404edcSAsim Jamshed             {
774776404edcSAsim Jamshed                 b1 = gen_mcmp(OR_MACPL, 0, BPF_H, (bpf_int32) vlan_num, 0x0fff);
774876404edcSAsim Jamshed                 gen_and(b0, b1);
774976404edcSAsim Jamshed                 b0 = b1;
775076404edcSAsim Jamshed             }
775176404edcSAsim Jamshed 
775276404edcSAsim Jamshed             off_macpl += 4;
775376404edcSAsim Jamshed             off_linktype += 4;
775476404edcSAsim Jamshed             break;
775576404edcSAsim Jamshed 
775676404edcSAsim Jamshed         default:
775776404edcSAsim Jamshed             bpf_error("no VLAN support for data link type %d", linktype);
775876404edcSAsim Jamshed      /*NOTREACHED*/}
775976404edcSAsim Jamshed 
776076404edcSAsim Jamshed     return (b0);
776176404edcSAsim Jamshed }
776276404edcSAsim Jamshed 
776376404edcSAsim Jamshed /*
776476404edcSAsim Jamshed  * support for MPLS
776576404edcSAsim Jamshed  */
gen_mpls(label_num)776676404edcSAsim Jamshed struct block *gen_mpls(label_num)
776776404edcSAsim Jamshed      int label_num;
776876404edcSAsim Jamshed {
776976404edcSAsim Jamshed     struct block *b0, *b1;
777076404edcSAsim Jamshed 
777176404edcSAsim Jamshed     /*
777276404edcSAsim Jamshed      * Change the offsets to point to the type and data fields within
777376404edcSAsim Jamshed      * the MPLS packet.  Just increment the offsets, so that we
777476404edcSAsim Jamshed      * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to
777576404edcSAsim Jamshed      * capture packets with an outer label of 100000 and an inner
777676404edcSAsim Jamshed      * label of 1024.
777776404edcSAsim Jamshed      *
777876404edcSAsim Jamshed      * XXX - this is a bit of a kludge.  See comments in gen_vlan().
777976404edcSAsim Jamshed      */
778076404edcSAsim Jamshed     orig_nl = off_nl;
778176404edcSAsim Jamshed 
778276404edcSAsim Jamshed     if (label_stack_depth > 0)
778376404edcSAsim Jamshed     {
778476404edcSAsim Jamshed         /* just match the bottom-of-stack bit clear */
778576404edcSAsim Jamshed         b0 = gen_mcmp(OR_MACPL, orig_nl - 2, BPF_B, 0, 0x01);
778676404edcSAsim Jamshed     }
778776404edcSAsim Jamshed     else
778876404edcSAsim Jamshed     {
778976404edcSAsim Jamshed         /*
779076404edcSAsim Jamshed          * Indicate that we're checking MPLS-encapsulated headers,
779176404edcSAsim Jamshed          * to make sure higher level code generators don't try to
779276404edcSAsim Jamshed          * match against IP-related protocols such as Q_ARP, Q_RARP
779376404edcSAsim Jamshed          * etc.
779476404edcSAsim Jamshed          */
779576404edcSAsim Jamshed         switch (linktype)
779676404edcSAsim Jamshed         {
779776404edcSAsim Jamshed 
779876404edcSAsim Jamshed             case DLT_C_HDLC:   /* fall through */
779976404edcSAsim Jamshed             case DLT_EN10MB:
780076404edcSAsim Jamshed                 b0 = gen_linktype(ETHERTYPE_MPLS);
780176404edcSAsim Jamshed                 break;
780276404edcSAsim Jamshed 
780376404edcSAsim Jamshed             case DLT_PPP:
780476404edcSAsim Jamshed                 b0 = gen_linktype(PPP_MPLS_UCAST);
780576404edcSAsim Jamshed                 break;
780676404edcSAsim Jamshed 
780776404edcSAsim Jamshed                 /* FIXME add other DLT_s ...
780876404edcSAsim Jamshed                  * for Frame-Relay/and ATM this may get messy due to SNAP headers
780976404edcSAsim Jamshed                  * leave it for now */
781076404edcSAsim Jamshed 
781176404edcSAsim Jamshed             default:
781276404edcSAsim Jamshed                 bpf_error("no MPLS support for data link type %d", linktype);
781376404edcSAsim Jamshed                 b0 = NULL;
781476404edcSAsim Jamshed                  /*NOTREACHED*/ break;
781576404edcSAsim Jamshed         }
781676404edcSAsim Jamshed     }
781776404edcSAsim Jamshed 
781876404edcSAsim Jamshed     /* If a specific MPLS label is requested, check it */
781976404edcSAsim Jamshed     if (label_num >= 0)
782076404edcSAsim Jamshed     {
782176404edcSAsim Jamshed         label_num = label_num << 12;    /* label is shifted 12 bits on the wire */
782276404edcSAsim Jamshed         b1 = gen_mcmp(OR_MACPL, orig_nl, BPF_W, (bpf_int32) label_num, 0xfffff000); /* only compare the first 20 bits */
782376404edcSAsim Jamshed         gen_and(b0, b1);
782476404edcSAsim Jamshed         b0 = b1;
782576404edcSAsim Jamshed     }
782676404edcSAsim Jamshed 
782776404edcSAsim Jamshed     off_nl_nosnap += 4;
782876404edcSAsim Jamshed     off_nl += 4;
782976404edcSAsim Jamshed     label_stack_depth++;
783076404edcSAsim Jamshed     return (b0);
783176404edcSAsim Jamshed }
783276404edcSAsim Jamshed 
783376404edcSAsim Jamshed /*
783476404edcSAsim Jamshed  * Support PPPOE discovery and session.
783576404edcSAsim Jamshed  */
gen_pppoed()783676404edcSAsim Jamshed struct block *gen_pppoed()
783776404edcSAsim Jamshed {
783876404edcSAsim Jamshed     /* check for PPPoE discovery */
783976404edcSAsim Jamshed     return gen_linktype((bpf_int32) ETHERTYPE_PPPOED);
784076404edcSAsim Jamshed }
784176404edcSAsim Jamshed 
gen_pppoes()784276404edcSAsim Jamshed struct block *gen_pppoes()
784376404edcSAsim Jamshed {
784476404edcSAsim Jamshed     struct block *b0;
784576404edcSAsim Jamshed 
784676404edcSAsim Jamshed     /*
784776404edcSAsim Jamshed      * Test against the PPPoE session link-layer type.
784876404edcSAsim Jamshed      */
784976404edcSAsim Jamshed     b0 = gen_linktype((bpf_int32) ETHERTYPE_PPPOES);
785076404edcSAsim Jamshed 
785176404edcSAsim Jamshed     /*
785276404edcSAsim Jamshed      * Change the offsets to point to the type and data fields within
785376404edcSAsim Jamshed      * the PPP packet, and note that this is PPPoE rather than
785476404edcSAsim Jamshed      * raw PPP.
785576404edcSAsim Jamshed      *
785676404edcSAsim Jamshed      * XXX - this is a bit of a kludge.  If we were to split the
785776404edcSAsim Jamshed      * compiler into a parser that parses an expression and
785876404edcSAsim Jamshed      * generates an expression tree, and a code generator that
785976404edcSAsim Jamshed      * takes an expression tree (which could come from our
786076404edcSAsim Jamshed      * parser or from some other parser) and generates BPF code,
786176404edcSAsim Jamshed      * we could perhaps make the offsets parameters of routines
786276404edcSAsim Jamshed      * and, in the handler for an "AND" node, pass to subnodes
786376404edcSAsim Jamshed      * other than the PPPoE node the adjusted offsets.
786476404edcSAsim Jamshed      *
786576404edcSAsim Jamshed      * This would mean that "pppoes" would, instead of changing the
786676404edcSAsim Jamshed      * behavior of *all* tests after it, change only the behavior
786776404edcSAsim Jamshed      * of tests ANDed with it.  That would change the documented
786876404edcSAsim Jamshed      * semantics of "pppoes", which might break some expressions.
786976404edcSAsim Jamshed      * However, it would mean that "(pppoes and ip) or ip" would check
787076404edcSAsim Jamshed      * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
787176404edcSAsim Jamshed      * checking only for VLAN-encapsulated IP, so that could still
787276404edcSAsim Jamshed      * be considered worth doing; it wouldn't break expressions
787376404edcSAsim Jamshed      * that are of the form "pppoes and ..." which I suspect are the
787476404edcSAsim Jamshed      * most common expressions involving "pppoes".  "pppoes or ..."
787576404edcSAsim Jamshed      * doesn't necessarily do what the user would really want, now,
787676404edcSAsim Jamshed      * as all the "or ..." tests would be done assuming PPPoE, even
787776404edcSAsim Jamshed      * though the "or" could be viewed as meaning "or, if this isn't
787876404edcSAsim Jamshed      * a PPPoE packet...".
787976404edcSAsim Jamshed      */
788076404edcSAsim Jamshed     orig_linktype = off_linktype;   /* save original values */
788176404edcSAsim Jamshed     orig_nl = off_nl;
788276404edcSAsim Jamshed     is_pppoes = 1;
788376404edcSAsim Jamshed 
788476404edcSAsim Jamshed     /*
788576404edcSAsim Jamshed      * The "network-layer" protocol is PPPoE, which has a 6-byte
788676404edcSAsim Jamshed      * PPPoE header, followed by a PPP packet.
788776404edcSAsim Jamshed      *
788876404edcSAsim Jamshed      * There is no HDLC encapsulation for the PPP packet (it's
788976404edcSAsim Jamshed      * encapsulated in PPPoES instead), so the link-layer type
789076404edcSAsim Jamshed      * starts at the first byte of the PPP packet.  For PPPoE,
789176404edcSAsim Jamshed      * that offset is relative to the beginning of the total
789276404edcSAsim Jamshed      * link-layer payload, including any 802.2 LLC header, so
789376404edcSAsim Jamshed      * it's 6 bytes past off_nl.
789476404edcSAsim Jamshed      */
789576404edcSAsim Jamshed     off_linktype = off_nl + 6;
789676404edcSAsim Jamshed 
789776404edcSAsim Jamshed     /*
789876404edcSAsim Jamshed      * The network-layer offsets are relative to the beginning
789976404edcSAsim Jamshed      * of the MAC-layer payload; that's past the 6-byte
790076404edcSAsim Jamshed      * PPPoE header and the 2-byte PPP header.
790176404edcSAsim Jamshed      */
790276404edcSAsim Jamshed     off_nl = 6 + 2;
790376404edcSAsim Jamshed     off_nl_nosnap = 6 + 2;
790476404edcSAsim Jamshed 
790576404edcSAsim Jamshed     return b0;
790676404edcSAsim Jamshed }
790776404edcSAsim Jamshed 
gen_atmfield_code(atmfield,jvalue,jtype,reverse)790876404edcSAsim Jamshed struct block *gen_atmfield_code(atmfield, jvalue, jtype, reverse)
790976404edcSAsim Jamshed      int atmfield;
791076404edcSAsim Jamshed      bpf_int32 jvalue;
791176404edcSAsim Jamshed      bpf_u_int32 jtype;
791276404edcSAsim Jamshed      int reverse;
791376404edcSAsim Jamshed {
791476404edcSAsim Jamshed     struct block *b0;
791576404edcSAsim Jamshed 
791676404edcSAsim Jamshed     switch (atmfield)
791776404edcSAsim Jamshed     {
791876404edcSAsim Jamshed 
791976404edcSAsim Jamshed         case A_VPI:
792076404edcSAsim Jamshed             if (!is_atm)
792176404edcSAsim Jamshed                 bpf_error("'vpi' supported only on raw ATM");
792276404edcSAsim Jamshed             if (off_vpi == (u_int) - 1)
792376404edcSAsim Jamshed                 abort();
792476404edcSAsim Jamshed             b0 = gen_ncmp(OR_LINK, off_vpi, BPF_B, 0xffffffff, jtype, reverse, jvalue);
792576404edcSAsim Jamshed             break;
792676404edcSAsim Jamshed 
792776404edcSAsim Jamshed         case A_VCI:
792876404edcSAsim Jamshed             if (!is_atm)
792976404edcSAsim Jamshed                 bpf_error("'vci' supported only on raw ATM");
793076404edcSAsim Jamshed             if (off_vci == (u_int) - 1)
793176404edcSAsim Jamshed                 abort();
793276404edcSAsim Jamshed             b0 = gen_ncmp(OR_LINK, off_vci, BPF_H, 0xffffffff, jtype, reverse, jvalue);
793376404edcSAsim Jamshed             break;
793476404edcSAsim Jamshed 
793576404edcSAsim Jamshed         case A_PROTOTYPE:
793676404edcSAsim Jamshed             if (off_proto == (u_int) - 1)
793776404edcSAsim Jamshed                 abort();        /* XXX - this isn't on FreeBSD */
793876404edcSAsim Jamshed             b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0x0f, jtype, reverse, jvalue);
793976404edcSAsim Jamshed             break;
794076404edcSAsim Jamshed 
794176404edcSAsim Jamshed         case A_MSGTYPE:
794276404edcSAsim Jamshed             if (off_payload == (u_int) - 1)
794376404edcSAsim Jamshed                 abort();
794476404edcSAsim Jamshed             b0 = gen_ncmp(OR_LINK, off_payload + MSG_TYPE_POS, BPF_B, 0xffffffff, jtype, reverse, jvalue);
794576404edcSAsim Jamshed             break;
794676404edcSAsim Jamshed 
794776404edcSAsim Jamshed         case A_CALLREFTYPE:
794876404edcSAsim Jamshed             if (!is_atm)
794976404edcSAsim Jamshed                 bpf_error("'callref' supported only on raw ATM");
795076404edcSAsim Jamshed             if (off_proto == (u_int) - 1)
795176404edcSAsim Jamshed                 abort();
795276404edcSAsim Jamshed             b0 = gen_ncmp(OR_LINK, off_proto, BPF_B, 0xffffffff, jtype, reverse, jvalue);
795376404edcSAsim Jamshed             break;
795476404edcSAsim Jamshed 
795576404edcSAsim Jamshed         default:
795676404edcSAsim Jamshed             abort();
795776404edcSAsim Jamshed     }
795876404edcSAsim Jamshed     return b0;
795976404edcSAsim Jamshed }
796076404edcSAsim Jamshed 
gen_atmtype_abbrev(type)796176404edcSAsim Jamshed struct block *gen_atmtype_abbrev(type)
796276404edcSAsim Jamshed      int type;
796376404edcSAsim Jamshed {
796476404edcSAsim Jamshed     struct block *b0, *b1;
796576404edcSAsim Jamshed 
796676404edcSAsim Jamshed     switch (type)
796776404edcSAsim Jamshed     {
796876404edcSAsim Jamshed 
796976404edcSAsim Jamshed         case A_METAC:
797076404edcSAsim Jamshed             /* Get all packets in Meta signalling Circuit */
797176404edcSAsim Jamshed             if (!is_atm)
797276404edcSAsim Jamshed                 bpf_error("'metac' supported only on raw ATM");
797376404edcSAsim Jamshed             b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
797476404edcSAsim Jamshed             b1 = gen_atmfield_code(A_VCI, 1, BPF_JEQ, 0);
797576404edcSAsim Jamshed             gen_and(b0, b1);
797676404edcSAsim Jamshed             break;
797776404edcSAsim Jamshed 
797876404edcSAsim Jamshed         case A_BCC:
797976404edcSAsim Jamshed             /* Get all packets in Broadcast Circuit */
798076404edcSAsim Jamshed             if (!is_atm)
798176404edcSAsim Jamshed                 bpf_error("'bcc' supported only on raw ATM");
798276404edcSAsim Jamshed             b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
798376404edcSAsim Jamshed             b1 = gen_atmfield_code(A_VCI, 2, BPF_JEQ, 0);
798476404edcSAsim Jamshed             gen_and(b0, b1);
798576404edcSAsim Jamshed             break;
798676404edcSAsim Jamshed 
798776404edcSAsim Jamshed         case A_OAMF4SC:
798876404edcSAsim Jamshed             /* Get all cells in Segment OAM F4 circuit */
798976404edcSAsim Jamshed             if (!is_atm)
799076404edcSAsim Jamshed                 bpf_error("'oam4sc' supported only on raw ATM");
799176404edcSAsim Jamshed             b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
799276404edcSAsim Jamshed             b1 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
799376404edcSAsim Jamshed             gen_and(b0, b1);
799476404edcSAsim Jamshed             break;
799576404edcSAsim Jamshed 
799676404edcSAsim Jamshed         case A_OAMF4EC:
799776404edcSAsim Jamshed             /* Get all cells in End-to-End OAM F4 Circuit */
799876404edcSAsim Jamshed             if (!is_atm)
799976404edcSAsim Jamshed                 bpf_error("'oam4ec' supported only on raw ATM");
800076404edcSAsim Jamshed             b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
800176404edcSAsim Jamshed             b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0);
800276404edcSAsim Jamshed             gen_and(b0, b1);
800376404edcSAsim Jamshed             break;
800476404edcSAsim Jamshed 
800576404edcSAsim Jamshed         case A_SC:
800676404edcSAsim Jamshed             /*  Get all packets in connection Signalling Circuit */
800776404edcSAsim Jamshed             if (!is_atm)
800876404edcSAsim Jamshed                 bpf_error("'sc' supported only on raw ATM");
800976404edcSAsim Jamshed             b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
801076404edcSAsim Jamshed             b1 = gen_atmfield_code(A_VCI, 5, BPF_JEQ, 0);
801176404edcSAsim Jamshed             gen_and(b0, b1);
801276404edcSAsim Jamshed             break;
801376404edcSAsim Jamshed 
801476404edcSAsim Jamshed         case A_ILMIC:
801576404edcSAsim Jamshed             /* Get all packets in ILMI Circuit */
801676404edcSAsim Jamshed             if (!is_atm)
801776404edcSAsim Jamshed                 bpf_error("'ilmic' supported only on raw ATM");
801876404edcSAsim Jamshed             b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
801976404edcSAsim Jamshed             b1 = gen_atmfield_code(A_VCI, 16, BPF_JEQ, 0);
802076404edcSAsim Jamshed             gen_and(b0, b1);
802176404edcSAsim Jamshed             break;
802276404edcSAsim Jamshed 
802376404edcSAsim Jamshed         case A_LANE:
802476404edcSAsim Jamshed             /* Get all LANE packets */
802576404edcSAsim Jamshed             if (!is_atm)
802676404edcSAsim Jamshed                 bpf_error("'lane' supported only on raw ATM");
802776404edcSAsim Jamshed             b1 = gen_atmfield_code(A_PROTOTYPE, PT_LANE, BPF_JEQ, 0);
802876404edcSAsim Jamshed 
802976404edcSAsim Jamshed             /*
803076404edcSAsim Jamshed              * Arrange that all subsequent tests assume LANE
803176404edcSAsim Jamshed              * rather than LLC-encapsulated packets, and set
803276404edcSAsim Jamshed              * the offsets appropriately for LANE-encapsulated
803376404edcSAsim Jamshed              * Ethernet.
803476404edcSAsim Jamshed              *
803576404edcSAsim Jamshed              * "off_mac" is the offset of the Ethernet header,
803676404edcSAsim Jamshed              * which is 2 bytes past the ATM pseudo-header
803776404edcSAsim Jamshed              * (skipping the pseudo-header and 2-byte LE Client
803876404edcSAsim Jamshed              * field).  The other offsets are Ethernet offsets
803976404edcSAsim Jamshed              * relative to "off_mac".
804076404edcSAsim Jamshed              */
804176404edcSAsim Jamshed             is_lane = 1;
804276404edcSAsim Jamshed             off_mac = off_payload + 2;  /* MAC header */
804376404edcSAsim Jamshed             off_linktype = off_mac + 12;
804476404edcSAsim Jamshed             off_macpl = off_mac + 14;   /* Ethernet */
804576404edcSAsim Jamshed             off_nl = 0;         /* Ethernet II */
804676404edcSAsim Jamshed             off_nl_nosnap = 3;  /* 802.3+802.2 */
804776404edcSAsim Jamshed             break;
804876404edcSAsim Jamshed 
804976404edcSAsim Jamshed         case A_LLC:
805076404edcSAsim Jamshed             /* Get all LLC-encapsulated packets */
805176404edcSAsim Jamshed             if (!is_atm)
805276404edcSAsim Jamshed                 bpf_error("'llc' supported only on raw ATM");
805376404edcSAsim Jamshed             b1 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
805476404edcSAsim Jamshed             is_lane = 0;
805576404edcSAsim Jamshed             break;
805676404edcSAsim Jamshed 
805776404edcSAsim Jamshed         default:
805876404edcSAsim Jamshed             abort();
805976404edcSAsim Jamshed     }
806076404edcSAsim Jamshed     return b1;
806176404edcSAsim Jamshed }
806276404edcSAsim Jamshed 
806376404edcSAsim Jamshed /*
806476404edcSAsim Jamshed  * Filtering for MTP2 messages based on li value
806576404edcSAsim Jamshed  * FISU, length is null
806676404edcSAsim Jamshed  * LSSU, length is 1 or 2
806776404edcSAsim Jamshed  * MSU, length is 3 or more
806876404edcSAsim Jamshed  */
gen_mtp2type_abbrev(type)806976404edcSAsim Jamshed struct block *gen_mtp2type_abbrev(type)
807076404edcSAsim Jamshed      int type;
807176404edcSAsim Jamshed {
807276404edcSAsim Jamshed     struct block *b0, *b1;
807376404edcSAsim Jamshed 
807476404edcSAsim Jamshed     switch (type)
807576404edcSAsim Jamshed     {
807676404edcSAsim Jamshed 
807776404edcSAsim Jamshed         case M_FISU:
807876404edcSAsim Jamshed             if ((linktype != DLT_MTP2) && (linktype != DLT_ERF) && (linktype != DLT_MTP2_WITH_PHDR))
807976404edcSAsim Jamshed                 bpf_error("'fisu' supported only on MTP2");
808076404edcSAsim Jamshed             /* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */
808176404edcSAsim Jamshed             b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JEQ, 0, 0);
808276404edcSAsim Jamshed             break;
808376404edcSAsim Jamshed 
808476404edcSAsim Jamshed         case M_LSSU:
808576404edcSAsim Jamshed             if ((linktype != DLT_MTP2) && (linktype != DLT_ERF) && (linktype != DLT_MTP2_WITH_PHDR))
808676404edcSAsim Jamshed                 bpf_error("'lssu' supported only on MTP2");
808776404edcSAsim Jamshed             b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 1, 2);
808876404edcSAsim Jamshed             b1 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 0);
808976404edcSAsim Jamshed             gen_and(b1, b0);
809076404edcSAsim Jamshed             break;
809176404edcSAsim Jamshed 
809276404edcSAsim Jamshed         case M_MSU:
809376404edcSAsim Jamshed             if ((linktype != DLT_MTP2) && (linktype != DLT_ERF) && (linktype != DLT_MTP2_WITH_PHDR))
809476404edcSAsim Jamshed                 bpf_error("'msu' supported only on MTP2");
809576404edcSAsim Jamshed             b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 2);
809676404edcSAsim Jamshed             break;
809776404edcSAsim Jamshed 
809876404edcSAsim Jamshed         default:
809976404edcSAsim Jamshed             abort();
810076404edcSAsim Jamshed     }
810176404edcSAsim Jamshed     return b0;
810276404edcSAsim Jamshed }
810376404edcSAsim Jamshed 
gen_mtp3field_code(mtp3field,jvalue,jtype,reverse)810476404edcSAsim Jamshed struct block *gen_mtp3field_code(mtp3field, jvalue, jtype, reverse)
810576404edcSAsim Jamshed      int mtp3field;
810676404edcSAsim Jamshed      bpf_u_int32 jvalue;
810776404edcSAsim Jamshed      bpf_u_int32 jtype;
810876404edcSAsim Jamshed      int reverse;
810976404edcSAsim Jamshed {
811076404edcSAsim Jamshed     struct block *b0;
811176404edcSAsim Jamshed     bpf_u_int32 val1, val2, val3;
811276404edcSAsim Jamshed 
811376404edcSAsim Jamshed     switch (mtp3field)
811476404edcSAsim Jamshed     {
811576404edcSAsim Jamshed 
811676404edcSAsim Jamshed         case M_SIO:
811776404edcSAsim Jamshed             if (off_sio == (u_int) - 1)
811876404edcSAsim Jamshed                 bpf_error("'sio' supported only on SS7");
811976404edcSAsim Jamshed             /* sio coded on 1 byte so max value 255 */
812076404edcSAsim Jamshed             if (jvalue > 255)
812176404edcSAsim Jamshed                 bpf_error("sio value %u too big; max value = 255", jvalue);
812276404edcSAsim Jamshed             b0 = gen_ncmp(OR_PACKET, off_sio, BPF_B, 0xffffffff, (u_int) jtype, reverse, (u_int) jvalue);
812376404edcSAsim Jamshed             break;
812476404edcSAsim Jamshed 
812576404edcSAsim Jamshed         case M_OPC:
812676404edcSAsim Jamshed             if (off_opc == (u_int) - 1)
812776404edcSAsim Jamshed                 bpf_error("'opc' supported only on SS7");
812876404edcSAsim Jamshed             /* opc coded on 14 bits so max value 16383 */
812976404edcSAsim Jamshed             if (jvalue > 16383)
813076404edcSAsim Jamshed                 bpf_error("opc value %u too big; max value = 16383", jvalue);
813176404edcSAsim Jamshed             /* the following instructions are made to convert jvalue
813276404edcSAsim Jamshed              * to the form used to write opc in an ss7 message*/
813376404edcSAsim Jamshed             val1 = jvalue & 0x00003c00;
813476404edcSAsim Jamshed             val1 = val1 >> 10;
813576404edcSAsim Jamshed             val2 = jvalue & 0x000003fc;
813676404edcSAsim Jamshed             val2 = val2 << 6;
813776404edcSAsim Jamshed             val3 = jvalue & 0x00000003;
813876404edcSAsim Jamshed             val3 = val3 << 22;
813976404edcSAsim Jamshed             jvalue = val1 + val2 + val3;
814076404edcSAsim Jamshed             b0 = gen_ncmp(OR_PACKET, off_opc, BPF_W, 0x00c0ff0f, (u_int) jtype, reverse, (u_int) jvalue);
814176404edcSAsim Jamshed             break;
814276404edcSAsim Jamshed 
814376404edcSAsim Jamshed         case M_DPC:
814476404edcSAsim Jamshed             if (off_dpc == (u_int) - 1)
814576404edcSAsim Jamshed                 bpf_error("'dpc' supported only on SS7");
814676404edcSAsim Jamshed             /* dpc coded on 14 bits so max value 16383 */
814776404edcSAsim Jamshed             if (jvalue > 16383)
814876404edcSAsim Jamshed                 bpf_error("dpc value %u too big; max value = 16383", jvalue);
814976404edcSAsim Jamshed             /* the following instructions are made to convert jvalue
815076404edcSAsim Jamshed              * to the forme used to write dpc in an ss7 message*/
815176404edcSAsim Jamshed             val1 = jvalue & 0x000000ff;
815276404edcSAsim Jamshed             val1 = val1 << 24;
815376404edcSAsim Jamshed             val2 = jvalue & 0x00003f00;
815476404edcSAsim Jamshed             val2 = val2 << 8;
815576404edcSAsim Jamshed             jvalue = val1 + val2;
815676404edcSAsim Jamshed             b0 = gen_ncmp(OR_PACKET, off_dpc, BPF_W, 0xff3f0000, (u_int) jtype, reverse, (u_int) jvalue);
815776404edcSAsim Jamshed             break;
815876404edcSAsim Jamshed 
815976404edcSAsim Jamshed         case M_SLS:
816076404edcSAsim Jamshed             if (off_sls == (u_int) - 1)
816176404edcSAsim Jamshed                 bpf_error("'sls' supported only on SS7");
816276404edcSAsim Jamshed             /* sls coded on 4 bits so max value 15 */
816376404edcSAsim Jamshed             if (jvalue > 15)
816476404edcSAsim Jamshed                 bpf_error("sls value %u too big; max value = 15", jvalue);
816576404edcSAsim Jamshed             /* the following instruction is made to convert jvalue
816676404edcSAsim Jamshed              * to the forme used to write sls in an ss7 message*/
816776404edcSAsim Jamshed             jvalue = jvalue << 4;
816876404edcSAsim Jamshed             b0 = gen_ncmp(OR_PACKET, off_sls, BPF_B, 0xf0, (u_int) jtype, reverse, (u_int) jvalue);
816976404edcSAsim Jamshed             break;
817076404edcSAsim Jamshed 
817176404edcSAsim Jamshed         default:
817276404edcSAsim Jamshed             abort();
817376404edcSAsim Jamshed     }
817476404edcSAsim Jamshed     return b0;
817576404edcSAsim Jamshed }
817676404edcSAsim Jamshed 
gen_msg_abbrev(type)817776404edcSAsim Jamshed static struct block *gen_msg_abbrev(type)
817876404edcSAsim Jamshed      int type;
817976404edcSAsim Jamshed {
818076404edcSAsim Jamshed     struct block *b1;
818176404edcSAsim Jamshed 
818276404edcSAsim Jamshed     /*
818376404edcSAsim Jamshed      * Q.2931 signalling protocol messages for handling virtual circuits
818476404edcSAsim Jamshed      * establishment and teardown
818576404edcSAsim Jamshed      */
818676404edcSAsim Jamshed     switch (type)
818776404edcSAsim Jamshed     {
818876404edcSAsim Jamshed 
818976404edcSAsim Jamshed         case A_SETUP:
819076404edcSAsim Jamshed             b1 = gen_atmfield_code(A_MSGTYPE, SETUP, BPF_JEQ, 0);
819176404edcSAsim Jamshed             break;
819276404edcSAsim Jamshed 
819376404edcSAsim Jamshed         case A_CALLPROCEED:
819476404edcSAsim Jamshed             b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
819576404edcSAsim Jamshed             break;
819676404edcSAsim Jamshed 
819776404edcSAsim Jamshed         case A_CONNECT:
819876404edcSAsim Jamshed             b1 = gen_atmfield_code(A_MSGTYPE, CONNECT, BPF_JEQ, 0);
819976404edcSAsim Jamshed             break;
820076404edcSAsim Jamshed 
820176404edcSAsim Jamshed         case A_CONNECTACK:
820276404edcSAsim Jamshed             b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
820376404edcSAsim Jamshed             break;
820476404edcSAsim Jamshed 
820576404edcSAsim Jamshed         case A_RELEASE:
820676404edcSAsim Jamshed             b1 = gen_atmfield_code(A_MSGTYPE, RELEASE, BPF_JEQ, 0);
820776404edcSAsim Jamshed             break;
820876404edcSAsim Jamshed 
820976404edcSAsim Jamshed         case A_RELEASE_DONE:
821076404edcSAsim Jamshed             b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
821176404edcSAsim Jamshed             break;
821276404edcSAsim Jamshed 
821376404edcSAsim Jamshed         default:
821476404edcSAsim Jamshed             abort();
821576404edcSAsim Jamshed     }
821676404edcSAsim Jamshed     return b1;
821776404edcSAsim Jamshed }
821876404edcSAsim Jamshed 
gen_atmmulti_abbrev(type)821976404edcSAsim Jamshed struct block *gen_atmmulti_abbrev(type)
822076404edcSAsim Jamshed      int type;
822176404edcSAsim Jamshed {
822276404edcSAsim Jamshed     struct block *b0, *b1;
822376404edcSAsim Jamshed 
822476404edcSAsim Jamshed     switch (type)
822576404edcSAsim Jamshed     {
822676404edcSAsim Jamshed 
822776404edcSAsim Jamshed         case A_OAM:
822876404edcSAsim Jamshed             if (!is_atm)
822976404edcSAsim Jamshed                 bpf_error("'oam' supported only on raw ATM");
823076404edcSAsim Jamshed             b1 = gen_atmmulti_abbrev(A_OAMF4);
823176404edcSAsim Jamshed             break;
823276404edcSAsim Jamshed 
823376404edcSAsim Jamshed         case A_OAMF4:
823476404edcSAsim Jamshed             if (!is_atm)
823576404edcSAsim Jamshed                 bpf_error("'oamf4' supported only on raw ATM");
823676404edcSAsim Jamshed             /* OAM F4 type */
823776404edcSAsim Jamshed             b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
823876404edcSAsim Jamshed             b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0);
823976404edcSAsim Jamshed             gen_or(b0, b1);
824076404edcSAsim Jamshed             b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
824176404edcSAsim Jamshed             gen_and(b0, b1);
824276404edcSAsim Jamshed             break;
824376404edcSAsim Jamshed 
824476404edcSAsim Jamshed         case A_CONNECTMSG:
824576404edcSAsim Jamshed             /*
824676404edcSAsim Jamshed              * Get Q.2931 signalling messages for switched
824776404edcSAsim Jamshed              * virtual connection
824876404edcSAsim Jamshed              */
824976404edcSAsim Jamshed             if (!is_atm)
825076404edcSAsim Jamshed                 bpf_error("'connectmsg' supported only on raw ATM");
825176404edcSAsim Jamshed             b0 = gen_msg_abbrev(A_SETUP);
825276404edcSAsim Jamshed             b1 = gen_msg_abbrev(A_CALLPROCEED);
825376404edcSAsim Jamshed             gen_or(b0, b1);
825476404edcSAsim Jamshed             b0 = gen_msg_abbrev(A_CONNECT);
825576404edcSAsim Jamshed             gen_or(b0, b1);
825676404edcSAsim Jamshed             b0 = gen_msg_abbrev(A_CONNECTACK);
825776404edcSAsim Jamshed             gen_or(b0, b1);
825876404edcSAsim Jamshed             b0 = gen_msg_abbrev(A_RELEASE);
825976404edcSAsim Jamshed             gen_or(b0, b1);
826076404edcSAsim Jamshed             b0 = gen_msg_abbrev(A_RELEASE_DONE);
826176404edcSAsim Jamshed             gen_or(b0, b1);
826276404edcSAsim Jamshed             b0 = gen_atmtype_abbrev(A_SC);
826376404edcSAsim Jamshed             gen_and(b0, b1);
826476404edcSAsim Jamshed             break;
826576404edcSAsim Jamshed 
826676404edcSAsim Jamshed         case A_METACONNECT:
826776404edcSAsim Jamshed             if (!is_atm)
826876404edcSAsim Jamshed                 bpf_error("'metaconnect' supported only on raw ATM");
826976404edcSAsim Jamshed             b0 = gen_msg_abbrev(A_SETUP);
827076404edcSAsim Jamshed             b1 = gen_msg_abbrev(A_CALLPROCEED);
827176404edcSAsim Jamshed             gen_or(b0, b1);
827276404edcSAsim Jamshed             b0 = gen_msg_abbrev(A_CONNECT);
827376404edcSAsim Jamshed             gen_or(b0, b1);
827476404edcSAsim Jamshed             b0 = gen_msg_abbrev(A_RELEASE);
827576404edcSAsim Jamshed             gen_or(b0, b1);
827676404edcSAsim Jamshed             b0 = gen_msg_abbrev(A_RELEASE_DONE);
827776404edcSAsim Jamshed             gen_or(b0, b1);
827876404edcSAsim Jamshed             b0 = gen_atmtype_abbrev(A_METAC);
827976404edcSAsim Jamshed             gen_and(b0, b1);
828076404edcSAsim Jamshed             break;
828176404edcSAsim Jamshed 
828276404edcSAsim Jamshed         default:
828376404edcSAsim Jamshed             abort();
828476404edcSAsim Jamshed     }
828576404edcSAsim Jamshed     return b1;
828676404edcSAsim Jamshed }
8287