1 %{ 2 /* $OpenBSD: grammar.y,v 1.22 2020/08/03 03:40:02 dlg Exp $ */ 3 4 /* 5 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that: (1) source code distributions 10 * retain the above copyright notice and this paragraph in its entirety, (2) 11 * distributions including binary code include the above copyright notice and 12 * this paragraph in its entirety in the documentation or other materials 13 * provided with the distribution, and (3) all advertising materials mentioning 14 * features or use of this software display the following acknowledgement: 15 * ``This product includes software developed by the University of California, 16 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 17 * the University nor the names of its contributors may be used to endorse 18 * or promote products derived from this software without specific prior 19 * written permission. 20 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 21 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 23 * 24 */ 25 26 #include <sys/types.h> 27 #include <sys/time.h> 28 #include <sys/socket.h> 29 30 struct mbuf; 31 struct rtentry; 32 33 #include <net/if.h> 34 35 #include <netinet/in.h> 36 #include <netinet/if_ether.h> 37 38 #include <net/pfvar.h> 39 40 #include <net80211/ieee80211.h> 41 42 #include <stdio.h> 43 #include <string.h> 44 45 #include "pcap-int.h" 46 47 #include "gencode.h" 48 #include <pcap-namedb.h> 49 50 #ifdef HAVE_OS_PROTO_H 51 #include "os-proto.h" 52 #endif 53 54 #define QSET(q, p, d, a) (q).proto = (p),\ 55 (q).dir = (d),\ 56 (q).addr = (a) 57 58 int n_errors = 0; 59 60 static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF }; 61 62 static void 63 yyerror(char *msg) 64 { 65 ++n_errors; 66 bpf_error("%s", msg); 67 /* NOTREACHED */ 68 } 69 70 #ifndef YYBISON 71 int yyparse(void); 72 73 int 74 pcap_parse() 75 { 76 return (yyparse()); 77 } 78 #endif 79 80 %} 81 82 %union { 83 int i; 84 bpf_u_int32 h; 85 u_char *e; 86 char *s; 87 struct stmt *stmt; 88 struct arth *a; 89 struct { 90 struct qual q; 91 struct block *b; 92 } blk; 93 struct block *rblk; 94 } 95 96 %type <blk> expr id nid pid term rterm qid 97 %type <blk> head 98 %type <i> pqual dqual aqual ndaqual 99 %type <a> arth narth 100 %type <i> byteop pname pnum relop irelop 101 %type <blk> and or paren not null prog 102 %type <rblk> other pfvar p80211 103 104 %token DST SRC HOST GATEWAY 105 %token NET MASK PORT LESS GREATER PROTO PROTOCHAIN BYTE 106 %token ARP RARP IP TCP UDP ICMP IGMP IGRP PIM 107 %token ATALK DECNET LAT SCA MOPRC MOPDL STP 108 %token TK_BROADCAST TK_MULTICAST 109 %token NUM INBOUND OUTBOUND 110 %token PF_IFNAME PF_RSET PF_RNR PF_SRNR PF_REASON PF_ACTION 111 %token TYPE SUBTYPE DIR ADDR1 ADDR2 ADDR3 ADDR4 112 %token LINK 113 %token GEQ LEQ NEQ 114 %token ID EID HID HID6 115 %token LSH RSH 116 %token LEN RND SAMPLE 117 %token IPV6 ICMPV6 AH ESP 118 %token VLAN MPLS 119 120 %type <s> ID 121 %type <e> EID 122 %type <s> HID HID6 123 %type <i> NUM action reason type subtype dir 124 125 %left OR AND 126 %nonassoc '!' 127 %left '|' 128 %left '&' 129 %left LSH RSH 130 %left '+' '-' 131 %left '*' '/' 132 %nonassoc UMINUS 133 %% 134 prog: null expr 135 { 136 finish_parse($2.b); 137 } 138 | null 139 ; 140 null: /* null */ { $$.q = qerr; } 141 ; 142 expr: term 143 | expr and term { gen_and($1.b, $3.b); $$ = $3; } 144 | expr and id { gen_and($1.b, $3.b); $$ = $3; } 145 | expr or term { gen_or($1.b, $3.b); $$ = $3; } 146 | expr or id { gen_or($1.b, $3.b); $$ = $3; } 147 ; 148 and: AND { $$ = $<blk>0; } 149 ; 150 or: OR { $$ = $<blk>0; } 151 ; 152 id: nid 153 | pnum { $$.b = gen_ncode(NULL, (bpf_u_int32)$1, 154 $$.q = $<blk>0.q); } 155 | paren pid ')' { $$ = $2; } 156 ; 157 nid: ID { $$.b = gen_scode($1, $$.q = $<blk>0.q); } 158 | HID '/' NUM { $$.b = gen_mcode($1, NULL, $3, 159 $$.q = $<blk>0.q); } 160 | HID MASK HID { $$.b = gen_mcode($1, $3, 0, 161 $$.q = $<blk>0.q); } 162 | HID { 163 /* Decide how to parse HID based on proto */ 164 $$.q = $<blk>0.q; 165 switch ($$.q.proto) { 166 case Q_DECNET: 167 $$.b = gen_ncode($1, 0, $$.q); 168 break; 169 default: 170 $$.b = gen_ncode($1, 0, $$.q); 171 break; 172 } 173 } 174 | HID6 '/' NUM { 175 #ifdef INET6 176 $$.b = gen_mcode6($1, NULL, $3, 177 $$.q = $<blk>0.q); 178 #else 179 bpf_error("'ip6addr/prefixlen' not supported " 180 "in this configuration"); 181 #endif /*INET6*/ 182 } 183 | HID6 { 184 #ifdef INET6 185 $$.b = gen_mcode6($1, 0, 128, 186 $$.q = $<blk>0.q); 187 #else 188 bpf_error("'ip6addr' not supported " 189 "in this configuration"); 190 #endif /*INET6*/ 191 } 192 | EID { $$.b = gen_ecode($1, $$.q = $<blk>0.q); } 193 | not id { gen_not($2.b); $$ = $2; } 194 ; 195 not: '!' { $$ = $<blk>0; } 196 ; 197 paren: '(' { $$ = $<blk>0; } 198 ; 199 pid: nid 200 | qid and id { gen_and($1.b, $3.b); $$ = $3; } 201 | qid or id { gen_or($1.b, $3.b); $$ = $3; } 202 ; 203 qid: pnum { $$.b = gen_ncode(NULL, (bpf_u_int32)$1, 204 $$.q = $<blk>0.q); } 205 | pid 206 ; 207 term: rterm 208 | not term { gen_not($2.b); $$ = $2; } 209 ; 210 head: pqual dqual aqual { QSET($$.q, $1, $2, $3); } 211 | pqual dqual { QSET($$.q, $1, $2, Q_DEFAULT); } 212 | pqual aqual { QSET($$.q, $1, Q_DEFAULT, $2); } 213 | pqual PROTO { QSET($$.q, $1, Q_DEFAULT, Q_PROTO); } 214 | pqual PROTOCHAIN { QSET($$.q, $1, Q_DEFAULT, Q_PROTOCHAIN); } 215 | pqual ndaqual { QSET($$.q, $1, Q_DEFAULT, $2); } 216 ; 217 rterm: head id { $$ = $2; } 218 | paren expr ')' { $$.b = $2.b; $$.q = $1.q; } 219 | pname { $$.b = gen_proto_abbrev($1); $$.q = qerr; } 220 | arth relop arth { $$.b = gen_relation($2, $1, $3, 0); 221 $$.q = qerr; } 222 | arth irelop arth { $$.b = gen_relation($2, $1, $3, 1); 223 $$.q = qerr; } 224 | other { $$.b = $1; $$.q = qerr; } 225 ; 226 /* protocol level qualifiers */ 227 pqual: pname 228 | { $$ = Q_DEFAULT; } 229 ; 230 /* 'direction' qualifiers */ 231 dqual: SRC { $$ = Q_SRC; } 232 | DST { $$ = Q_DST; } 233 | SRC OR DST { $$ = Q_OR; } 234 | DST OR SRC { $$ = Q_OR; } 235 | SRC AND DST { $$ = Q_AND; } 236 | DST AND SRC { $$ = Q_AND; } 237 | ADDR1 { $$ = Q_ADDR1; } 238 | ADDR2 { $$ = Q_ADDR2; } 239 | ADDR3 { $$ = Q_ADDR3; } 240 | ADDR4 { $$ = Q_ADDR4; } 241 ; 242 243 /* address type qualifiers */ 244 aqual: HOST { $$ = Q_HOST; } 245 | NET { $$ = Q_NET; } 246 | PORT { $$ = Q_PORT; } 247 ; 248 /* non-directional address type qualifiers */ 249 ndaqual: GATEWAY { $$ = Q_GATEWAY; } 250 ; 251 pname: LINK { $$ = Q_LINK; } 252 | IP { $$ = Q_IP; } 253 | ARP { $$ = Q_ARP; } 254 | RARP { $$ = Q_RARP; } 255 | TCP { $$ = Q_TCP; } 256 | UDP { $$ = Q_UDP; } 257 | ICMP { $$ = Q_ICMP; } 258 | IGMP { $$ = Q_IGMP; } 259 | IGRP { $$ = Q_IGRP; } 260 | PIM { $$ = Q_PIM; } 261 | ATALK { $$ = Q_ATALK; } 262 | DECNET { $$ = Q_DECNET; } 263 | LAT { $$ = Q_LAT; } 264 | SCA { $$ = Q_SCA; } 265 | MOPDL { $$ = Q_MOPDL; } 266 | MOPRC { $$ = Q_MOPRC; } 267 | IPV6 { $$ = Q_IPV6; } 268 | ICMPV6 { $$ = Q_ICMPV6; } 269 | AH { $$ = Q_AH; } 270 | ESP { $$ = Q_ESP; } 271 | STP { $$ = Q_STP; } 272 ; 273 other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } 274 | pqual TK_MULTICAST { $$ = gen_multicast($1); } 275 | LESS NUM { $$ = gen_less($2); } 276 | GREATER NUM { $$ = gen_greater($2); } 277 | BYTE NUM byteop NUM { $$ = gen_byteop($3, $2, $4); } 278 | INBOUND { $$ = gen_inbound(0); } 279 | OUTBOUND { $$ = gen_inbound(1); } 280 | VLAN pnum { $$ = gen_vlan($2); } 281 | VLAN { $$ = gen_vlan(-1); } 282 | MPLS pnum { $$ = gen_mpls($2); } 283 | MPLS { $$ = gen_mpls(-1); } 284 | pfvar { $$ = $1; } 285 | pqual p80211 { $$ = $2; } 286 | SAMPLE NUM { $$ = gen_sample($2); } 287 ; 288 289 pfvar: PF_IFNAME ID { $$ = gen_pf_ifname($2); } 290 | PF_RSET ID { $$ = gen_pf_ruleset($2); } 291 | PF_RNR NUM { $$ = gen_pf_rnr($2); } 292 | PF_SRNR NUM { $$ = gen_pf_srnr($2); } 293 | PF_REASON reason { $$ = gen_pf_reason($2); } 294 | PF_ACTION action { $$ = gen_pf_action($2); } 295 ; 296 297 reason: NUM { $$ = $1; } 298 | ID { const char *reasons[] = PFRES_NAMES; 299 int i; 300 for (i = 0; reasons[i]; i++) { 301 if (strcasecmp($1, reasons[i]) == 0) { 302 $$ = i; 303 break; 304 } 305 } 306 if (reasons[i] == NULL) 307 bpf_error("unknown PF reason"); 308 } 309 ; 310 311 action: ID { if (strcasecmp($1, "pass") == 0 || 312 strcasecmp($1, "accept") == 0) 313 $$ = PF_PASS; 314 else if (strcasecmp($1, "drop") == 0 || 315 strcasecmp($1, "block") == 0) 316 $$ = PF_DROP; 317 else if (strcasecmp($1, "match") == 0) 318 $$ = PF_MATCH; 319 else if (strcasecmp($1, "rdr") == 0) 320 $$ = PF_RDR; 321 else if (strcasecmp($1, "nat") == 0) 322 $$ = PF_NAT; 323 else if (strcasecmp($1, "binat") == 0) 324 $$ = PF_BINAT; 325 else if (strcasecmp($1, "scrub") == 0) 326 $$ = PF_SCRUB; 327 else 328 bpf_error("unknown PF action"); 329 } 330 ; 331 332 p80211: TYPE type SUBTYPE subtype 333 { $$ = gen_p80211_type($2 | $4, 334 IEEE80211_FC0_TYPE_MASK | 335 IEEE80211_FC0_SUBTYPE_MASK); 336 } 337 | TYPE type { $$ = gen_p80211_type($2, 338 IEEE80211_FC0_TYPE_MASK); } 339 | SUBTYPE subtype { $$ = gen_p80211_type($2, 340 IEEE80211_FC0_SUBTYPE_MASK); } 341 | DIR dir { $$ = gen_p80211_fcdir($2); } 342 ; 343 344 type: NUM 345 | ID { if (strcasecmp($1, "data") == 0) 346 $$ = IEEE80211_FC0_TYPE_DATA; 347 else if (strcasecmp($1, "mgt") == 0 || 348 strcasecmp($1, "management") == 0) 349 $$ = IEEE80211_FC0_TYPE_MGT; 350 else if (strcasecmp($1, "ctl") == 0 || 351 strcasecmp($1, "control") == 0) 352 $$ = IEEE80211_FC0_TYPE_CTL; 353 else 354 bpf_error("unknown 802.11 type"); 355 } 356 ; 357 358 subtype: NUM 359 | ID { if (strcasecmp($1, "assocreq") == 0) 360 $$ = IEEE80211_FC0_SUBTYPE_ASSOC_REQ; 361 else if (strcasecmp($1, "assocresp") == 0) 362 $$ = IEEE80211_FC0_SUBTYPE_ASSOC_RESP; 363 else if (strcasecmp($1, "reassocreq") == 0) 364 $$ = IEEE80211_FC0_SUBTYPE_REASSOC_REQ; 365 else if (strcasecmp($1, "reassocresp") == 0) 366 $$ = IEEE80211_FC0_SUBTYPE_REASSOC_RESP; 367 else if (strcasecmp($1, "probereq") == 0) 368 $$ = IEEE80211_FC0_SUBTYPE_PROBE_REQ; 369 else if (strcasecmp($1, "proberesp") == 0) 370 $$ = IEEE80211_FC0_SUBTYPE_PROBE_RESP; 371 else if (strcasecmp($1, "beacon") == 0) 372 $$ = IEEE80211_FC0_SUBTYPE_BEACON; 373 else if (strcasecmp($1, "atim") == 0) 374 $$ = IEEE80211_FC0_SUBTYPE_ATIM; 375 else if (strcasecmp($1, "disassoc") == 0 || 376 strcasecmp($1, "disassociation") == 0) 377 $$ = IEEE80211_FC0_SUBTYPE_DISASSOC; 378 else if (strcasecmp($1, "auth") == 0 || 379 strcasecmp($1, "authentication") == 0) 380 $$ = IEEE80211_FC0_SUBTYPE_AUTH; 381 else if (strcasecmp($1, "deauth") == 0 || 382 strcasecmp($1, "deauthentication") == 0) 383 $$ = IEEE80211_FC0_SUBTYPE_DEAUTH; 384 else if (strcasecmp($1, "data") == 0) 385 $$ = IEEE80211_FC0_SUBTYPE_DATA; 386 else 387 bpf_error("unknown 802.11 subtype"); 388 } 389 ; 390 391 dir: NUM 392 | ID { if (strcasecmp($1, "nods") == 0) 393 $$ = IEEE80211_FC1_DIR_NODS; 394 else if (strcasecmp($1, "tods") == 0) 395 $$ = IEEE80211_FC1_DIR_TODS; 396 else if (strcasecmp($1, "fromds") == 0) 397 $$ = IEEE80211_FC1_DIR_FROMDS; 398 else if (strcasecmp($1, "dstods") == 0) 399 $$ = IEEE80211_FC1_DIR_DSTODS; 400 else 401 bpf_error("unknown 802.11 direction"); 402 } 403 ; 404 405 relop: '>' { $$ = BPF_JGT; } 406 | GEQ { $$ = BPF_JGE; } 407 | '=' { $$ = BPF_JEQ; } 408 ; 409 irelop: LEQ { $$ = BPF_JGT; } 410 | '<' { $$ = BPF_JGE; } 411 | NEQ { $$ = BPF_JEQ; } 412 ; 413 arth: pnum { $$ = gen_loadi($1); } 414 | narth 415 ; 416 narth: pname '[' arth ']' { $$ = gen_load($1, $3, 1); } 417 | pname '[' arth ':' NUM ']' { $$ = gen_load($1, $3, $5); } 418 | arth '+' arth { $$ = gen_arth(BPF_ADD, $1, $3); } 419 | arth '-' arth { $$ = gen_arth(BPF_SUB, $1, $3); } 420 | arth '*' arth { $$ = gen_arth(BPF_MUL, $1, $3); } 421 | arth '/' arth { $$ = gen_arth(BPF_DIV, $1, $3); } 422 | arth '&' arth { $$ = gen_arth(BPF_AND, $1, $3); } 423 | arth '|' arth { $$ = gen_arth(BPF_OR, $1, $3); } 424 | arth LSH arth { $$ = gen_arth(BPF_LSH, $1, $3); } 425 | arth RSH arth { $$ = gen_arth(BPF_RSH, $1, $3); } 426 | '-' arth %prec UMINUS { $$ = gen_neg($2); } 427 | paren narth ')' { $$ = $2; } 428 | LEN { $$ = gen_loadlen(); } 429 | RND { $$ = gen_loadrnd(); } 430 ; 431 byteop: '&' { $$ = '&'; } 432 | '|' { $$ = '|'; } 433 | '<' { $$ = '<'; } 434 | '>' { $$ = '>'; } 435 | '=' { $$ = '='; } 436 ; 437 pnum: NUM 438 | paren pnum ')' { $$ = $2; } 439 ; 440 %% 441