1 %{
2 /* $OpenBSD: grammar.y,v 1.24 2024/04/08 02:51:14 jsg 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 #include <net/if.h>
31
32 #include <netinet/in.h>
33 #include <netinet/if_ether.h>
34
35 #include <net/pfvar.h>
36
37 #include <net80211/ieee80211.h>
38
39 #include <stdio.h>
40 #include <string.h>
41
42 #include "pcap-int.h"
43
44 #include "gencode.h"
45 #include <pcap-namedb.h>
46
47 #ifdef HAVE_OS_PROTO_H
48 #include "os-proto.h"
49 #endif
50
51 #define QSET(q, p, d, a) (q).proto = (p),\
52 (q).dir = (d),\
53 (q).addr = (a)
54
55 int n_errors = 0;
56
57 static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
58
59 static void
yyerror(char * msg)60 yyerror(char *msg)
61 {
62 ++n_errors;
63 bpf_error("%s", msg);
64 /* NOTREACHED */
65 }
66
67 #ifndef YYBISON
68 int yyparse(void);
69
70 int
pcap_parse(void)71 pcap_parse(void)
72 {
73 return (yyparse());
74 }
75 #endif
76
77 %}
78
79 %union {
80 int i;
81 bpf_u_int32 h;
82 u_char *e;
83 char *s;
84 struct stmt *stmt;
85 struct arth *a;
86 struct {
87 struct qual q;
88 struct block *b;
89 } blk;
90 struct block *rblk;
91 }
92
93 %type <blk> expr id nid pid term rterm qid
94 %type <blk> head
95 %type <i> pqual dqual aqual ndaqual
96 %type <a> arth narth
97 %type <i> byteop pname pnum relop irelop
98 %type <blk> and or paren not null prog
99 %type <rblk> other pfvar p80211
100
101 %token DST SRC HOST GATEWAY
102 %token NET MASK PORT LESS GREATER PROTO PROTOCHAIN BYTE
103 %token ARP RARP IP TCP UDP ICMP IGMP IGRP PIM
104 %token ATALK DECNET LAT SCA MOPRC MOPDL STP
105 %token TK_BROADCAST TK_MULTICAST
106 %token NUM INBOUND OUTBOUND
107 %token PF_IFNAME PF_RSET PF_RNR PF_SRNR PF_REASON PF_ACTION
108 %token TYPE SUBTYPE DIR ADDR1 ADDR2 ADDR3 ADDR4
109 %token LINK
110 %token GEQ LEQ NEQ
111 %token ID EID HID HID6
112 %token LSH RSH
113 %token LEN RND SAMPLE
114 %token IPV6 ICMPV6 AH ESP
115 %token VLAN MPLS
116
117 %type <s> ID
118 %type <e> EID
119 %type <s> HID HID6
120 %type <i> NUM action reason type subtype dir
121
122 %left OR AND
123 %nonassoc '!'
124 %left '|'
125 %left '&'
126 %left LSH RSH
127 %left '+' '-'
128 %left '*' '/'
129 %nonassoc UMINUS
130 %%
131 prog: null expr
132 {
133 finish_parse($2.b);
134 }
135 | null
136 ;
137 null: /* null */ { $$.q = qerr; }
138 ;
139 expr: term
140 | expr and term { gen_and($1.b, $3.b); $$ = $3; }
141 | expr and id { gen_and($1.b, $3.b); $$ = $3; }
142 | expr or term { gen_or($1.b, $3.b); $$ = $3; }
143 | expr or id { gen_or($1.b, $3.b); $$ = $3; }
144 ;
145 and: AND { $$ = $<blk>0; }
146 ;
147 or: OR { $$ = $<blk>0; }
148 ;
149 id: nid
150 | pnum { $$.b = gen_ncode(NULL, (bpf_u_int32)$1,
151 $$.q = $<blk>0.q); }
152 | paren pid ')' { $$ = $2; }
153 ;
154 nid: ID { $$.b = gen_scode($1, $$.q = $<blk>0.q); }
155 | HID '/' NUM { $$.b = gen_mcode($1, NULL, $3,
156 $$.q = $<blk>0.q); }
157 | HID MASK HID { $$.b = gen_mcode($1, $3, 0,
158 $$.q = $<blk>0.q); }
159 | HID {
160 /* Decide how to parse HID based on proto */
161 $$.q = $<blk>0.q;
162 switch ($$.q.proto) {
163 case Q_DECNET:
164 $$.b = gen_ncode($1, 0, $$.q);
165 break;
166 default:
167 $$.b = gen_ncode($1, 0, $$.q);
168 break;
169 }
170 }
171 | HID6 '/' NUM {
172 #ifdef INET6
173 $$.b = gen_mcode6($1, NULL, $3,
174 $$.q = $<blk>0.q);
175 #else
176 bpf_error("'ip6addr/prefixlen' not supported "
177 "in this configuration");
178 #endif /*INET6*/
179 }
180 | HID6 {
181 #ifdef INET6
182 $$.b = gen_mcode6($1, 0, 128,
183 $$.q = $<blk>0.q);
184 #else
185 bpf_error("'ip6addr' not supported "
186 "in this configuration");
187 #endif /*INET6*/
188 }
189 | EID { $$.b = gen_ecode($1, $$.q = $<blk>0.q); }
190 | not id { gen_not($2.b); $$ = $2; }
191 ;
192 not: '!' { $$ = $<blk>0; }
193 ;
194 paren: '(' { $$ = $<blk>0; }
195 ;
196 pid: nid
197 | qid and id { gen_and($1.b, $3.b); $$ = $3; }
198 | qid or id { gen_or($1.b, $3.b); $$ = $3; }
199 ;
200 qid: pnum { $$.b = gen_ncode(NULL, (bpf_u_int32)$1,
201 $$.q = $<blk>0.q); }
202 | pid
203 ;
204 term: rterm
205 | not term { gen_not($2.b); $$ = $2; }
206 ;
207 head: pqual dqual aqual { QSET($$.q, $1, $2, $3); }
208 | pqual dqual { QSET($$.q, $1, $2, Q_DEFAULT); }
209 | pqual aqual { QSET($$.q, $1, Q_DEFAULT, $2); }
210 | pqual PROTO { QSET($$.q, $1, Q_DEFAULT, Q_PROTO); }
211 | pqual PROTOCHAIN { QSET($$.q, $1, Q_DEFAULT, Q_PROTOCHAIN); }
212 | pqual ndaqual { QSET($$.q, $1, Q_DEFAULT, $2); }
213 ;
214 rterm: head id { $$ = $2; }
215 | paren expr ')' { $$.b = $2.b; $$.q = $1.q; }
216 | pname { $$.b = gen_proto_abbrev($1); $$.q = qerr; }
217 | arth relop arth { $$.b = gen_relation($2, $1, $3, 0);
218 $$.q = qerr; }
219 | arth irelop arth { $$.b = gen_relation($2, $1, $3, 1);
220 $$.q = qerr; }
221 | other { $$.b = $1; $$.q = qerr; }
222 ;
223 /* protocol level qualifiers */
224 pqual: pname
225 | { $$ = Q_DEFAULT; }
226 ;
227 /* 'direction' qualifiers */
228 dqual: SRC { $$ = Q_SRC; }
229 | DST { $$ = Q_DST; }
230 | SRC OR DST { $$ = Q_OR; }
231 | DST OR SRC { $$ = Q_OR; }
232 | SRC AND DST { $$ = Q_AND; }
233 | DST AND SRC { $$ = Q_AND; }
234 | ADDR1 { $$ = Q_ADDR1; }
235 | ADDR2 { $$ = Q_ADDR2; }
236 | ADDR3 { $$ = Q_ADDR3; }
237 | ADDR4 { $$ = Q_ADDR4; }
238 ;
239
240 /* address type qualifiers */
241 aqual: HOST { $$ = Q_HOST; }
242 | NET { $$ = Q_NET; }
243 | PORT { $$ = Q_PORT; }
244 ;
245 /* non-directional address type qualifiers */
246 ndaqual: GATEWAY { $$ = Q_GATEWAY; }
247 ;
248 pname: LINK { $$ = Q_LINK; }
249 | IP { $$ = Q_IP; }
250 | ARP { $$ = Q_ARP; }
251 | RARP { $$ = Q_RARP; }
252 | TCP { $$ = Q_TCP; }
253 | UDP { $$ = Q_UDP; }
254 | ICMP { $$ = Q_ICMP; }
255 | IGMP { $$ = Q_IGMP; }
256 | IGRP { $$ = Q_IGRP; }
257 | PIM { $$ = Q_PIM; }
258 | ATALK { $$ = Q_ATALK; }
259 | DECNET { $$ = Q_DECNET; }
260 | LAT { $$ = Q_LAT; }
261 | SCA { $$ = Q_SCA; }
262 | MOPDL { $$ = Q_MOPDL; }
263 | MOPRC { $$ = Q_MOPRC; }
264 | IPV6 { $$ = Q_IPV6; }
265 | ICMPV6 { $$ = Q_ICMPV6; }
266 | AH { $$ = Q_AH; }
267 | ESP { $$ = Q_ESP; }
268 | STP { $$ = Q_STP; }
269 ;
270 other: pqual TK_BROADCAST { $$ = gen_broadcast($1); }
271 | pqual TK_MULTICAST { $$ = gen_multicast($1); }
272 | LESS NUM { $$ = gen_less($2); }
273 | GREATER NUM { $$ = gen_greater($2); }
274 | BYTE NUM byteop NUM { $$ = gen_byteop($3, $2, $4); }
275 | INBOUND { $$ = gen_inbound(0); }
276 | OUTBOUND { $$ = gen_inbound(1); }
277 | VLAN pnum { $$ = gen_vlan($2); }
278 | VLAN { $$ = gen_vlan(-1); }
279 | MPLS pnum { $$ = gen_mpls($2); }
280 | MPLS { $$ = gen_mpls(-1); }
281 | pfvar { $$ = $1; }
282 | pqual p80211 { $$ = $2; }
283 | SAMPLE NUM { $$ = gen_sample($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 | RND { $$ = gen_loadrnd(); }
427 ;
428 byteop: '&' { $$ = '&'; }
429 | '|' { $$ = '|'; }
430 | '<' { $$ = '<'; }
431 | '>' { $$ = '>'; }
432 | '=' { $$ = '='; }
433 ;
434 pnum: NUM
435 | paren pnum ')' { $$ = $2; }
436 ;
437 %%
438