xref: /freebsd/contrib/libpcap/grammar.y.in (revision 7937bfbc0ca53fe7cdd0d54414f9296e273a518e)
1/*
2 * We want a reentrant parser.
3 */
4@REENTRANT_PARSER@
5
6/*
7 * We also want a reentrant scanner, so we have to pass the
8 * handle for the reentrant scanner to the parser, and the
9 * parser has to pass it to the lexical analyzer.
10 *
11 * We use void * rather than yyscan_t because, at least with some
12 * versions of Flex and Bison, if you use yyscan_t in %parse-param and
13 * %lex-param, you have to include scanner.h before grammar.h to get
14 * yyscan_t declared, and you have to include grammar.h before scanner.h
15 * to get YYSTYPE declared.  Using void * breaks the cycle; the Flex
16 * documentation says yyscan_t is just a void *.
17 */
18%parse-param   {void *yyscanner}
19%lex-param   {void *yyscanner}
20
21/*
22 * According to bison documentation, shift/reduce conflicts are not an issue
23 * in most parsers as long as the number does not evolve over time:
24 * https://www.gnu.org/software/bison/manual/html_node/Expect-Decl.html
25 * So, following the advice use %expect to check the amount of shift/reduce
26 * warnings.
27 *
28 * This doesn't appear to work in Berkeley YACC - 1.9 20170709; it still
29 * warns of 38 shift/reduce conflicts.
30 *
31 * The Berkeley YACC documentation:
32 *
33 *    https://invisible-island.net/byacc/manpage/yacc.html
34 *
35 * claims that "Bison's support for "%expect" is broken in more than one
36 * release.", but doesn't give details.  Hopefully, that only means that
37 * you get warnings even if you have the expected number of shift/reduce
38 * conflicts, not that anything else fails.
39 */
40%expect 38
41
42/*
43 * And we need to pass the compiler state to the scanner.
44 */
45%parse-param { compiler_state_t *cstate }
46
47%{
48/*
49 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
50 *	The Regents of the University of California.  All rights reserved.
51 *
52 * Redistribution and use in source and binary forms, with or without
53 * modification, are permitted provided that: (1) source code distributions
54 * retain the above copyright notice and this paragraph in its entirety, (2)
55 * distributions including binary code include the above copyright notice and
56 * this paragraph in its entirety in the documentation or other materials
57 * provided with the distribution, and (3) all advertising materials mentioning
58 * features or use of this software display the following acknowledgement:
59 * ``This product includes software developed by the University of California,
60 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
61 * the University nor the names of its contributors may be used to endorse
62 * or promote products derived from this software without specific prior
63 * written permission.
64 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
65 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
66 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
67 *
68 */
69
70#include <config.h>
71
72/*
73 * grammar.h requires gencode.h and sometimes breaks in a polluted namespace
74 * (see ftmacros.h), so include it early.
75 */
76#include "gencode.h"
77#include "grammar.h"
78
79#include <stdlib.h>
80
81#ifndef _WIN32
82#include <sys/types.h>
83#include <sys/socket.h>
84
85#if __STDC__
86struct mbuf;
87struct rtentry;
88#endif
89
90#include <netinet/in.h>
91#include <arpa/inet.h>
92#endif /* _WIN32 */
93
94#include <stdio.h>
95
96#include "diag-control.h"
97
98#include "pcap-int.h"
99
100#include "scanner.h"
101
102#include "llc.h"
103#include "ieee80211.h"
104#include "pflog.h"
105#include <pcap/namedb.h>
106
107#ifdef HAVE_OS_PROTO_H
108#include "os-proto.h"
109#endif
110
111/*
112 * Work around some bugs in Berkeley YACC prior to the 2017-07-09
113 * release.
114 *
115 * The 2005-05-05 release was the first one to define YYPATCH, so
116 * we treat any release that either 1) doesn't define YYPATCH or
117 * 2) defines it to a value < 20170709 as being buggy.
118 */
119#if defined(YYBYACC) && (!defined(YYPATCH) || YYPATCH < 20170709)
120/*
121 * Both Berkeley YACC and Bison define yydebug (under whatever name
122 * it has) as a global, but Bison does so only if YYDEBUG is defined.
123 * Berkeley YACC, prior to the 2017-07-09 release, defines it even if
124 * YYDEBUG isn't defined; declare it here to suppress a warning.  The
125 * 2017-07-09 release fixes that.
126 */
127#if !defined(YYDEBUG)
128extern int yydebug;
129#endif
130
131/*
132 * In Berkeley YACC, prior to the 2017-07-09 release, yynerrs (under
133 * whatever name it has) is global, even if it's building a reentrant
134 * parser.  In Bison, and in the Berkeley YACC 2017-07-09 release and
135 * later, it's local in reentrant parsers.
136 *
137 * Declare it to squelch a warning.
138 */
139extern int yynerrs;
140#endif
141
142#define QSET(q, p, d, a) (q).proto = (unsigned char)(p),\
143			 (q).dir = (unsigned char)(d),\
144			 (q).addr = (unsigned char)(a)
145
146struct tok {
147	int v;			/* value */
148	const char *s;		/* string */
149};
150
151static const struct tok ieee80211_types[] = {
152	{ IEEE80211_FC0_TYPE_DATA, "data" },
153	{ IEEE80211_FC0_TYPE_MGT, "mgt" },
154	{ IEEE80211_FC0_TYPE_MGT, "management" },
155	{ IEEE80211_FC0_TYPE_CTL, "ctl" },
156	{ IEEE80211_FC0_TYPE_CTL, "control" },
157	{ 0, NULL }
158};
159static const struct tok ieee80211_mgt_subtypes[] = {
160	{ IEEE80211_FC0_SUBTYPE_ASSOC_REQ, "assocreq" },
161	{ IEEE80211_FC0_SUBTYPE_ASSOC_REQ, "assoc-req" },
162	{ IEEE80211_FC0_SUBTYPE_ASSOC_RESP, "assocresp" },
163	{ IEEE80211_FC0_SUBTYPE_ASSOC_RESP, "assoc-resp" },
164	{ IEEE80211_FC0_SUBTYPE_REASSOC_REQ, "reassocreq" },
165	{ IEEE80211_FC0_SUBTYPE_REASSOC_REQ, "reassoc-req" },
166	{ IEEE80211_FC0_SUBTYPE_REASSOC_RESP, "reassocresp" },
167	{ IEEE80211_FC0_SUBTYPE_REASSOC_RESP, "reassoc-resp" },
168	{ IEEE80211_FC0_SUBTYPE_PROBE_REQ, "probereq" },
169	{ IEEE80211_FC0_SUBTYPE_PROBE_REQ, "probe-req" },
170	{ IEEE80211_FC0_SUBTYPE_PROBE_RESP, "proberesp" },
171	{ IEEE80211_FC0_SUBTYPE_PROBE_RESP, "probe-resp" },
172	{ IEEE80211_FC0_SUBTYPE_BEACON, "beacon" },
173	{ IEEE80211_FC0_SUBTYPE_ATIM, "atim" },
174	{ IEEE80211_FC0_SUBTYPE_DISASSOC, "disassoc" },
175	{ IEEE80211_FC0_SUBTYPE_DISASSOC, "disassociation" },
176	{ IEEE80211_FC0_SUBTYPE_AUTH, "auth" },
177	{ IEEE80211_FC0_SUBTYPE_AUTH, "authentication" },
178	{ IEEE80211_FC0_SUBTYPE_DEAUTH, "deauth" },
179	{ IEEE80211_FC0_SUBTYPE_DEAUTH, "deauthentication" },
180	{ 0, NULL }
181};
182static const struct tok ieee80211_ctl_subtypes[] = {
183	{ IEEE80211_FC0_SUBTYPE_PS_POLL, "ps-poll" },
184	{ IEEE80211_FC0_SUBTYPE_RTS, "rts" },
185	{ IEEE80211_FC0_SUBTYPE_CTS, "cts" },
186	{ IEEE80211_FC0_SUBTYPE_ACK, "ack" },
187	{ IEEE80211_FC0_SUBTYPE_CF_END, "cf-end" },
188	{ IEEE80211_FC0_SUBTYPE_CF_END_ACK, "cf-end-ack" },
189	{ 0, NULL }
190};
191static const struct tok ieee80211_data_subtypes[] = {
192	{ IEEE80211_FC0_SUBTYPE_DATA, "data" },
193	{ IEEE80211_FC0_SUBTYPE_CF_ACK, "data-cf-ack" },
194	{ IEEE80211_FC0_SUBTYPE_CF_POLL, "data-cf-poll" },
195	{ IEEE80211_FC0_SUBTYPE_CF_ACPL, "data-cf-ack-poll" },
196	{ IEEE80211_FC0_SUBTYPE_NODATA, "null" },
197	{ IEEE80211_FC0_SUBTYPE_NODATA_CF_ACK, "cf-ack" },
198	{ IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL, "cf-poll"  },
199	{ IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL, "cf-ack-poll" },
200	{ IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_DATA, "qos-data" },
201	{ IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_ACK, "qos-data-cf-ack" },
202	{ IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_POLL, "qos-data-cf-poll" },
203	{ IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_ACPL, "qos-data-cf-ack-poll" },
204	{ IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA, "qos" },
205	{ IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL, "qos-cf-poll" },
206	{ IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL, "qos-cf-ack-poll" },
207	{ 0, NULL }
208};
209static const struct tok llc_s_subtypes[] = {
210	{ LLC_RR, "rr" },
211	{ LLC_RNR, "rnr" },
212	{ LLC_REJ, "rej" },
213	{ 0, NULL }
214};
215static const struct tok llc_u_subtypes[] = {
216	{ LLC_UI, "ui" },
217	{ LLC_UA, "ua" },
218	{ LLC_DISC, "disc" },
219	{ LLC_DM, "dm" },
220	{ LLC_SABME, "sabme" },
221	{ LLC_TEST, "test" },
222	{ LLC_XID, "xid" },
223	{ LLC_FRMR, "frmr" },
224	{ 0, NULL }
225};
226struct type2tok {
227	int type;
228	const struct tok *tok;
229};
230static const struct type2tok ieee80211_type_subtypes[] = {
231	{ IEEE80211_FC0_TYPE_MGT, ieee80211_mgt_subtypes },
232	{ IEEE80211_FC0_TYPE_CTL, ieee80211_ctl_subtypes },
233	{ IEEE80211_FC0_TYPE_DATA, ieee80211_data_subtypes },
234	{ 0, NULL }
235};
236
237static int
238str2tok(const char *str, const struct tok *toks)
239{
240	int i;
241
242	for (i = 0; toks[i].s != NULL; i++) {
243		if (pcapint_strcasecmp(toks[i].s, str) == 0) {
244			/*
245			 * Just in case somebody is using this to
246			 * generate values of -1/0xFFFFFFFF.
247			 * That won't work, as it's indistinguishable
248			 * from an error.
249			 */
250			if (toks[i].v == -1)
251				abort();
252			return (toks[i].v);
253		}
254	}
255	return (-1);
256}
257
258static const struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
259
260static void
261yyerror(void *yyscanner _U_, compiler_state_t *cstate, const char *msg)
262{
263	bpf_set_error(cstate, "can't parse filter expression: %s", msg);
264}
265
266static const struct tok pflog_reasons[] = {
267	{ PFRES_MATCH,		"match" },
268	{ PFRES_BADOFF,		"bad-offset" },
269	{ PFRES_FRAG,		"fragment" },
270	{ PFRES_SHORT,		"short" },
271	{ PFRES_NORM,		"normalize" },
272	{ PFRES_MEMORY,		"memory" },
273	{ PFRES_TS,		"bad-timestamp" },
274	{ PFRES_CONGEST,	"congestion" },
275	{ PFRES_IPOPTIONS,	"ip-option" },
276	{ PFRES_PROTCKSUM,	"proto-cksum" },
277	{ PFRES_BADSTATE,	"state-mismatch" },
278	{ PFRES_STATEINS,	"state-insert" },
279	{ PFRES_MAXSTATES,	"state-limit" },
280	{ PFRES_SRCLIMIT,	"src-limit" },
281	{ PFRES_SYNPROXY,	"synproxy" },
282#if defined(__FreeBSD__)
283	{ PFRES_MAPFAILED,	"map-failed" },
284#elif defined(__NetBSD__)
285	{ PFRES_STATELOCKED,	"state-locked" },
286#elif defined(__OpenBSD__)
287	{ PFRES_TRANSLATE,	"translate" },
288	{ PFRES_NOROUTE,	"no-route" },
289#elif defined(__APPLE__)
290	{ PFRES_DUMMYNET,	"dummynet" },
291#endif
292	{ 0, NULL }
293};
294
295static int
296pfreason_to_num(compiler_state_t *cstate, const char *reason)
297{
298	int i;
299
300	i = str2tok(reason, pflog_reasons);
301	if (i == -1)
302		bpf_set_error(cstate, "unknown PF reason \"%s\"", reason);
303	return (i);
304}
305
306static const struct tok pflog_actions[] = {
307	{ PF_PASS,		"pass" },
308	{ PF_PASS,		"accept" },	/* alias for "pass" */
309	{ PF_DROP,		"drop" },
310	{ PF_DROP,		"block" },	/* alias for "drop" */
311	{ PF_SCRUB,		"scrub" },
312	{ PF_NOSCRUB,		"noscrub" },
313	{ PF_NAT,		"nat" },
314	{ PF_NONAT,		"nonat" },
315	{ PF_BINAT,		"binat" },
316	{ PF_NOBINAT,		"nobinat" },
317	{ PF_RDR,		"rdr" },
318	{ PF_NORDR,		"nordr" },
319	{ PF_SYNPROXY_DROP,	"synproxy-drop" },
320#if defined(__FreeBSD__)
321	{ PF_DEFER,		"defer" },
322#elif defined(__OpenBSD__)
323	{ PF_DEFER,		"defer" },
324	{ PF_MATCH,		"match" },
325	{ PF_DIVERT,		"divert" },
326	{ PF_RT,		"rt" },
327	{ PF_AFRT,		"afrt" },
328#elif defined(__APPLE__)
329	{ PF_DUMMYNET,		"dummynet" },
330	{ PF_NODUMMYNET,	"nodummynet" },
331	{ PF_NAT64,		"nat64" },
332	{ PF_NONAT64,		"nonat64" },
333#endif
334	{ 0, NULL },
335};
336
337static int
338pfaction_to_num(compiler_state_t *cstate, const char *action)
339{
340	int i;
341
342	i = str2tok(action, pflog_actions);
343	if (i == -1)
344		bpf_set_error(cstate, "unknown PF action \"%s\"", action);
345	return (i);
346}
347
348/*
349 * For calls that might return an "an error occurred" value.
350 */
351#define CHECK_INT_VAL(val)	if (val == -1) YYABORT
352#define CHECK_PTR_VAL(val)	if (val == NULL) YYABORT
353
354DIAG_OFF_BISON_BYACC
355%}
356
357%union {
358	int i;
359	bpf_u_int32 h;
360	char *s;
361	struct stmt *stmt;
362	struct arth *a;
363	struct {
364		struct qual q;
365		int atmfieldtype;
366		int mtp3fieldtype;
367		struct block *b;
368	} blk;
369	struct block *rblk;
370}
371
372%type	<blk>	expr id nid pid term rterm qid
373%type	<blk>	head
374%type	<i>	pqual dqual aqual ndaqual
375%type	<a>	arth narth
376%type	<i>	byteop pname relop irelop
377%type	<h>	pnum
378%type	<blk>	and or paren not null prog
379%type	<rblk>	other pfvar p80211 pllc
380%type	<i>	atmtype atmmultitype
381%type	<blk>	atmfield
382%type	<blk>	atmfieldvalue atmvalue atmlistvalue
383%type	<i>	mtp2type
384%type	<blk>	mtp3field
385%type	<blk>	mtp3fieldvalue mtp3value mtp3listvalue
386
387
388%token  DST SRC HOST GATEWAY
389%token  NET NETMASK PORT PORTRANGE LESS GREATER PROTO PROTOCHAIN CBYTE
390%token  ARP RARP IP SCTP TCP UDP ICMP IGMP IGRP PIM VRRP CARP
391%token  ATALK AARP DECNET LAT SCA MOPRC MOPDL
392%token  TK_BROADCAST TK_MULTICAST
393%token  NUM INBOUND OUTBOUND
394%token  IFINDEX
395%token  PF_IFNAME PF_RSET PF_RNR PF_SRNR PF_REASON PF_ACTION
396%token	TYPE SUBTYPE DIR ADDR1 ADDR2 ADDR3 ADDR4 RA TA
397%token  LINK
398%token	GEQ LEQ NEQ
399%token	ID EID HID HID6 AID
400%token	LSH RSH
401%token  LEN
402%token  IPV6 ICMPV6 AH ESP
403%token	VLAN MPLS
404%token	PPPOED PPPOES GENEVE
405%token  ISO ESIS CLNP ISIS L1 L2 IIH LSP SNP CSNP PSNP
406%token  STP
407%token  IPX
408%token  NETBEUI
409%token	LANE LLC METAC BCC SC ILMIC OAMF4EC OAMF4SC
410%token	OAM OAMF4 CONNECTMSG METACONNECT
411%token	VPI VCI
412%token	RADIO
413%token	FISU LSSU MSU HFISU HLSSU HMSU
414%token	SIO OPC DPC SLS HSIO HOPC HDPC HSLS
415%token	LEX_ERROR
416
417%type	<s> ID EID AID
418%type	<s> HID HID6
419%type	<h> NUM
420%type	<i> action reason type subtype type_subtype dir
421
422%left OR AND
423%nonassoc  '!'
424%left '|'
425%left '&'
426%left LSH RSH
427%left '+' '-'
428%left '*' '/'
429%nonassoc UMINUS
430%%
431prog:	  null expr
432{
433	/*
434	 * I'm not sure we have a reason to use yynerrs, but it's
435	 * declared, and incremented, whether we need it or not,
436	 * which means that Clang 15 will give a "used but not
437	 * set" warning.  This should suppress the warning for
438	 * yynerrs without suppressing it for other variables.
439	 */
440	(void) yynerrs;
441	CHECK_INT_VAL(finish_parse(cstate, $2.b));
442}
443	| null
444	;
445null:	  /* null */		{ $$.q = qerr; }
446	;
447expr:	  term
448	| expr and term		{ gen_and($1.b, $3.b); $$ = $3; }
449	| expr and id		{ gen_and($1.b, $3.b); $$ = $3; }
450	| expr or term		{ gen_or($1.b, $3.b); $$ = $3; }
451	| expr or id		{ gen_or($1.b, $3.b); $$ = $3; }
452	;
453and:	  AND			{ $$ = $<blk>0; }
454	;
455or:	  OR			{ $$ = $<blk>0; }
456	;
457id:	  nid
458	| pnum			{ CHECK_PTR_VAL(($$.b = gen_ncode(cstate, NULL, $1,
459						   $$.q = $<blk>0.q))); }
460	| paren pid ')'		{ $$ = $2; }
461	;
462nid:	  ID			{ CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_scode(cstate, $1, $$.q = $<blk>0.q))); }
463	| HID '/' NUM		{
464				  CHECK_PTR_VAL($1);
465				  /* Check whether HID/NUM is being used when appropriate */
466				  $$.q = $<blk>0.q;
467				  if ($$.q.addr == Q_PORT) {
468					bpf_set_error(cstate, "'port' modifier applied to IP address and prefix length");
469					YYABORT;
470				  } else if ($$.q.addr == Q_PORTRANGE) {
471					bpf_set_error(cstate, "'portrange' modifier applied to IP address and prefix length");
472					YYABORT;
473				  } else if ($$.q.addr == Q_PROTO) {
474					bpf_set_error(cstate, "'proto' modifier applied to IP address and prefix length");
475					YYABORT;
476				  } else if ($$.q.addr == Q_PROTOCHAIN) {
477					bpf_set_error(cstate, "'protochain' modifier applied to IP address and prefix length");
478					YYABORT;
479				  }
480				  CHECK_PTR_VAL(($$.b = gen_mcode(cstate, $1, NULL, $3, $$.q)));
481				}
482	| HID NETMASK HID	{
483				  CHECK_PTR_VAL($1);
484				  /* Check whether HID mask HID is being used when appropriate */
485				  $$.q = $<blk>0.q;
486				  if ($$.q.addr == Q_PORT) {
487					bpf_set_error(cstate, "'port' modifier applied to IP address and netmask");
488					YYABORT;
489				  } else if ($$.q.addr == Q_PORTRANGE) {
490					bpf_set_error(cstate, "'portrange' modifier applied to IP address and netmask");
491					YYABORT;
492				  } else if ($$.q.addr == Q_PROTO) {
493					bpf_set_error(cstate, "'proto' modifier applied to IP address and netmask");
494					YYABORT;
495				  } else if ($$.q.addr == Q_PROTOCHAIN) {
496					bpf_set_error(cstate, "'protochain' modifier applied to IP address and netmask");
497					YYABORT;
498				  }
499				  CHECK_PTR_VAL(($$.b = gen_mcode(cstate, $1, $3, 0, $$.q)));
500				}
501	| HID			{
502				  CHECK_PTR_VAL($1);
503				  /* Check whether HID is being used when appropriate */
504				  $$.q = $<blk>0.q;
505				  if ($$.q.addr == Q_PORT) {
506					bpf_set_error(cstate, "'port' modifier applied to IP address");
507					YYABORT;
508				  } else if ($$.q.addr == Q_PORTRANGE) {
509					bpf_set_error(cstate, "'portrange' modifier applied to IP address");
510					YYABORT;
511				  } else if ($$.q.addr == Q_PROTO) {
512					bpf_set_error(cstate, "'proto' modifier applied to IP address");
513					YYABORT;
514				  } else if ($$.q.addr == Q_PROTOCHAIN) {
515					bpf_set_error(cstate, "'protochain' modifier applied to IP address");
516					YYABORT;
517				  }
518				  CHECK_PTR_VAL(($$.b = gen_ncode(cstate, $1, 0, $$.q)));
519				}
520	| HID6 '/' NUM		{
521				  CHECK_PTR_VAL($1);
522#ifdef INET6
523				  /* Check whether HID6/NUM is being used when appropriate */
524				  $$.q = $<blk>0.q;
525				  if ($$.q.addr == Q_PORT) {
526					bpf_set_error(cstate, "'port' modifier applied to IP address and prefix length");
527					YYABORT;
528				  } else if ($$.q.addr == Q_PORTRANGE) {
529					bpf_set_error(cstate, "'portrange' modifier applied to IP address and prefix length");
530					YYABORT;
531				  } else if ($$.q.addr == Q_PROTO) {
532					bpf_set_error(cstate, "'proto' modifier applied to IP address and prefix length ");
533					YYABORT;
534				  } else if ($$.q.addr == Q_PROTOCHAIN) {
535					bpf_set_error(cstate, "'protochain' modifier applied to IP address and prefix length");
536					YYABORT;
537				  }
538				  CHECK_PTR_VAL(($$.b = gen_mcode6(cstate, $1, $3, $$.q)));
539#else
540				  bpf_set_error(cstate, "IPv6 addresses not supported "
541					"in this configuration");
542				  YYABORT;
543#endif /*INET6*/
544				}
545	| HID6			{
546				  CHECK_PTR_VAL($1);
547#ifdef INET6
548				  /* Check whether HID6 is being used when appropriate */
549				  $$.q = $<blk>0.q;
550				  if ($$.q.addr == Q_PORT) {
551					bpf_set_error(cstate, "'port' modifier applied to IP address");
552					YYABORT;
553				  } else if ($$.q.addr == Q_PORTRANGE) {
554					bpf_set_error(cstate, "'portrange' modifier applied to IP address");
555					YYABORT;
556				  } else if ($$.q.addr == Q_PROTO) {
557					bpf_set_error(cstate, "'proto' modifier applied to 'ip6addr/prefixlen");
558					YYABORT;
559				  } else if ($$.q.addr == Q_PROTOCHAIN) {
560					bpf_set_error(cstate, "'protochain' modifier applied to IP address");
561					YYABORT;
562				  }
563				  CHECK_PTR_VAL(($$.b = gen_mcode6(cstate, $1, 128, $$.q)));
564#else
565				  bpf_set_error(cstate, "IPv6 addresses not supported "
566					"in this configuration");
567				  YYABORT;
568#endif /*INET6*/
569				}
570	| EID			{ CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_ecode(cstate, $1, $$.q = $<blk>0.q))); }
571	| AID			{ CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_acode(cstate, $1, $$.q = $<blk>0.q))); }
572	| not id		{ gen_not($2.b); $$ = $2; }
573	;
574not:	  '!'			{ $$ = $<blk>0; }
575	;
576paren:	  '('			{ $$ = $<blk>0; }
577	;
578pid:	  nid
579	| qid and id		{ gen_and($1.b, $3.b); $$ = $3; }
580	| qid or id		{ gen_or($1.b, $3.b); $$ = $3; }
581	;
582qid:	  pnum			{ CHECK_PTR_VAL(($$.b = gen_ncode(cstate, NULL, $1,
583						   $$.q = $<blk>0.q))); }
584	| pid
585	;
586term:	  rterm
587	| not term		{ gen_not($2.b); $$ = $2; }
588	;
589head:	  pqual dqual aqual	{ QSET($$.q, $1, $2, $3); }
590	| pqual dqual		{ QSET($$.q, $1, $2, Q_DEFAULT); }
591	| pqual aqual		{ QSET($$.q, $1, Q_DEFAULT, $2); }
592	| pqual PROTO		{ QSET($$.q, $1, Q_DEFAULT, Q_PROTO); }
593	| pqual PROTOCHAIN	{
594#ifdef NO_PROTOCHAIN
595				  bpf_set_error(cstate, "protochain not supported");
596				  YYABORT;
597#else
598				  QSET($$.q, $1, Q_DEFAULT, Q_PROTOCHAIN);
599#endif
600				}
601	| pqual ndaqual		{ QSET($$.q, $1, Q_DEFAULT, $2); }
602	;
603rterm:	  head id		{ $$ = $2; }
604	| paren expr ')'	{ $$.b = $2.b; $$.q = $1.q; }
605	| pname			{ CHECK_PTR_VAL(($$.b = gen_proto_abbrev(cstate, $1))); $$.q = qerr; }
606	| arth relop arth	{ CHECK_PTR_VAL(($$.b = gen_relation(cstate, $2, $1, $3, 0)));
607				  $$.q = qerr; }
608	| arth irelop arth	{ CHECK_PTR_VAL(($$.b = gen_relation(cstate, $2, $1, $3, 1)));
609				  $$.q = qerr; }
610	| other			{ $$.b = $1; $$.q = qerr; }
611	| atmtype		{ CHECK_PTR_VAL(($$.b = gen_atmtype_abbrev(cstate, $1))); $$.q = qerr; }
612	| atmmultitype		{ CHECK_PTR_VAL(($$.b = gen_atmmulti_abbrev(cstate, $1))); $$.q = qerr; }
613	| atmfield atmvalue	{ $$.b = $2.b; $$.q = qerr; }
614	| mtp2type		{ CHECK_PTR_VAL(($$.b = gen_mtp2type_abbrev(cstate, $1))); $$.q = qerr; }
615	| mtp3field mtp3value	{ $$.b = $2.b; $$.q = qerr; }
616	;
617/* protocol level qualifiers */
618pqual:	  pname
619	|			{ $$ = Q_DEFAULT; }
620	;
621/* 'direction' qualifiers */
622dqual:	  SRC			{ $$ = Q_SRC; }
623	| DST			{ $$ = Q_DST; }
624	| SRC OR DST		{ $$ = Q_OR; }
625	| DST OR SRC		{ $$ = Q_OR; }
626	| SRC AND DST		{ $$ = Q_AND; }
627	| DST AND SRC		{ $$ = Q_AND; }
628	| ADDR1			{ $$ = Q_ADDR1; }
629	| ADDR2			{ $$ = Q_ADDR2; }
630	| ADDR3			{ $$ = Q_ADDR3; }
631	| ADDR4			{ $$ = Q_ADDR4; }
632	| RA			{ $$ = Q_RA; }
633	| TA			{ $$ = Q_TA; }
634	;
635/* address type qualifiers */
636aqual:	  HOST			{ $$ = Q_HOST; }
637	| NET			{ $$ = Q_NET; }
638	| PORT			{ $$ = Q_PORT; }
639	| PORTRANGE		{ $$ = Q_PORTRANGE; }
640	;
641/* non-directional address type qualifiers */
642ndaqual:  GATEWAY		{ $$ = Q_GATEWAY; }
643	;
644pname:	  LINK			{ $$ = Q_LINK; }
645	| IP			{ $$ = Q_IP; }
646	| ARP			{ $$ = Q_ARP; }
647	| RARP			{ $$ = Q_RARP; }
648	| SCTP			{ $$ = Q_SCTP; }
649	| TCP			{ $$ = Q_TCP; }
650	| UDP			{ $$ = Q_UDP; }
651	| ICMP			{ $$ = Q_ICMP; }
652	| IGMP			{ $$ = Q_IGMP; }
653	| IGRP			{ $$ = Q_IGRP; }
654	| PIM			{ $$ = Q_PIM; }
655	| VRRP			{ $$ = Q_VRRP; }
656	| CARP			{ $$ = Q_CARP; }
657	| ATALK			{ $$ = Q_ATALK; }
658	| AARP			{ $$ = Q_AARP; }
659	| DECNET		{ $$ = Q_DECNET; }
660	| LAT			{ $$ = Q_LAT; }
661	| SCA			{ $$ = Q_SCA; }
662	| MOPDL			{ $$ = Q_MOPDL; }
663	| MOPRC			{ $$ = Q_MOPRC; }
664	| IPV6			{ $$ = Q_IPV6; }
665	| ICMPV6		{ $$ = Q_ICMPV6; }
666	| AH			{ $$ = Q_AH; }
667	| ESP			{ $$ = Q_ESP; }
668	| ISO			{ $$ = Q_ISO; }
669	| ESIS			{ $$ = Q_ESIS; }
670	| ISIS			{ $$ = Q_ISIS; }
671	| L1			{ $$ = Q_ISIS_L1; }
672	| L2			{ $$ = Q_ISIS_L2; }
673	| IIH			{ $$ = Q_ISIS_IIH; }
674	| LSP			{ $$ = Q_ISIS_LSP; }
675	| SNP			{ $$ = Q_ISIS_SNP; }
676	| PSNP			{ $$ = Q_ISIS_PSNP; }
677	| CSNP			{ $$ = Q_ISIS_CSNP; }
678	| CLNP			{ $$ = Q_CLNP; }
679	| STP			{ $$ = Q_STP; }
680	| IPX			{ $$ = Q_IPX; }
681	| NETBEUI		{ $$ = Q_NETBEUI; }
682	| RADIO			{ $$ = Q_RADIO; }
683	;
684other:	  pqual TK_BROADCAST	{ CHECK_PTR_VAL(($$ = gen_broadcast(cstate, $1))); }
685	| pqual TK_MULTICAST	{ CHECK_PTR_VAL(($$ = gen_multicast(cstate, $1))); }
686	| LESS NUM		{ CHECK_PTR_VAL(($$ = gen_less(cstate, $2))); }
687	| GREATER NUM		{ CHECK_PTR_VAL(($$ = gen_greater(cstate, $2))); }
688	| CBYTE NUM byteop NUM	{ CHECK_PTR_VAL(($$ = gen_byteop(cstate, $3, $2, $4))); }
689	| INBOUND		{ CHECK_PTR_VAL(($$ = gen_inbound(cstate, 0))); }
690	| OUTBOUND		{ CHECK_PTR_VAL(($$ = gen_inbound(cstate, 1))); }
691	| IFINDEX NUM		{ CHECK_PTR_VAL(($$ = gen_ifindex(cstate, $2))); }
692	| VLAN pnum		{ CHECK_PTR_VAL(($$ = gen_vlan(cstate, $2, 1))); }
693	| VLAN			{ CHECK_PTR_VAL(($$ = gen_vlan(cstate, 0, 0))); }
694	| MPLS pnum		{ CHECK_PTR_VAL(($$ = gen_mpls(cstate, $2, 1))); }
695	| MPLS			{ CHECK_PTR_VAL(($$ = gen_mpls(cstate, 0, 0))); }
696	| PPPOED		{ CHECK_PTR_VAL(($$ = gen_pppoed(cstate))); }
697	| PPPOES pnum		{ CHECK_PTR_VAL(($$ = gen_pppoes(cstate, $2, 1))); }
698	| PPPOES		{ CHECK_PTR_VAL(($$ = gen_pppoes(cstate, 0, 0))); }
699	| GENEVE pnum		{ CHECK_PTR_VAL(($$ = gen_geneve(cstate, $2, 1))); }
700	| GENEVE		{ CHECK_PTR_VAL(($$ = gen_geneve(cstate, 0, 0))); }
701	| pfvar			{ $$ = $1; }
702	| pqual p80211		{ $$ = $2; }
703	| pllc			{ $$ = $1; }
704	;
705
706pfvar:	  PF_IFNAME ID		{ CHECK_PTR_VAL($2); CHECK_PTR_VAL(($$ = gen_pf_ifname(cstate, $2))); }
707	| PF_RSET ID		{ CHECK_PTR_VAL($2); CHECK_PTR_VAL(($$ = gen_pf_ruleset(cstate, $2))); }
708	| PF_RNR NUM		{ CHECK_PTR_VAL(($$ = gen_pf_rnr(cstate, $2))); }
709	| PF_SRNR NUM		{ CHECK_PTR_VAL(($$ = gen_pf_srnr(cstate, $2))); }
710	| PF_REASON reason	{ CHECK_PTR_VAL(($$ = gen_pf_reason(cstate, $2))); }
711	| PF_ACTION action	{ CHECK_PTR_VAL(($$ = gen_pf_action(cstate, $2))); }
712	;
713
714p80211:   TYPE type SUBTYPE subtype
715				{ CHECK_PTR_VAL(($$ = gen_p80211_type(cstate, $2 | $4,
716					IEEE80211_FC0_TYPE_MASK |
717					IEEE80211_FC0_SUBTYPE_MASK)));
718				}
719	| TYPE type		{ CHECK_PTR_VAL(($$ = gen_p80211_type(cstate, $2,
720					IEEE80211_FC0_TYPE_MASK)));
721				}
722	| SUBTYPE type_subtype	{ CHECK_PTR_VAL(($$ = gen_p80211_type(cstate, $2,
723					IEEE80211_FC0_TYPE_MASK |
724					IEEE80211_FC0_SUBTYPE_MASK)));
725				}
726	| DIR dir		{ CHECK_PTR_VAL(($$ = gen_p80211_fcdir(cstate, $2))); }
727	;
728
729type:	  NUM			{ if (($1 & (~IEEE80211_FC0_TYPE_MASK)) != 0) {
730					bpf_set_error(cstate, "invalid 802.11 type value 0x%02x", $1);
731					YYABORT;
732				  }
733				  $$ = (int)$1;
734				}
735	| ID			{ CHECK_PTR_VAL($1);
736				  $$ = str2tok($1, ieee80211_types);
737				  if ($$ == -1) {
738					bpf_set_error(cstate, "unknown 802.11 type name \"%s\"", $1);
739					YYABORT;
740				  }
741				}
742	;
743
744subtype:  NUM			{ if (($1 & (~IEEE80211_FC0_SUBTYPE_MASK)) != 0) {
745					bpf_set_error(cstate, "invalid 802.11 subtype value 0x%02x", $1);
746					YYABORT;
747				  }
748				  $$ = (int)$1;
749				}
750	| ID			{ const struct tok *types = NULL;
751				  int i;
752				  CHECK_PTR_VAL($1);
753				  for (i = 0;; i++) {
754					if (ieee80211_type_subtypes[i].tok == NULL) {
755						/* Ran out of types */
756						bpf_set_error(cstate, "unknown 802.11 type");
757						YYABORT;
758					}
759					if ($<i>-1 == ieee80211_type_subtypes[i].type) {
760						types = ieee80211_type_subtypes[i].tok;
761						break;
762					}
763				  }
764
765				  $$ = str2tok($1, types);
766				  if ($$ == -1) {
767					bpf_set_error(cstate, "unknown 802.11 subtype name \"%s\"", $1);
768					YYABORT;
769				  }
770				}
771	;
772
773type_subtype:	ID		{ int i;
774				  CHECK_PTR_VAL($1);
775				  for (i = 0;; i++) {
776					if (ieee80211_type_subtypes[i].tok == NULL) {
777						/* Ran out of types */
778						bpf_set_error(cstate, "unknown 802.11 type name");
779						YYABORT;
780					}
781					$$ = str2tok($1, ieee80211_type_subtypes[i].tok);
782					if ($$ != -1) {
783						$$ |= ieee80211_type_subtypes[i].type;
784						break;
785					}
786				  }
787				}
788		;
789
790pllc:	LLC			{ CHECK_PTR_VAL(($$ = gen_llc(cstate))); }
791	| LLC ID		{ CHECK_PTR_VAL($2);
792				  if (pcapint_strcasecmp($2, "i") == 0) {
793					CHECK_PTR_VAL(($$ = gen_llc_i(cstate)));
794				  } else if (pcapint_strcasecmp($2, "s") == 0) {
795					CHECK_PTR_VAL(($$ = gen_llc_s(cstate)));
796				  } else if (pcapint_strcasecmp($2, "u") == 0) {
797					CHECK_PTR_VAL(($$ = gen_llc_u(cstate)));
798				  } else {
799					int subtype;
800
801					subtype = str2tok($2, llc_s_subtypes);
802					if (subtype != -1) {
803						CHECK_PTR_VAL(($$ = gen_llc_s_subtype(cstate, subtype)));
804					} else {
805						subtype = str2tok($2, llc_u_subtypes);
806						if (subtype == -1) {
807							bpf_set_error(cstate, "unknown LLC type name \"%s\"", $2);
808							YYABORT;
809						}
810						CHECK_PTR_VAL(($$ = gen_llc_u_subtype(cstate, subtype)));
811					}
812				  }
813				}
814				/* sigh, "rnr" is already a keyword for PF */
815	| LLC PF_RNR		{ CHECK_PTR_VAL(($$ = gen_llc_s_subtype(cstate, LLC_RNR))); }
816	;
817
818dir:	  NUM			{ $$ = (int)$1; }
819	| ID			{ CHECK_PTR_VAL($1);
820				  if (pcapint_strcasecmp($1, "nods") == 0)
821					$$ = IEEE80211_FC1_DIR_NODS;
822				  else if (pcapint_strcasecmp($1, "tods") == 0)
823					$$ = IEEE80211_FC1_DIR_TODS;
824				  else if (pcapint_strcasecmp($1, "fromds") == 0)
825					$$ = IEEE80211_FC1_DIR_FROMDS;
826				  else if (pcapint_strcasecmp($1, "dstods") == 0)
827					$$ = IEEE80211_FC1_DIR_DSTODS;
828				  else {
829					bpf_set_error(cstate, "unknown 802.11 direction");
830					YYABORT;
831				  }
832				}
833	;
834
835reason:	  NUM			{ $$ = $1; }
836	| ID			{ CHECK_PTR_VAL($1); CHECK_INT_VAL(($$ = pfreason_to_num(cstate, $1))); }
837	;
838
839action:	  ID			{ CHECK_PTR_VAL($1); CHECK_INT_VAL(($$ = pfaction_to_num(cstate, $1))); }
840	;
841
842relop:	  '>'			{ $$ = BPF_JGT; }
843	| GEQ			{ $$ = BPF_JGE; }
844	| '='			{ $$ = BPF_JEQ; }
845	;
846irelop:	  LEQ			{ $$ = BPF_JGT; }
847	| '<'			{ $$ = BPF_JGE; }
848	| NEQ			{ $$ = BPF_JEQ; }
849	;
850arth:	  pnum			{ CHECK_PTR_VAL(($$ = gen_loadi(cstate, $1))); }
851	| narth
852	;
853narth:	  pname '[' arth ']'		{ CHECK_PTR_VAL(($$ = gen_load(cstate, $1, $3, 1))); }
854	| pname '[' arth ':' NUM ']'	{ CHECK_PTR_VAL(($$ = gen_load(cstate, $1, $3, $5))); }
855	| arth '+' arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_ADD, $1, $3))); }
856	| arth '-' arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_SUB, $1, $3))); }
857	| arth '*' arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_MUL, $1, $3))); }
858	| arth '/' arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_DIV, $1, $3))); }
859	| arth '%' arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_MOD, $1, $3))); }
860	| arth '&' arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_AND, $1, $3))); }
861	| arth '|' arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_OR, $1, $3))); }
862	| arth '^' arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_XOR, $1, $3))); }
863	| arth LSH arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_LSH, $1, $3))); }
864	| arth RSH arth			{ CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_RSH, $1, $3))); }
865	| '-' arth %prec UMINUS		{ CHECK_PTR_VAL(($$ = gen_neg(cstate, $2))); }
866	| paren narth ')'		{ $$ = $2; }
867	| LEN				{ CHECK_PTR_VAL(($$ = gen_loadlen(cstate))); }
868	;
869byteop:	  '&'			{ $$ = '&'; }
870	| '|'			{ $$ = '|'; }
871	| '<'			{ $$ = '<'; }
872	| '>'			{ $$ = '>'; }
873	| '='			{ $$ = '='; }
874	;
875pnum:	  NUM
876	| paren pnum ')'	{ $$ = $2; }
877	;
878atmtype: LANE			{ $$ = A_LANE; }
879	| METAC			{ $$ = A_METAC;	}
880	| BCC			{ $$ = A_BCC; }
881	| OAMF4EC		{ $$ = A_OAMF4EC; }
882	| OAMF4SC		{ $$ = A_OAMF4SC; }
883	| SC			{ $$ = A_SC; }
884	| ILMIC			{ $$ = A_ILMIC; }
885	;
886atmmultitype: OAM		{ $$ = A_OAM; }
887	| OAMF4			{ $$ = A_OAMF4; }
888	| CONNECTMSG		{ $$ = A_CONNECTMSG; }
889	| METACONNECT		{ $$ = A_METACONNECT; }
890	;
891	/* ATM field types quantifier */
892atmfield: VPI			{ $$.atmfieldtype = A_VPI; }
893	| VCI			{ $$.atmfieldtype = A_VCI; }
894	;
895atmvalue: atmfieldvalue
896	| relop NUM		{ CHECK_PTR_VAL(($$.b = gen_atmfield_code(cstate, $<blk>0.atmfieldtype, $2, $1, 0))); }
897	| irelop NUM		{ CHECK_PTR_VAL(($$.b = gen_atmfield_code(cstate, $<blk>0.atmfieldtype, $2, $1, 1))); }
898	| paren atmlistvalue ')' { $$.b = $2.b; $$.q = qerr; }
899	;
900atmfieldvalue: NUM {
901	$$.atmfieldtype = $<blk>0.atmfieldtype;
902	if ($$.atmfieldtype == A_VPI ||
903	    $$.atmfieldtype == A_VCI)
904		CHECK_PTR_VAL(($$.b = gen_atmfield_code(cstate, $$.atmfieldtype, $1, BPF_JEQ, 0)));
905	}
906	;
907atmlistvalue: atmfieldvalue
908	| atmlistvalue or atmfieldvalue { gen_or($1.b, $3.b); $$ = $3; }
909	;
910	/* MTP2 types quantifier */
911mtp2type: FISU			{ $$ = M_FISU; }
912	| LSSU			{ $$ = M_LSSU; }
913	| MSU			{ $$ = M_MSU; }
914	| HFISU			{ $$ = MH_FISU; }
915	| HLSSU			{ $$ = MH_LSSU; }
916	| HMSU			{ $$ = MH_MSU; }
917	;
918	/* MTP3 field types quantifier */
919mtp3field: SIO			{ $$.mtp3fieldtype = M_SIO; }
920	| OPC			{ $$.mtp3fieldtype = M_OPC; }
921	| DPC			{ $$.mtp3fieldtype = M_DPC; }
922	| SLS                   { $$.mtp3fieldtype = M_SLS; }
923	| HSIO			{ $$.mtp3fieldtype = MH_SIO; }
924	| HOPC			{ $$.mtp3fieldtype = MH_OPC; }
925	| HDPC			{ $$.mtp3fieldtype = MH_DPC; }
926	| HSLS                  { $$.mtp3fieldtype = MH_SLS; }
927	;
928mtp3value: mtp3fieldvalue
929	| relop NUM		{ CHECK_PTR_VAL(($$.b = gen_mtp3field_code(cstate, $<blk>0.mtp3fieldtype, $2, $1, 0))); }
930	| irelop NUM		{ CHECK_PTR_VAL(($$.b = gen_mtp3field_code(cstate, $<blk>0.mtp3fieldtype, $2, $1, 1))); }
931	| paren mtp3listvalue ')' { $$.b = $2.b; $$.q = qerr; }
932	;
933mtp3fieldvalue: NUM {
934	$$.mtp3fieldtype = $<blk>0.mtp3fieldtype;
935	if ($$.mtp3fieldtype == M_SIO ||
936	    $$.mtp3fieldtype == M_OPC ||
937	    $$.mtp3fieldtype == M_DPC ||
938	    $$.mtp3fieldtype == M_SLS ||
939	    $$.mtp3fieldtype == MH_SIO ||
940	    $$.mtp3fieldtype == MH_OPC ||
941	    $$.mtp3fieldtype == MH_DPC ||
942	    $$.mtp3fieldtype == MH_SLS)
943		CHECK_PTR_VAL(($$.b = gen_mtp3field_code(cstate, $$.mtp3fieldtype, $1, BPF_JEQ, 0)));
944	}
945	;
946mtp3listvalue: mtp3fieldvalue
947	| mtp3listvalue or mtp3fieldvalue { gen_or($1.b, $3.b); $$ = $3; }
948	;
949%%
950