1 %{ 2 /* $OpenBSD: grammar.y,v 1.19 2009/10/27 23:59:30 deraadt 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 117 %token IPV6 ICMPV6 AH ESP 118 %token VLAN 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 | pfvar { $$ = $1; } 283 | pqual p80211 { $$ = $2; } 284 ; 285 286 pfvar: PF_IFNAME ID { $$ = gen_pf_ifname($2); } 287 | PF_RSET ID { $$ = gen_pf_ruleset($2); } 288 | PF_RNR NUM { $$ = gen_pf_rnr($2); } 289 | PF_SRNR NUM { $$ = gen_pf_srnr($2); } 290 | PF_REASON reason { $$ = gen_pf_reason($2); } 291 | PF_ACTION action { $$ = gen_pf_action($2); } 292 ; 293 294 reason: NUM { $$ = $1; } 295 | ID { const char *reasons[] = PFRES_NAMES; 296 int i; 297 for (i = 0; reasons[i]; i++) { 298 if (strcasecmp($1, reasons[i]) == 0) { 299 $$ = i; 300 break; 301 } 302 } 303 if (reasons[i] == NULL) 304 bpf_error("unknown PF reason"); 305 } 306 ; 307 308 action: ID { if (strcasecmp($1, "pass") == 0 || 309 strcasecmp($1, "accept") == 0) 310 $$ = PF_PASS; 311 else if (strcasecmp($1, "drop") == 0 || 312 strcasecmp($1, "block") == 0) 313 $$ = PF_DROP; 314 else if (strcasecmp($1, "match") == 0) 315 $$ = PF_MATCH; 316 else if (strcasecmp($1, "rdr") == 0) 317 $$ = PF_RDR; 318 else if (strcasecmp($1, "nat") == 0) 319 $$ = PF_NAT; 320 else if (strcasecmp($1, "binat") == 0) 321 $$ = PF_BINAT; 322 else if (strcasecmp($1, "scrub") == 0) 323 $$ = PF_SCRUB; 324 else 325 bpf_error("unknown PF action"); 326 } 327 ; 328 329 p80211: TYPE type SUBTYPE subtype 330 { $$ = gen_p80211_type($2 | $4, 331 IEEE80211_FC0_TYPE_MASK | 332 IEEE80211_FC0_SUBTYPE_MASK); 333 } 334 | TYPE type { $$ = gen_p80211_type($2, 335 IEEE80211_FC0_TYPE_MASK); } 336 | SUBTYPE subtype { $$ = gen_p80211_type($2, 337 IEEE80211_FC0_SUBTYPE_MASK); } 338 | DIR dir { $$ = gen_p80211_fcdir($2); } 339 ; 340 341 type: NUM 342 | ID { if (strcasecmp($1, "data") == 0) 343 $$ = IEEE80211_FC0_TYPE_DATA; 344 else if (strcasecmp($1, "mgt") == 0 || 345 strcasecmp($1, "management") == 0) 346 $$ = IEEE80211_FC0_TYPE_MGT; 347 else if (strcasecmp($1, "ctl") == 0 || 348 strcasecmp($1, "control") == 0) 349 $$ = IEEE80211_FC0_TYPE_CTL; 350 else 351 bpf_error("unknown 802.11 type"); 352 } 353 ; 354 355 subtype: NUM 356 | ID { if (strcasecmp($1, "assocreq") == 0) 357 $$ = IEEE80211_FC0_SUBTYPE_ASSOC_REQ; 358 else if (strcasecmp($1, "assocresp") == 0) 359 $$ = IEEE80211_FC0_SUBTYPE_ASSOC_RESP; 360 else if (strcasecmp($1, "reassocreq") == 0) 361 $$ = IEEE80211_FC0_SUBTYPE_REASSOC_REQ; 362 else if (strcasecmp($1, "reassocresp") == 0) 363 $$ = IEEE80211_FC0_SUBTYPE_REASSOC_RESP; 364 else if (strcasecmp($1, "probereq") == 0) 365 $$ = IEEE80211_FC0_SUBTYPE_PROBE_REQ; 366 else if (strcasecmp($1, "proberesp") == 0) 367 $$ = IEEE80211_FC0_SUBTYPE_PROBE_RESP; 368 else if (strcasecmp($1, "beacon") == 0) 369 $$ = IEEE80211_FC0_SUBTYPE_BEACON; 370 else if (strcasecmp($1, "atim") == 0) 371 $$ = IEEE80211_FC0_SUBTYPE_ATIM; 372 else if (strcasecmp($1, "disassoc") == 0 || 373 strcasecmp($1, "disassociation") == 0) 374 $$ = IEEE80211_FC0_SUBTYPE_DISASSOC; 375 else if (strcasecmp($1, "auth") == 0 || 376 strcasecmp($1, "authentication") == 0) 377 $$ = IEEE80211_FC0_SUBTYPE_AUTH; 378 else if (strcasecmp($1, "deauth") == 0 || 379 strcasecmp($1, "deauthentication") == 0) 380 $$ = IEEE80211_FC0_SUBTYPE_DEAUTH; 381 else if (strcasecmp($1, "data") == 0) 382 $$ = IEEE80211_FC0_SUBTYPE_DATA; 383 else 384 bpf_error("unknown 802.11 subtype"); 385 } 386 ; 387 388 dir: NUM 389 | ID { if (strcasecmp($1, "nods") == 0) 390 $$ = IEEE80211_FC1_DIR_NODS; 391 else if (strcasecmp($1, "tods") == 0) 392 $$ = IEEE80211_FC1_DIR_TODS; 393 else if (strcasecmp($1, "fromds") == 0) 394 $$ = IEEE80211_FC1_DIR_FROMDS; 395 else if (strcasecmp($1, "dstods") == 0) 396 $$ = IEEE80211_FC1_DIR_DSTODS; 397 else 398 bpf_error("unknown 802.11 direction"); 399 } 400 ; 401 402 relop: '>' { $$ = BPF_JGT; } 403 | GEQ { $$ = BPF_JGE; } 404 | '=' { $$ = BPF_JEQ; } 405 ; 406 irelop: LEQ { $$ = BPF_JGT; } 407 | '<' { $$ = BPF_JGE; } 408 | NEQ { $$ = BPF_JEQ; } 409 ; 410 arth: pnum { $$ = gen_loadi($1); } 411 | narth 412 ; 413 narth: pname '[' arth ']' { $$ = gen_load($1, $3, 1); } 414 | pname '[' arth ':' NUM ']' { $$ = gen_load($1, $3, $5); } 415 | arth '+' arth { $$ = gen_arth(BPF_ADD, $1, $3); } 416 | arth '-' arth { $$ = gen_arth(BPF_SUB, $1, $3); } 417 | arth '*' arth { $$ = gen_arth(BPF_MUL, $1, $3); } 418 | arth '/' arth { $$ = gen_arth(BPF_DIV, $1, $3); } 419 | arth '&' arth { $$ = gen_arth(BPF_AND, $1, $3); } 420 | arth '|' arth { $$ = gen_arth(BPF_OR, $1, $3); } 421 | arth LSH arth { $$ = gen_arth(BPF_LSH, $1, $3); } 422 | arth RSH arth { $$ = gen_arth(BPF_RSH, $1, $3); } 423 | '-' arth %prec UMINUS { $$ = gen_neg($2); } 424 | paren narth ')' { $$ = $2; } 425 | LEN { $$ = gen_loadlen(); } 426 ; 427 byteop: '&' { $$ = '&'; } 428 | '|' { $$ = '|'; } 429 | '<' { $$ = '<'; } 430 | '>' { $$ = '>'; } 431 | '=' { $$ = '='; } 432 ; 433 pnum: NUM 434 | paren pnum ')' { $$ = $2; } 435 ; 436 %% 437