xref: /openbsd/lib/libpcap/grammar.y (revision e5dd7070)
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