class BPF
#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 HFISU HLSSU HMSU token SIO OPC DPC SLS HSIO HOPC HDPC HSLS #type <s> ID #type <e> EID #type <e> AID #type <s> HID HID6 #type <i> NUM action reason type subtype type_subtype dir preclow left OR AND nonassoc '!' left '|' left '&' left LSH RSH left '+' '-' left '*' '/' nonassoc UMINUS prechigh rule 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 { $$.b = gen_mcode6($1, NULL, $3, $$.q = $<blk>0.q); } | HID6 { $$.b = gen_mcode6($1, 0, 128, $$.q = $<blk>0.q); } | 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; } | HFISU { $$ = MH_FISU; } | HLSSU { $$ = MH_LSSU; } | HMSU { $$ = MH_MSU; } ; # MTP3 field types quantifier mtp3field : SIO { $$.mtp3fieldtype = M_SIO; } | OPC { $$.mtp3fieldtype = M_OPC; } | DPC { $$.mtp3fieldtype = M_DPC; } | SLS { $$.mtp3fieldtype = M_SLS; } | HSIO { $$.mtp3fieldtype = MH_SIO; } | HOPC { $$.mtp3fieldtype = MH_OPC; } | HDPC { $$.mtp3fieldtype = MH_DPC; } | HSLS { $$.mtp3fieldtype = MH_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 || $$.mtp3fieldtype == MH_SIO || $$.mtp3fieldtype == MH_OPC || $$.mtp3fieldtype == MH_DPC || $$.mtp3fieldtype == MH_SLS) $$.b = gen_mtp3field_code($$.mtp3fieldtype, (u_int) $1, BPF_JEQ, 0); } ; mtp3listvalue : mtp3fieldvalue | mtp3listvalue or mtp3fieldvalue { gen_or($1.b, $3.b); $$ = $3; } ;
end