summaryrefslogtreecommitdiff
path: root/grammar.y
diff options
context:
space:
mode:
Diffstat (limited to 'grammar.y')
-rw-r--r--grammar.y697
1 files changed, 697 insertions, 0 deletions
diff --git a/grammar.y b/grammar.y
new file mode 100644
index 0000000..f2ba28b
--- /dev/null
+++ b/grammar.y
@@ -0,0 +1,697 @@
+%{
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+#ifndef lint
+static const char rcsid[] _U_ =
+ "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.101 2007-11-18 02:03:52 guy Exp $ (LBL)";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef WIN32
+#include <pcap-stdinc.h>
+#else /* WIN32 */
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif /* WIN32 */
+
+#include <stdlib.h>
+
+#ifndef WIN32
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif /* WIN32 */
+
+#include <stdio.h>
+
+#include "pcap-int.h"
+
+#include "gencode.h"
+#ifdef HAVE_NET_PFVAR_H
+#include <net/if.h>
+#include <net/pfvar.h>
+#include <net/if_pflog.h>
+#endif
+#include "ieee80211.h"
+#include <pcap/namedb.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#define QSET(q, p, d, a) (q).proto = (p),\
+ (q).dir = (d),\
+ (q).addr = (a)
+
+struct tok {
+ int v; /* value */
+ const char *s; /* string */
+};
+
+static const struct tok ieee80211_types[] = {
+ { IEEE80211_FC0_TYPE_DATA, "data" },
+ { IEEE80211_FC0_TYPE_MGT, "mgt" },
+ { IEEE80211_FC0_TYPE_MGT, "management" },
+ { IEEE80211_FC0_TYPE_CTL, "ctl" },
+ { IEEE80211_FC0_TYPE_CTL, "control" },
+ { 0, NULL }
+};
+static const struct tok ieee80211_mgt_subtypes[] = {
+ { IEEE80211_FC0_SUBTYPE_ASSOC_REQ, "assocreq" },
+ { IEEE80211_FC0_SUBTYPE_ASSOC_REQ, "assoc-req" },
+ { IEEE80211_FC0_SUBTYPE_ASSOC_RESP, "assocresp" },
+ { IEEE80211_FC0_SUBTYPE_ASSOC_RESP, "assoc-resp" },
+ { IEEE80211_FC0_SUBTYPE_REASSOC_REQ, "reassocreq" },
+ { IEEE80211_FC0_SUBTYPE_REASSOC_REQ, "reassoc-req" },
+ { IEEE80211_FC0_SUBTYPE_REASSOC_RESP, "reassocresp" },
+ { IEEE80211_FC0_SUBTYPE_REASSOC_RESP, "reassoc-resp" },
+ { IEEE80211_FC0_SUBTYPE_PROBE_REQ, "probereq" },
+ { IEEE80211_FC0_SUBTYPE_PROBE_REQ, "probe-req" },
+ { IEEE80211_FC0_SUBTYPE_PROBE_RESP, "proberesp" },
+ { IEEE80211_FC0_SUBTYPE_PROBE_RESP, "probe-resp" },
+ { IEEE80211_FC0_SUBTYPE_BEACON, "beacon" },
+ { IEEE80211_FC0_SUBTYPE_ATIM, "atim" },
+ { IEEE80211_FC0_SUBTYPE_DISASSOC, "disassoc" },
+ { IEEE80211_FC0_SUBTYPE_DISASSOC, "disassociation" },
+ { IEEE80211_FC0_SUBTYPE_AUTH, "auth" },
+ { IEEE80211_FC0_SUBTYPE_AUTH, "authentication" },
+ { IEEE80211_FC0_SUBTYPE_DEAUTH, "deauth" },
+ { IEEE80211_FC0_SUBTYPE_DEAUTH, "deauthentication" },
+ { 0, NULL }
+};
+static const struct tok ieee80211_ctl_subtypes[] = {
+ { IEEE80211_FC0_SUBTYPE_PS_POLL, "ps-poll" },
+ { IEEE80211_FC0_SUBTYPE_RTS, "rts" },
+ { IEEE80211_FC0_SUBTYPE_CTS, "cts" },
+ { IEEE80211_FC0_SUBTYPE_ACK, "ack" },
+ { IEEE80211_FC0_SUBTYPE_CF_END, "cf-end" },
+ { IEEE80211_FC0_SUBTYPE_CF_END_ACK, "cf-end-ack" },
+ { 0, NULL }
+};
+static const struct tok ieee80211_data_subtypes[] = {
+ { IEEE80211_FC0_SUBTYPE_DATA, "data" },
+ { IEEE80211_FC0_SUBTYPE_CF_ACK, "data-cf-ack" },
+ { IEEE80211_FC0_SUBTYPE_CF_POLL, "data-cf-poll" },
+ { IEEE80211_FC0_SUBTYPE_CF_ACPL, "data-cf-ack-poll" },
+ { IEEE80211_FC0_SUBTYPE_NODATA, "null" },
+ { IEEE80211_FC0_SUBTYPE_NODATA_CF_ACK, "cf-ack" },
+ { IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL, "cf-poll" },
+ { IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL, "cf-ack-poll" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_DATA, "qos-data" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_ACK, "qos-data-cf-ack" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_POLL, "qos-data-cf-poll" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_ACPL, "qos-data-cf-ack-poll" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA, "qos" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL, "qos-cf-poll" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL, "qos-cf-ack-poll" },
+ { 0, NULL }
+};
+struct type2tok {
+ int type;
+ const struct tok *tok;
+};
+static const struct type2tok ieee80211_type_subtypes[] = {
+ { IEEE80211_FC0_TYPE_MGT, ieee80211_mgt_subtypes },
+ { IEEE80211_FC0_TYPE_CTL, ieee80211_ctl_subtypes },
+ { IEEE80211_FC0_TYPE_DATA, ieee80211_data_subtypes },
+ { 0, NULL }
+};
+
+static int
+str2tok(const char *str, const struct tok *toks)
+{
+ int i;
+
+ for (i = 0; toks[i].s != NULL; i++) {
+ if (pcap_strcasecmp(toks[i].s, str) == 0)
+ return (toks[i].v);
+ }
+ return (-1);
+}
+
+int n_errors = 0;
+
+static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
+
+static void
+yyerror(const char *msg)
+{
+ ++n_errors;
+ bpf_error("%s", msg);
+ /* NOTREACHED */
+}
+
+#ifndef YYBISON
+int yyparse(void);
+
+int
+pcap_parse()
+{
+ return (yyparse());
+}
+#endif
+
+#ifdef HAVE_NET_PFVAR_H
+static int
+pfreason_to_num(const char *reason)
+{
+ const char *reasons[] = PFRES_NAMES;
+ int i;
+
+ for (i = 0; reasons[i]; i++) {
+ if (pcap_strcasecmp(reason, reasons[i]) == 0)
+ return (i);
+ }
+ bpf_error("unknown PF reason");
+ /*NOTREACHED*/
+}
+
+static int
+pfaction_to_num(const char *action)
+{
+ if (pcap_strcasecmp(action, "pass") == 0 ||
+ pcap_strcasecmp(action, "accept") == 0)
+ return (PF_PASS);
+ else if (pcap_strcasecmp(action, "drop") == 0 ||
+ pcap_strcasecmp(action, "block") == 0)
+ return (PF_DROP);
+#if HAVE_PF_NAT_THROUGH_PF_NORDR
+ else if (pcap_strcasecmp(action, "rdr") == 0)
+ return (PF_RDR);
+ else if (pcap_strcasecmp(action, "nat") == 0)
+ return (PF_NAT);
+ else if (pcap_strcasecmp(action, "binat") == 0)
+ return (PF_BINAT);
+ else if (pcap_strcasecmp(action, "nordr") == 0)
+ return (PF_NORDR);
+#endif
+ else {
+ bpf_error("unknown PF action");
+ /*NOTREACHED*/
+ }
+}
+#else /* !HAVE_NET_PFVAR_H */
+static int
+pfreason_to_num(const char *reason)
+{
+ bpf_error("libpcap was compiled on a machine without pf support");
+ /*NOTREACHED*/
+
+ /* this is to make the VC compiler happy */
+ return -1;
+}
+
+static int
+pfaction_to_num(const char *action)
+{
+ bpf_error("libpcap was compiled on a machine without pf support");
+ /*NOTREACHED*/
+
+ /* this is to make the VC compiler happy */
+ return -1;
+}
+#endif /* HAVE_NET_PFVAR_H */
+%}
+
+%union {
+ int i;
+ bpf_u_int32 h;
+ u_char *e;
+ char *s;
+ struct stmt *stmt;
+ struct arth *a;
+ struct {
+ struct qual q;
+ int atmfieldtype;
+ int mtp3fieldtype;
+ struct block *b;
+ } blk;
+ struct block *rblk;
+}
+
+%type <blk> expr id nid pid term rterm qid
+%type <blk> head
+%type <i> pqual dqual aqual ndaqual
+%type <a> arth narth
+%type <i> byteop pname pnum relop irelop
+%type <blk> and or paren not null prog
+%type <rblk> other pfvar p80211
+%type <i> atmtype atmmultitype
+%type <blk> atmfield
+%type <blk> atmfieldvalue atmvalue atmlistvalue
+%type <i> mtp2type
+%type <blk> mtp3field
+%type <blk> mtp3fieldvalue mtp3value mtp3listvalue
+
+
+%token DST SRC HOST GATEWAY
+%token NET NETMASK PORT PORTRANGE LESS GREATER PROTO PROTOCHAIN CBYTE
+%token ARP RARP IP SCTP TCP UDP ICMP IGMP IGRP PIM VRRP CARP
+%token ATALK AARP DECNET LAT SCA MOPRC MOPDL
+%token TK_BROADCAST TK_MULTICAST
+%token NUM INBOUND OUTBOUND
+%token PF_IFNAME PF_RSET PF_RNR PF_SRNR PF_REASON PF_ACTION
+%token TYPE SUBTYPE DIR ADDR1 ADDR2 ADDR3 ADDR4 RA TA
+%token LINK
+%token GEQ LEQ NEQ
+%token ID EID HID HID6 AID
+%token LSH RSH
+%token LEN
+%token IPV6 ICMPV6 AH ESP
+%token VLAN MPLS
+%token PPPOED PPPOES
+%token ISO ESIS CLNP ISIS L1 L2 IIH LSP SNP CSNP PSNP
+%token STP
+%token IPX
+%token NETBEUI
+%token LANE LLC METAC BCC SC ILMIC OAMF4EC OAMF4SC
+%token OAM OAMF4 CONNECTMSG METACONNECT
+%token VPI VCI
+%token RADIO
+%token FISU LSSU MSU
+%token SIO OPC DPC SLS
+
+%type <s> ID
+%type <e> EID
+%type <e> AID
+%type <s> HID HID6
+%type <i> NUM action reason type subtype type_subtype dir
+
+%left OR AND
+%nonassoc '!'
+%left '|'
+%left '&'
+%left LSH RSH
+%left '+' '-'
+%left '*' '/'
+%nonassoc UMINUS
+%%
+prog: null expr
+{
+ finish_parse($2.b);
+}
+ | null
+ ;
+null: /* null */ { $$.q = qerr; }
+ ;
+expr: term
+ | expr and term { gen_and($1.b, $3.b); $$ = $3; }
+ | expr and id { gen_and($1.b, $3.b); $$ = $3; }
+ | expr or term { gen_or($1.b, $3.b); $$ = $3; }
+ | expr or id { gen_or($1.b, $3.b); $$ = $3; }
+ ;
+and: AND { $$ = $<blk>0; }
+ ;
+or: OR { $$ = $<blk>0; }
+ ;
+id: nid
+ | pnum { $$.b = gen_ncode(NULL, (bpf_u_int32)$1,
+ $$.q = $<blk>0.q); }
+ | paren pid ')' { $$ = $2; }
+ ;
+nid: ID { $$.b = gen_scode($1, $$.q = $<blk>0.q); }
+ | HID '/' NUM { $$.b = gen_mcode($1, NULL, $3,
+ $$.q = $<blk>0.q); }
+ | HID NETMASK HID { $$.b = gen_mcode($1, $3, 0,
+ $$.q = $<blk>0.q); }
+ | HID {
+ /* Decide how to parse HID based on proto */
+ $$.q = $<blk>0.q;
+ if ($$.q.addr == Q_PORT)
+ bpf_error("'port' modifier applied to ip host");
+ else if ($$.q.addr == Q_PORTRANGE)
+ bpf_error("'portrange' modifier applied to ip host");
+ else if ($$.q.addr == Q_PROTO)
+ bpf_error("'proto' modifier applied to ip host");
+ else if ($$.q.addr == Q_PROTOCHAIN)
+ bpf_error("'protochain' modifier applied to ip host");
+ $$.b = gen_ncode($1, 0, $$.q);
+ }
+ | HID6 '/' NUM {
+#ifdef INET6
+ $$.b = gen_mcode6($1, NULL, $3,
+ $$.q = $<blk>0.q);
+#else
+ bpf_error("'ip6addr/prefixlen' not supported "
+ "in this configuration");
+#endif /*INET6*/
+ }
+ | HID6 {
+#ifdef INET6
+ $$.b = gen_mcode6($1, 0, 128,
+ $$.q = $<blk>0.q);
+#else
+ bpf_error("'ip6addr' not supported "
+ "in this configuration");
+#endif /*INET6*/
+ }
+ | EID {
+ $$.b = gen_ecode($1, $$.q = $<blk>0.q);
+ /*
+ * $1 was allocated by "pcap_ether_aton()",
+ * so we must free it now that we're done
+ * with it.
+ */
+ free($1);
+ }
+ | AID {
+ $$.b = gen_acode($1, $$.q = $<blk>0.q);
+ /*
+ * $1 was allocated by "pcap_ether_aton()",
+ * so we must free it now that we're done
+ * with it.
+ */
+ free($1);
+ }
+ | not id { gen_not($2.b); $$ = $2; }
+ ;
+not: '!' { $$ = $<blk>0; }
+ ;
+paren: '(' { $$ = $<blk>0; }
+ ;
+pid: nid
+ | qid and id { gen_and($1.b, $3.b); $$ = $3; }
+ | qid or id { gen_or($1.b, $3.b); $$ = $3; }
+ ;
+qid: pnum { $$.b = gen_ncode(NULL, (bpf_u_int32)$1,
+ $$.q = $<blk>0.q); }
+ | pid
+ ;
+term: rterm
+ | not term { gen_not($2.b); $$ = $2; }
+ ;
+head: pqual dqual aqual { QSET($$.q, $1, $2, $3); }
+ | pqual dqual { QSET($$.q, $1, $2, Q_DEFAULT); }
+ | pqual aqual { QSET($$.q, $1, Q_DEFAULT, $2); }
+ | pqual PROTO { QSET($$.q, $1, Q_DEFAULT, Q_PROTO); }
+ | pqual PROTOCHAIN { QSET($$.q, $1, Q_DEFAULT, Q_PROTOCHAIN); }
+ | pqual ndaqual { QSET($$.q, $1, Q_DEFAULT, $2); }
+ ;
+rterm: head id { $$ = $2; }
+ | paren expr ')' { $$.b = $2.b; $$.q = $1.q; }
+ | pname { $$.b = gen_proto_abbrev($1); $$.q = qerr; }
+ | arth relop arth { $$.b = gen_relation($2, $1, $3, 0);
+ $$.q = qerr; }
+ | arth irelop arth { $$.b = gen_relation($2, $1, $3, 1);
+ $$.q = qerr; }
+ | other { $$.b = $1; $$.q = qerr; }
+ | atmtype { $$.b = gen_atmtype_abbrev($1); $$.q = qerr; }
+ | atmmultitype { $$.b = gen_atmmulti_abbrev($1); $$.q = qerr; }
+ | atmfield atmvalue { $$.b = $2.b; $$.q = qerr; }
+ | mtp2type { $$.b = gen_mtp2type_abbrev($1); $$.q = qerr; }
+ | mtp3field mtp3value { $$.b = $2.b; $$.q = qerr; }
+ ;
+/* protocol level qualifiers */
+pqual: pname
+ | { $$ = Q_DEFAULT; }
+ ;
+/* 'direction' qualifiers */
+dqual: SRC { $$ = Q_SRC; }
+ | DST { $$ = Q_DST; }
+ | SRC OR DST { $$ = Q_OR; }
+ | DST OR SRC { $$ = Q_OR; }
+ | SRC AND DST { $$ = Q_AND; }
+ | DST AND SRC { $$ = Q_AND; }
+ | ADDR1 { $$ = Q_ADDR1; }
+ | ADDR2 { $$ = Q_ADDR2; }
+ | ADDR3 { $$ = Q_ADDR3; }
+ | ADDR4 { $$ = Q_ADDR4; }
+ | RA { $$ = Q_RA; }
+ | TA { $$ = Q_TA; }
+ ;
+/* address type qualifiers */
+aqual: HOST { $$ = Q_HOST; }
+ | NET { $$ = Q_NET; }
+ | PORT { $$ = Q_PORT; }
+ | PORTRANGE { $$ = Q_PORTRANGE; }
+ ;
+/* non-directional address type qualifiers */
+ndaqual: GATEWAY { $$ = Q_GATEWAY; }
+ ;
+pname: LINK { $$ = Q_LINK; }
+ | IP { $$ = Q_IP; }
+ | ARP { $$ = Q_ARP; }
+ | RARP { $$ = Q_RARP; }
+ | SCTP { $$ = Q_SCTP; }
+ | TCP { $$ = Q_TCP; }
+ | UDP { $$ = Q_UDP; }
+ | ICMP { $$ = Q_ICMP; }
+ | IGMP { $$ = Q_IGMP; }
+ | IGRP { $$ = Q_IGRP; }
+ | PIM { $$ = Q_PIM; }
+ | VRRP { $$ = Q_VRRP; }
+ | CARP { $$ = Q_CARP; }
+ | ATALK { $$ = Q_ATALK; }
+ | AARP { $$ = Q_AARP; }
+ | DECNET { $$ = Q_DECNET; }
+ | LAT { $$ = Q_LAT; }
+ | SCA { $$ = Q_SCA; }
+ | MOPDL { $$ = Q_MOPDL; }
+ | MOPRC { $$ = Q_MOPRC; }
+ | IPV6 { $$ = Q_IPV6; }
+ | ICMPV6 { $$ = Q_ICMPV6; }
+ | AH { $$ = Q_AH; }
+ | ESP { $$ = Q_ESP; }
+ | ISO { $$ = Q_ISO; }
+ | ESIS { $$ = Q_ESIS; }
+ | ISIS { $$ = Q_ISIS; }
+ | L1 { $$ = Q_ISIS_L1; }
+ | L2 { $$ = Q_ISIS_L2; }
+ | IIH { $$ = Q_ISIS_IIH; }
+ | LSP { $$ = Q_ISIS_LSP; }
+ | SNP { $$ = Q_ISIS_SNP; }
+ | PSNP { $$ = Q_ISIS_PSNP; }
+ | CSNP { $$ = Q_ISIS_CSNP; }
+ | CLNP { $$ = Q_CLNP; }
+ | STP { $$ = Q_STP; }
+ | IPX { $$ = Q_IPX; }
+ | NETBEUI { $$ = Q_NETBEUI; }
+ | RADIO { $$ = Q_RADIO; }
+ ;
+other: pqual TK_BROADCAST { $$ = gen_broadcast($1); }
+ | pqual TK_MULTICAST { $$ = gen_multicast($1); }
+ | LESS NUM { $$ = gen_less($2); }
+ | GREATER NUM { $$ = gen_greater($2); }
+ | CBYTE NUM byteop NUM { $$ = gen_byteop($3, $2, $4); }
+ | INBOUND { $$ = gen_inbound(0); }
+ | OUTBOUND { $$ = gen_inbound(1); }
+ | VLAN pnum { $$ = gen_vlan($2); }
+ | VLAN { $$ = gen_vlan(-1); }
+ | MPLS pnum { $$ = gen_mpls($2); }
+ | MPLS { $$ = gen_mpls(-1); }
+ | PPPOED { $$ = gen_pppoed(); }
+ | PPPOES { $$ = gen_pppoes(); }
+ | pfvar { $$ = $1; }
+ | pqual p80211 { $$ = $2; }
+ ;
+
+pfvar: PF_IFNAME ID { $$ = gen_pf_ifname($2); }
+ | PF_RSET ID { $$ = gen_pf_ruleset($2); }
+ | PF_RNR NUM { $$ = gen_pf_rnr($2); }
+ | PF_SRNR NUM { $$ = gen_pf_srnr($2); }
+ | PF_REASON reason { $$ = gen_pf_reason($2); }
+ | PF_ACTION action { $$ = gen_pf_action($2); }
+ ;
+
+p80211: TYPE type SUBTYPE subtype
+ { $$ = gen_p80211_type($2 | $4,
+ IEEE80211_FC0_TYPE_MASK |
+ IEEE80211_FC0_SUBTYPE_MASK);
+ }
+ | TYPE type { $$ = gen_p80211_type($2,
+ IEEE80211_FC0_TYPE_MASK);
+ }
+ | SUBTYPE type_subtype { $$ = gen_p80211_type($2,
+ IEEE80211_FC0_TYPE_MASK |
+ IEEE80211_FC0_SUBTYPE_MASK);
+ }
+ | DIR dir { $$ = gen_p80211_fcdir($2); }
+ ;
+
+type: NUM
+ | ID { $$ = str2tok($1, ieee80211_types);
+ if ($$ == -1)
+ bpf_error("unknown 802.11 type name");
+ }
+ ;
+
+subtype: NUM
+ | ID { const struct tok *types = NULL;
+ int i;
+ for (i = 0;; i++) {
+ if (ieee80211_type_subtypes[i].tok == NULL) {
+ /* Ran out of types */
+ bpf_error("unknown 802.11 type");
+ break;
+ }
+ if ($<i>-1 == ieee80211_type_subtypes[i].type) {
+ types = ieee80211_type_subtypes[i].tok;
+ break;
+ }
+ }
+
+ $$ = str2tok($1, types);
+ if ($$ == -1)
+ bpf_error("unknown 802.11 subtype name");
+ }
+ ;
+
+type_subtype: ID { int i;
+ for (i = 0;; i++) {
+ if (ieee80211_type_subtypes[i].tok == NULL) {
+ /* Ran out of types */
+ bpf_error("unknown 802.11 type name");
+ break;
+ }
+ $$ = str2tok($1, ieee80211_type_subtypes[i].tok);
+ if ($$ != -1) {
+ $$ |= ieee80211_type_subtypes[i].type;
+ break;
+ }
+ }
+ }
+ ;
+
+dir: NUM
+ | ID { if (pcap_strcasecmp($1, "nods") == 0)
+ $$ = IEEE80211_FC1_DIR_NODS;
+ else if (pcap_strcasecmp($1, "tods") == 0)
+ $$ = IEEE80211_FC1_DIR_TODS;
+ else if (pcap_strcasecmp($1, "fromds") == 0)
+ $$ = IEEE80211_FC1_DIR_FROMDS;
+ else if (pcap_strcasecmp($1, "dstods") == 0)
+ $$ = IEEE80211_FC1_DIR_DSTODS;
+ else
+ bpf_error("unknown 802.11 direction");
+ }
+ ;
+
+reason: NUM { $$ = $1; }
+ | ID { $$ = pfreason_to_num($1); }
+ ;
+
+action: ID { $$ = pfaction_to_num($1); }
+ ;
+
+relop: '>' { $$ = BPF_JGT; }
+ | GEQ { $$ = BPF_JGE; }
+ | '=' { $$ = BPF_JEQ; }
+ ;
+irelop: LEQ { $$ = BPF_JGT; }
+ | '<' { $$ = BPF_JGE; }
+ | NEQ { $$ = BPF_JEQ; }
+ ;
+arth: pnum { $$ = gen_loadi($1); }
+ | narth
+ ;
+narth: pname '[' arth ']' { $$ = gen_load($1, $3, 1); }
+ | pname '[' arth ':' NUM ']' { $$ = gen_load($1, $3, $5); }
+ | arth '+' arth { $$ = gen_arth(BPF_ADD, $1, $3); }
+ | arth '-' arth { $$ = gen_arth(BPF_SUB, $1, $3); }
+ | arth '*' arth { $$ = gen_arth(BPF_MUL, $1, $3); }
+ | arth '/' arth { $$ = gen_arth(BPF_DIV, $1, $3); }
+ | arth '&' arth { $$ = gen_arth(BPF_AND, $1, $3); }
+ | arth '|' arth { $$ = gen_arth(BPF_OR, $1, $3); }
+ | arth LSH arth { $$ = gen_arth(BPF_LSH, $1, $3); }
+ | arth RSH arth { $$ = gen_arth(BPF_RSH, $1, $3); }
+ | '-' arth %prec UMINUS { $$ = gen_neg($2); }
+ | paren narth ')' { $$ = $2; }
+ | LEN { $$ = gen_loadlen(); }
+ ;
+byteop: '&' { $$ = '&'; }
+ | '|' { $$ = '|'; }
+ | '<' { $$ = '<'; }
+ | '>' { $$ = '>'; }
+ | '=' { $$ = '='; }
+ ;
+pnum: NUM
+ | paren pnum ')' { $$ = $2; }
+ ;
+atmtype: LANE { $$ = A_LANE; }
+ | LLC { $$ = A_LLC; }
+ | METAC { $$ = A_METAC; }
+ | BCC { $$ = A_BCC; }
+ | OAMF4EC { $$ = A_OAMF4EC; }
+ | OAMF4SC { $$ = A_OAMF4SC; }
+ | SC { $$ = A_SC; }
+ | ILMIC { $$ = A_ILMIC; }
+ ;
+atmmultitype: OAM { $$ = A_OAM; }
+ | OAMF4 { $$ = A_OAMF4; }
+ | CONNECTMSG { $$ = A_CONNECTMSG; }
+ | METACONNECT { $$ = A_METACONNECT; }
+ ;
+ /* ATM field types quantifier */
+atmfield: VPI { $$.atmfieldtype = A_VPI; }
+ | VCI { $$.atmfieldtype = A_VCI; }
+ ;
+atmvalue: atmfieldvalue
+ | relop NUM { $$.b = gen_atmfield_code($<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 0); }
+ | irelop NUM { $$.b = gen_atmfield_code($<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 1); }
+ | paren atmlistvalue ')' { $$.b = $2.b; $$.q = qerr; }
+ ;
+atmfieldvalue: NUM {
+ $$.atmfieldtype = $<blk>0.atmfieldtype;
+ if ($$.atmfieldtype == A_VPI ||
+ $$.atmfieldtype == A_VCI)
+ $$.b = gen_atmfield_code($$.atmfieldtype, (bpf_int32) $1, BPF_JEQ, 0);
+ }
+ ;
+atmlistvalue: atmfieldvalue
+ | atmlistvalue or atmfieldvalue { gen_or($1.b, $3.b); $$ = $3; }
+ ;
+ /* MTP2 types quantifier */
+mtp2type: FISU { $$ = M_FISU; }
+ | LSSU { $$ = M_LSSU; }
+ | MSU { $$ = M_MSU; }
+ ;
+ /* MTP3 field types quantifier */
+mtp3field: SIO { $$.mtp3fieldtype = M_SIO; }
+ | OPC { $$.mtp3fieldtype = M_OPC; }
+ | DPC { $$.mtp3fieldtype = M_DPC; }
+ | SLS { $$.mtp3fieldtype = M_SLS; }
+ ;
+mtp3value: mtp3fieldvalue
+ | relop NUM { $$.b = gen_mtp3field_code($<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 0); }
+ | irelop NUM { $$.b = gen_mtp3field_code($<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 1); }
+ | paren mtp3listvalue ')' { $$.b = $2.b; $$.q = qerr; }
+ ;
+mtp3fieldvalue: NUM {
+ $$.mtp3fieldtype = $<blk>0.mtp3fieldtype;
+ if ($$.mtp3fieldtype == M_SIO ||
+ $$.mtp3fieldtype == M_OPC ||
+ $$.mtp3fieldtype == M_DPC ||
+ $$.mtp3fieldtype == M_SLS )
+ $$.b = gen_mtp3field_code($$.mtp3fieldtype, (u_int) $1, BPF_JEQ, 0);
+ }
+ ;
+mtp3listvalue: mtp3fieldvalue
+ | mtp3listvalue or mtp3fieldvalue { gen_or($1.b, $3.b); $$ = $3; }
+ ;
+%%