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