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