xref: /netbsd/usr.sbin/npf/npfctl/npf_parse.y (revision a894e3f7)
1*a894e3f7Srmind /*	$NetBSD: npf_parse.y,v 1.32 2014/02/13 03:34:40 rmind Exp $	*/
2f03cb1d4Srmind 
3f03cb1d4Srmind /*-
4*a894e3f7Srmind  * Copyright (c) 2011-2014 The NetBSD Foundation, Inc.
5f03cb1d4Srmind  * All rights reserved.
6f03cb1d4Srmind  *
7f03cb1d4Srmind  * This code is derived from software contributed to The NetBSD Foundation
8c6e77e2aSrmind  * by Martin Husemann, Christos Zoulas and Mindaugas Rasiukevicius.
9f03cb1d4Srmind  *
10f03cb1d4Srmind  * Redistribution and use in source and binary forms, with or without
11f03cb1d4Srmind  * modification, are permitted provided that the following conditions
12f03cb1d4Srmind  * are met:
13f03cb1d4Srmind  * 1. Redistributions of source code must retain the above copyright
14f03cb1d4Srmind  *    notice, this list of conditions and the following disclaimer.
15f03cb1d4Srmind  * 2. Redistributions in binary form must reproduce the above copyright
16f03cb1d4Srmind  *    notice, this list of conditions and the following disclaimer in the
17f03cb1d4Srmind  *    documentation and/or other materials provided with the distribution.
18f03cb1d4Srmind  *
19f03cb1d4Srmind  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20f03cb1d4Srmind  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21f03cb1d4Srmind  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22f03cb1d4Srmind  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23f03cb1d4Srmind  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24f03cb1d4Srmind  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25f03cb1d4Srmind  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26f03cb1d4Srmind  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27f03cb1d4Srmind  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28f03cb1d4Srmind  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29f03cb1d4Srmind  * POSSIBILITY OF SUCH DAMAGE.
30f03cb1d4Srmind  */
31f03cb1d4Srmind 
32f03cb1d4Srmind %{
33f03cb1d4Srmind 
34f03cb1d4Srmind #include <stdio.h>
35f03cb1d4Srmind #include <err.h>
36f03cb1d4Srmind #include <vis.h>
37f03cb1d4Srmind #include <netdb.h>
38f03cb1d4Srmind 
39f03cb1d4Srmind #include "npfctl.h"
40f03cb1d4Srmind 
418b3f8af5Srmind #define	YYSTACKSIZE	4096
428b3f8af5Srmind 
4337527ec6Srmind int			yyparsetarget;
44f03cb1d4Srmind const char *		yyfilename;
45f03cb1d4Srmind 
46f03cb1d4Srmind extern int		yylineno, yycolumn;
47f03cb1d4Srmind extern int		yylex(void);
48f03cb1d4Srmind 
49f03cb1d4Srmind void
50f03cb1d4Srmind yyerror(const char *fmt, ...)
51f03cb1d4Srmind {
52f03cb1d4Srmind 	extern int yyleng;
53f03cb1d4Srmind 	extern char *yytext;
54f03cb1d4Srmind 
557c0a5ca2Srmind 	char *msg, *context = estrndup(yytext, yyleng);
564e3d5046Srmind 	bool eol = (*context == '\n');
57f03cb1d4Srmind 	va_list ap;
58f03cb1d4Srmind 
59f03cb1d4Srmind 	va_start(ap, fmt);
60f03cb1d4Srmind 	vasprintf(&msg, fmt, ap);
61f03cb1d4Srmind 	va_end(ap);
62f03cb1d4Srmind 
634e3d5046Srmind 	fprintf(stderr, "%s:%d:%d: %s", yyfilename,
644e3d5046Srmind 	    yylineno - (int)eol, yycolumn, msg);
654e3d5046Srmind 	if (!eol) {
664e3d5046Srmind 		size_t len = strlen(context);
673c7c5558Srmind 		char *dst = ecalloc(1, len * 4 + 1);
684e3d5046Srmind 
69f03cb1d4Srmind 		strvisx(dst, context, len, VIS_WHITE|VIS_CSTYLE);
704e3d5046Srmind 		fprintf(stderr, " near '%s'", dst);
714e3d5046Srmind 	}
724e3d5046Srmind 	fprintf(stderr, "\n");
73f03cb1d4Srmind 	exit(EXIT_FAILURE);
74f03cb1d4Srmind }
75f03cb1d4Srmind 
7637527ec6Srmind #define	CHECK_PARSER_FILE				\
7737527ec6Srmind 	if (yyparsetarget != NPFCTL_PARSE_FILE)		\
7837527ec6Srmind 		yyerror("rule must be in the group");
7937527ec6Srmind 
8037527ec6Srmind #define	CHECK_PARSER_STRING				\
8137527ec6Srmind 	if (yyparsetarget != NPFCTL_PARSE_STRING)	\
8237527ec6Srmind 		yyerror("invalid rule syntax");
8337527ec6Srmind 
84f03cb1d4Srmind %}
85f03cb1d4Srmind 
863b895110Schristos %token			ALG
87*a894e3f7Srmind %token			ALGO
88f03cb1d4Srmind %token			ALL
89f03cb1d4Srmind %token			ANY
90f03cb1d4Srmind %token			APPLY
91add921fbSrmind %token			ARROWBOTH
92add921fbSrmind %token			ARROWLEFT
93add921fbSrmind %token			ARROWRIGHT
94f03cb1d4Srmind %token			BLOCK
95820aad11Srmind %token			CDB
96f03cb1d4Srmind %token			CURLY_CLOSE
97f03cb1d4Srmind %token			CURLY_OPEN
98f03cb1d4Srmind %token			CODE
99f03cb1d4Srmind %token			COLON
100f03cb1d4Srmind %token			COMMA
101f03cb1d4Srmind %token			DEFAULT
102f03cb1d4Srmind %token			TDYNAMIC
103add921fbSrmind %token			TSTATIC
104f03cb1d4Srmind %token			EQ
105f03cb1d4Srmind %token			TFILE
106f03cb1d4Srmind %token			FLAGS
107f03cb1d4Srmind %token			FROM
108f03cb1d4Srmind %token			GROUP
109f03cb1d4Srmind %token			HASH
110f03cb1d4Srmind %token			ICMPTYPE
111f03cb1d4Srmind %token			ID
112f03cb1d4Srmind %token			IN
113348a4177Srmind %token			INET4
114f03cb1d4Srmind %token			INET6
115f03cb1d4Srmind %token			INTERFACE
116add921fbSrmind %token			MAP
117f03cb1d4Srmind %token			MINUS
118f03cb1d4Srmind %token			NAME
119*a894e3f7Srmind %token			NPT66
120f03cb1d4Srmind %token			ON
121f03cb1d4Srmind %token			OUT
122f03cb1d4Srmind %token			PAR_CLOSE
123f03cb1d4Srmind %token			PAR_OPEN
124f03cb1d4Srmind %token			PASS
125c6e77e2aSrmind %token			PCAP_FILTER
126f03cb1d4Srmind %token			PORT
127f03cb1d4Srmind %token			PROCEDURE
128f03cb1d4Srmind %token			PROTO
129f03cb1d4Srmind %token			FAMILY
130ba11b3c0Srmind %token			FINAL
13137527ec6Srmind %token			FORW
132f03cb1d4Srmind %token			RETURN
133f03cb1d4Srmind %token			RETURNICMP
134f03cb1d4Srmind %token			RETURNRST
1357b486642Srmind %token			RULESET
136f03cb1d4Srmind %token			SEPLINE
137f03cb1d4Srmind %token			SLASH
138ba11b3c0Srmind %token			STATEFUL
139f03cb1d4Srmind %token			TABLE
140f03cb1d4Srmind %token			TCP
141f03cb1d4Srmind %token			TO
142f03cb1d4Srmind %token			TREE
143f03cb1d4Srmind %token			TYPE
144afd9e22aSspz %token	<num>		ICMP
145afd9e22aSspz %token	<num>		ICMP6
146f03cb1d4Srmind 
147f03cb1d4Srmind %token	<num>		HEX
148f03cb1d4Srmind %token	<str>		IDENTIFIER
149f03cb1d4Srmind %token	<str>		IPV4ADDR
150f03cb1d4Srmind %token	<str>		IPV6ADDR
151f03cb1d4Srmind %token	<num>		NUM
15248a1ec7dSrmind %token	<fpnum>		FPNUM
153f03cb1d4Srmind %token	<str>		STRING
154f03cb1d4Srmind %token	<str>		TABLE_ID
155f03cb1d4Srmind %token	<str>		VAR_ID
156f03cb1d4Srmind 
157348a4177Srmind %type	<str>		addr, some_name, table_store
158348a4177Srmind %type	<str>		proc_param_val, opt_apply, ifname, on_ifname, ifref
159d1d2e2c9Srmind %type	<num>		port, opt_final, number, afamily, opt_family
160c6e77e2aSrmind %type	<num>		block_or_pass, rule_dir, group_dir, block_opts
161*a894e3f7Srmind %type	<num>		opt_stateful, icmp_type, table_type
162*a894e3f7Srmind %type	<num>		map_sd, map_algo, map_type
163348a4177Srmind %type	<var>		ifaddrs, addr_or_ifaddr, port_range, icmp_type_and_code
164f03cb1d4Srmind %type	<var>		filt_addr, addr_and_mask, tcp_flags, tcp_flags_and_mask
16548a1ec7dSrmind %type	<var>		procs, proc_call, proc_param_list, proc_param
166348a4177Srmind %type	<var>		element, list_elems, list, value
167add921fbSrmind %type	<addrport>	mapseg
168f03cb1d4Srmind %type	<filtopts>	filt_opts, all_or_filt_opts
169f03cb1d4Srmind %type	<optproto>	opt_proto
170c6e77e2aSrmind %type	<rulegroup>	group_opts
171f03cb1d4Srmind 
172f03cb1d4Srmind %union {
173f03cb1d4Srmind 	char *		str;
174f03cb1d4Srmind 	unsigned long	num;
17548a1ec7dSrmind 	double		fpnum;
176ec3d0e07Srmind 	npfvar_t *	var;
177add921fbSrmind 	addr_port_t	addrport;
178f03cb1d4Srmind 	filt_opts_t	filtopts;
179f03cb1d4Srmind 	opt_proto_t	optproto;
180f03cb1d4Srmind 	rule_group_t	rulegroup;
181f03cb1d4Srmind }
182f03cb1d4Srmind 
183f03cb1d4Srmind %%
184f03cb1d4Srmind 
185f03cb1d4Srmind input
18637527ec6Srmind 	: { CHECK_PARSER_FILE	} lines
18737527ec6Srmind 	| { CHECK_PARSER_STRING	} rule
188f03cb1d4Srmind 	;
189f03cb1d4Srmind 
190f03cb1d4Srmind lines
191f03cb1d4Srmind 	: line SEPLINE lines
192f03cb1d4Srmind 	| line
193f03cb1d4Srmind 	;
194f03cb1d4Srmind 
195f03cb1d4Srmind line
1968f6547d8Srmind 	: vardef
197f03cb1d4Srmind 	| table
198add921fbSrmind 	| map
199f03cb1d4Srmind 	| group
200f03cb1d4Srmind 	| rproc
2013b895110Schristos 	| alg
202f03cb1d4Srmind 	|
203f03cb1d4Srmind 	;
204f03cb1d4Srmind 
2058f6547d8Srmind alg
2068f6547d8Srmind 	: ALG STRING
2078f6547d8Srmind 	{
2088f6547d8Srmind 		npfctl_build_alg($2);
2098f6547d8Srmind 	}
2108f6547d8Srmind 	;
2118f6547d8Srmind 
2128f6547d8Srmind /*
2138f6547d8Srmind  * A value - an element or a list of elements.
2148f6547d8Srmind  * Can be assigned to a variable or used inline.
2158f6547d8Srmind  */
2168f6547d8Srmind 
2178f6547d8Srmind vardef
218348a4177Srmind 	: VAR_ID EQ value
219f03cb1d4Srmind 	{
220348a4177Srmind 		npfvar_add($3, $1);
221f03cb1d4Srmind 	}
222f03cb1d4Srmind 	;
223f03cb1d4Srmind 
2248f6547d8Srmind value
2258f6547d8Srmind 	: element
2268f6547d8Srmind 	| list
227f03cb1d4Srmind 	;
228f03cb1d4Srmind 
2298f6547d8Srmind list
230f03cb1d4Srmind 	: CURLY_OPEN list_elems CURLY_CLOSE
231348a4177Srmind 	{
232348a4177Srmind 		$$ = $2;
233348a4177Srmind 	}
234f03cb1d4Srmind 	;
235f03cb1d4Srmind 
236f03cb1d4Srmind list_elems
2378f6547d8Srmind 	: element COMMA list_elems
238348a4177Srmind 	{
239348a4177Srmind 		npfvar_add_elements($1, $3);
240348a4177Srmind 	}
2418f6547d8Srmind 	| element
242f03cb1d4Srmind 	;
243f03cb1d4Srmind 
2448f6547d8Srmind element
245f03cb1d4Srmind 	: IDENTIFIER
246f03cb1d4Srmind 	{
247348a4177Srmind 		$$ = npfvar_create_from_string(NPFVAR_IDENTIFIER, $1);
248f03cb1d4Srmind 	}
249f03cb1d4Srmind 	| STRING
250f03cb1d4Srmind 	{
251348a4177Srmind 		$$ = npfvar_create_from_string(NPFVAR_STRING, $1);
252f03cb1d4Srmind 	}
253f2174d83Schristos 	| number MINUS number
254ff24200fSchristos 	{
255348a4177Srmind 		$$ = npfctl_parse_port_range($1, $3);
256ff24200fSchristos 	}
257f2174d83Schristos 	| number
258f03cb1d4Srmind 	{
259348a4177Srmind 		$$ = npfvar_create_element(NPFVAR_NUM, &$1, sizeof($1));
260f03cb1d4Srmind 	}
261f03cb1d4Srmind 	| VAR_ID
262f03cb1d4Srmind 	{
263348a4177Srmind 		$$ = npfvar_create_from_string(NPFVAR_VAR_ID, $1);
264f03cb1d4Srmind 	}
265348a4177Srmind 	| TABLE_ID		{ $$ = npfctl_parse_table_id($1); }
266348a4177Srmind 	| ifaddrs		{ $$ = $1; }
267348a4177Srmind 	| addr_and_mask		{ $$ = $1; }
268f03cb1d4Srmind 	;
269f03cb1d4Srmind 
2708f6547d8Srmind /*
2718f6547d8Srmind  * Table definition.
2728f6547d8Srmind  */
2738f6547d8Srmind 
274f03cb1d4Srmind table
275f03cb1d4Srmind 	: TABLE TABLE_ID TYPE table_type table_store
276f03cb1d4Srmind 	{
277f03cb1d4Srmind 		npfctl_build_table($2, $4, $5);
278f03cb1d4Srmind 	}
279f03cb1d4Srmind 	;
280f03cb1d4Srmind 
281f03cb1d4Srmind table_type
282f03cb1d4Srmind 	: HASH		{ $$ = NPF_TABLE_HASH; }
283664900efSrmind 	| TREE		{ $$ = NPF_TABLE_TREE; }
284820aad11Srmind 	| CDB		{ $$ = NPF_TABLE_CDB; }
285f03cb1d4Srmind 	;
286f03cb1d4Srmind 
287f03cb1d4Srmind table_store
288f03cb1d4Srmind 	: TDYNAMIC	{ $$ = NULL; }
289f03cb1d4Srmind 	| TFILE STRING	{ $$ = $2; }
290f03cb1d4Srmind 	;
291f03cb1d4Srmind 
2928f6547d8Srmind /*
2938f6547d8Srmind  * Map definition.
2948f6547d8Srmind  */
2958f6547d8Srmind 
296add921fbSrmind map_sd
297add921fbSrmind 	: TSTATIC	{ $$ = NPFCTL_NAT_STATIC; }
298add921fbSrmind 	| TDYNAMIC	{ $$ = NPFCTL_NAT_DYNAMIC; }
299add921fbSrmind 	|		{ $$ = NPFCTL_NAT_DYNAMIC; }
300f03cb1d4Srmind 	;
301f03cb1d4Srmind 
302*a894e3f7Srmind map_algo
303*a894e3f7Srmind 	: ALGO NPT66	{ $$ = NPF_ALGO_NPT66; }
304*a894e3f7Srmind 	|		{ $$ = 0; }
305*a894e3f7Srmind 	;
306*a894e3f7Srmind 
307add921fbSrmind map_type
308add921fbSrmind 	: ARROWBOTH	{ $$ = NPF_NATIN | NPF_NATOUT; }
309add921fbSrmind 	| ARROWLEFT	{ $$ = NPF_NATIN; }
310add921fbSrmind 	| ARROWRIGHT	{ $$ = NPF_NATOUT; }
311add921fbSrmind 	;
312add921fbSrmind 
313add921fbSrmind mapseg
314348a4177Srmind 	: addr_or_ifaddr port_range
315f03cb1d4Srmind 	{
316add921fbSrmind 		$$.ap_netaddr = $1;
317add921fbSrmind 		$$.ap_portrange = $2;
318f03cb1d4Srmind 	}
319f03cb1d4Srmind 	;
320f03cb1d4Srmind 
321add921fbSrmind map
322*a894e3f7Srmind 	: MAP ifref map_sd map_algo mapseg map_type mapseg PASS filt_opts
323f03cb1d4Srmind 	{
324*a894e3f7Srmind 		npfctl_build_natseg($3, $6, $2, &$5, &$7, &$9, $4);
325f03cb1d4Srmind 	}
326*a894e3f7Srmind 	| MAP ifref map_sd map_algo mapseg map_type mapseg
327f03cb1d4Srmind 	{
328*a894e3f7Srmind 		npfctl_build_natseg($3, $6, $2, &$5, &$7, NULL, $4);
329f03cb1d4Srmind 	}
330c6e77e2aSrmind 	| MAP RULESET group_opts
3317b486642Srmind 	{
332d1d2e2c9Srmind 		npfctl_build_maprset($3.rg_name, $3.rg_attr, $3.rg_ifname);
3337b486642Srmind 	}
334f03cb1d4Srmind 	;
335f03cb1d4Srmind 
3368f6547d8Srmind /*
3378f6547d8Srmind  * Rule procedure definition and its parameters.
3388f6547d8Srmind  */
3398f6547d8Srmind 
340f03cb1d4Srmind rproc
341f03cb1d4Srmind 	: PROCEDURE STRING CURLY_OPEN procs CURLY_CLOSE
342f03cb1d4Srmind 	{
343f03cb1d4Srmind 		npfctl_build_rproc($2, $4);
344f03cb1d4Srmind 	}
345f03cb1d4Srmind 	;
346f03cb1d4Srmind 
347f03cb1d4Srmind procs
34848a1ec7dSrmind 	: proc_call SEPLINE procs
349f03cb1d4Srmind 	{
350f03cb1d4Srmind 		$$ = npfvar_add_elements($1, $3);
351f03cb1d4Srmind 	}
35248a1ec7dSrmind 	| proc_call	{ $$ = $1; }
35348a1ec7dSrmind 	;
35448a1ec7dSrmind 
35548a1ec7dSrmind proc_call
35648a1ec7dSrmind 	: IDENTIFIER COLON proc_param_list
35748a1ec7dSrmind 	{
35848a1ec7dSrmind 		proc_call_t pc;
35948a1ec7dSrmind 
3607c0a5ca2Srmind 		pc.pc_name = estrdup($1);
36148a1ec7dSrmind 		pc.pc_opts = $3;
362348a4177Srmind 
363348a4177Srmind 		$$ = npfvar_create_element(NPFVAR_PROC, &pc, sizeof(pc));
36448a1ec7dSrmind 	}
365f03cb1d4Srmind 	|		{ $$ = NULL; }
366f03cb1d4Srmind 	;
367f03cb1d4Srmind 
36848a1ec7dSrmind proc_param_list
36948a1ec7dSrmind 	: proc_param COMMA proc_param_list
370f03cb1d4Srmind 	{
37148a1ec7dSrmind 		$$ = npfvar_add_elements($1, $3);
37248a1ec7dSrmind 	}
37348a1ec7dSrmind 	| proc_param	{ $$ = $1; }
37448a1ec7dSrmind 	|		{ $$ = NULL; }
37548a1ec7dSrmind 	;
376f03cb1d4Srmind 
37748a1ec7dSrmind proc_param
37848a1ec7dSrmind 	: some_name proc_param_val
37948a1ec7dSrmind 	{
38048a1ec7dSrmind 		proc_param_t pp;
38148a1ec7dSrmind 
3827c0a5ca2Srmind 		pp.pp_param = estrdup($1);
3837c0a5ca2Srmind 		pp.pp_value = $2 ? estrdup($2) : NULL;
384348a4177Srmind 
385348a4177Srmind 		$$ = npfvar_create_element(NPFVAR_PROC_PARAM, &pp, sizeof(pp));
386f03cb1d4Srmind 	}
387f03cb1d4Srmind 	;
388f03cb1d4Srmind 
38948a1ec7dSrmind proc_param_val
39048a1ec7dSrmind 	: some_name	{ $$ = $1; }
391f2174d83Schristos 	| number	{ (void)asprintf(&$$, "%ld", $1); }
39248a1ec7dSrmind 	| FPNUM		{ (void)asprintf(&$$, "%lf", $1); }
393f03cb1d4Srmind 	|		{ $$ = NULL; }
394f03cb1d4Srmind 	;
395f03cb1d4Srmind 
3968f6547d8Srmind /*
3978f6547d8Srmind  * Group and dynamic ruleset definition.
3988f6547d8Srmind  */
3998f6547d8Srmind 
400f03cb1d4Srmind group
401c6e77e2aSrmind 	: GROUP group_opts
402f03cb1d4Srmind 	{
403348a4177Srmind 		/* Build a group.  Increase the nesting level. */
404c6e77e2aSrmind 		npfctl_build_group($2.rg_name, $2.rg_attr,
405d1d2e2c9Srmind 		    $2.rg_ifname, $2.rg_default);
406f03cb1d4Srmind 	}
40737527ec6Srmind 	  ruleset_block
40837527ec6Srmind 	{
40937527ec6Srmind 		/* Decrease the nesting level. */
41037527ec6Srmind 		npfctl_build_group_end();
41137527ec6Srmind 	}
412f03cb1d4Srmind 	;
413f03cb1d4Srmind 
4147b486642Srmind ruleset
415c6e77e2aSrmind 	: RULESET group_opts
4167b486642Srmind 	{
4177b486642Srmind 		/* Ruleset is a dynamic group. */
418c6e77e2aSrmind 		npfctl_build_group($2.rg_name, $2.rg_attr | NPF_RULE_DYNAMIC,
419d1d2e2c9Srmind 		    $2.rg_ifname, $2.rg_default);
4207b486642Srmind 		npfctl_build_group_end();
4217b486642Srmind 	}
422f03cb1d4Srmind 	;
423f03cb1d4Srmind 
424c6e77e2aSrmind group_dir
425c6e77e2aSrmind 	: FORW		{ $$ = NPF_RULE_FORW; }
426c6e77e2aSrmind 	| rule_dir
427c6e77e2aSrmind 	;
428c6e77e2aSrmind 
429c6e77e2aSrmind group_opts
430f03cb1d4Srmind 	: DEFAULT
431f03cb1d4Srmind 	{
43237527ec6Srmind 		memset(&$$, 0, sizeof(rule_group_t));
43337527ec6Srmind 		$$.rg_default = true;
434f03cb1d4Srmind 	}
435d1d2e2c9Srmind 	| STRING group_dir on_ifname
436f03cb1d4Srmind 	{
43737527ec6Srmind 		memset(&$$, 0, sizeof(rule_group_t));
438c6e77e2aSrmind 		$$.rg_name = $1;
439c6e77e2aSrmind 		$$.rg_attr = $2;
440d1d2e2c9Srmind 		$$.rg_ifname = $3;
441f03cb1d4Srmind 	}
442f03cb1d4Srmind 	;
443f03cb1d4Srmind 
44437527ec6Srmind ruleset_block
4457b486642Srmind 	: CURLY_OPEN ruleset_def CURLY_CLOSE
446f03cb1d4Srmind 	;
447f03cb1d4Srmind 
4487b486642Srmind ruleset_def
4497b486642Srmind 	: rule_group SEPLINE ruleset_def
45037527ec6Srmind 	| rule_group
451f03cb1d4Srmind 	;
452f03cb1d4Srmind 
45337527ec6Srmind rule_group
45437527ec6Srmind 	: rule
45537527ec6Srmind 	| group
4567b486642Srmind 	| ruleset
45737527ec6Srmind 	|
45885aa89dfSrmind 	;
45937527ec6Srmind 
4608f6547d8Srmind /*
4618f6547d8Srmind  * Rule and misc.
4628f6547d8Srmind  */
4638f6547d8Srmind 
464f03cb1d4Srmind rule
465d1d2e2c9Srmind 	: block_or_pass opt_stateful rule_dir opt_final on_ifname
466ec3d0e07Srmind 	  opt_family opt_proto all_or_filt_opts opt_apply
467f03cb1d4Srmind 	{
468ba11b3c0Srmind 		npfctl_build_rule($1 | $2 | $3 | $4, $5,
469c6e77e2aSrmind 		    $6, &$7, &$8, NULL, $9);
470c6e77e2aSrmind 	}
471d1d2e2c9Srmind 	| block_or_pass opt_stateful rule_dir opt_final on_ifname
472c6e77e2aSrmind 	  PCAP_FILTER STRING opt_apply
473c6e77e2aSrmind 	{
474c6e77e2aSrmind 		npfctl_build_rule($1 | $2 | $3 | $4, $5,
475c6e77e2aSrmind 		    AF_UNSPEC, NULL, NULL, $7, $8);
476f03cb1d4Srmind 	}
477f03cb1d4Srmind 	;
478f03cb1d4Srmind 
479f03cb1d4Srmind block_or_pass
480f03cb1d4Srmind 	: BLOCK block_opts	{ $$ = $2; }
481f03cb1d4Srmind 	| PASS			{ $$ = NPF_RULE_PASS; }
482f03cb1d4Srmind 	;
483f03cb1d4Srmind 
484f03cb1d4Srmind rule_dir
485f03cb1d4Srmind 	: IN			{ $$ = NPF_RULE_IN; }
486f03cb1d4Srmind 	| OUT			{ $$ = NPF_RULE_OUT; }
487f03cb1d4Srmind 	|			{ $$ = NPF_RULE_IN | NPF_RULE_OUT; }
488f03cb1d4Srmind 	;
489f03cb1d4Srmind 
490ba11b3c0Srmind opt_final
491ba11b3c0Srmind 	: FINAL			{ $$ = NPF_RULE_FINAL; }
492f03cb1d4Srmind 	|			{ $$ = 0; }
493f03cb1d4Srmind 	;
494f03cb1d4Srmind 
495d1d2e2c9Srmind on_ifname
496348a4177Srmind 	: ON ifref		{ $$ = $2; }
497d1d2e2c9Srmind 	|			{ $$ = NULL; }
498f03cb1d4Srmind 	;
499f03cb1d4Srmind 
500ec3d0e07Srmind afamily
501348a4177Srmind 	: INET4			{ $$ = AF_INET; }
502ec3d0e07Srmind 	| INET6			{ $$ = AF_INET6; }
503ec3d0e07Srmind 	;
504ec3d0e07Srmind 
505f75d4435Srmind opt_family
506ec3d0e07Srmind 	: FAMILY afamily	{ $$ = $2; }
507f75d4435Srmind 	|			{ $$ = AF_UNSPEC; }
508f03cb1d4Srmind 	;
509f03cb1d4Srmind 
510f03cb1d4Srmind opt_proto
511f03cb1d4Srmind 	: PROTO TCP tcp_flags_and_mask
512f03cb1d4Srmind 	{
513f03cb1d4Srmind 		$$.op_proto = IPPROTO_TCP;
514f03cb1d4Srmind 		$$.op_opts = $3;
515f03cb1d4Srmind 	}
516f03cb1d4Srmind 	| PROTO ICMP icmp_type_and_code
517f03cb1d4Srmind 	{
518f03cb1d4Srmind 		$$.op_proto = IPPROTO_ICMP;
519f03cb1d4Srmind 		$$.op_opts = $3;
520f03cb1d4Srmind 	}
521afd9e22aSspz 	| PROTO ICMP6 icmp_type_and_code
522afd9e22aSspz 	{
523afd9e22aSspz 		$$.op_proto = IPPROTO_ICMPV6;
524afd9e22aSspz 		$$.op_opts = $3;
525afd9e22aSspz 	}
526f75d4435Srmind 	| PROTO some_name
527f03cb1d4Srmind 	{
528f75d4435Srmind 		$$.op_proto = npfctl_protono($2);
529f75d4435Srmind 		$$.op_opts = NULL;
530f75d4435Srmind 	}
531f2174d83Schristos 	| PROTO number
532f75d4435Srmind 	{
533f75d4435Srmind 		$$.op_proto = $2;
534f03cb1d4Srmind 		$$.op_opts = NULL;
535f03cb1d4Srmind 	}
536f03cb1d4Srmind 	|
537f03cb1d4Srmind 	{
538f03cb1d4Srmind 		$$.op_proto = -1;
539f03cb1d4Srmind 		$$.op_opts = NULL;
540f03cb1d4Srmind 	}
541f03cb1d4Srmind 	;
542f03cb1d4Srmind 
543f03cb1d4Srmind all_or_filt_opts
544f03cb1d4Srmind 	: ALL
545f03cb1d4Srmind 	{
546add921fbSrmind 		$$.fo_from.ap_netaddr = NULL;
547add921fbSrmind 		$$.fo_from.ap_portrange = NULL;
548add921fbSrmind 		$$.fo_to.ap_netaddr = NULL;
549add921fbSrmind 		$$.fo_to.ap_portrange = NULL;
550f03cb1d4Srmind 	}
551f03cb1d4Srmind 	| filt_opts	{ $$ = $1; }
552f03cb1d4Srmind 	;
553f03cb1d4Srmind 
554ba11b3c0Srmind opt_stateful
555f75d4435Srmind 	: STATEFUL	{ $$ = NPF_RULE_STATEFUL; }
556f03cb1d4Srmind 	|		{ $$ = 0; }
557f03cb1d4Srmind 	;
558f03cb1d4Srmind 
559f03cb1d4Srmind opt_apply
560f03cb1d4Srmind 	: APPLY STRING	{ $$ = $2; }
561f03cb1d4Srmind 	|		{ $$ = NULL; }
562f03cb1d4Srmind 	;
563f03cb1d4Srmind 
564f03cb1d4Srmind block_opts
565f03cb1d4Srmind 	: RETURNRST	{ $$ = NPF_RULE_RETRST; }
566f03cb1d4Srmind 	| RETURNICMP	{ $$ = NPF_RULE_RETICMP; }
567f03cb1d4Srmind 	| RETURN	{ $$ = NPF_RULE_RETRST | NPF_RULE_RETICMP; }
568f03cb1d4Srmind 	|		{ $$ = 0; }
569f03cb1d4Srmind 	;
570f03cb1d4Srmind 
571f03cb1d4Srmind filt_opts
572f03cb1d4Srmind 	: FROM filt_addr port_range TO filt_addr port_range
573f03cb1d4Srmind 	{
574add921fbSrmind 		$$.fo_from.ap_netaddr = $2;
575add921fbSrmind 		$$.fo_from.ap_portrange = $3;
576add921fbSrmind 		$$.fo_to.ap_netaddr = $5;
577add921fbSrmind 		$$.fo_to.ap_portrange = $6;
578f03cb1d4Srmind 	}
579f03cb1d4Srmind 	| FROM filt_addr port_range
580f03cb1d4Srmind 	{
581add921fbSrmind 		$$.fo_from.ap_netaddr = $2;
582add921fbSrmind 		$$.fo_from.ap_portrange = $3;
583add921fbSrmind 		$$.fo_to.ap_netaddr = NULL;
584add921fbSrmind 		$$.fo_to.ap_portrange = NULL;
585f03cb1d4Srmind 	}
586f03cb1d4Srmind 	| TO filt_addr port_range
587f03cb1d4Srmind 	{
588add921fbSrmind 		$$.fo_from.ap_netaddr = NULL;
589add921fbSrmind 		$$.fo_from.ap_portrange = NULL;
590add921fbSrmind 		$$.fo_to.ap_netaddr = $2;
591add921fbSrmind 		$$.fo_to.ap_portrange = $3;
592f03cb1d4Srmind 	}
593f03cb1d4Srmind 	;
594f03cb1d4Srmind 
595f03cb1d4Srmind filt_addr
596348a4177Srmind 	: addr_or_ifaddr	{ $$ = $1; }
597f03cb1d4Srmind 	| TABLE_ID		{ $$ = npfctl_parse_table_id($1); }
598f03cb1d4Srmind 	| ANY			{ $$ = NULL; }
599f03cb1d4Srmind 	;
600f03cb1d4Srmind 
601f03cb1d4Srmind addr_and_mask
602f2174d83Schristos 	: addr SLASH number
603f03cb1d4Srmind 	{
604f03cb1d4Srmind 		$$ = npfctl_parse_fam_addr_mask($1, NULL, &$3);
605f03cb1d4Srmind 	}
606f03cb1d4Srmind 	| addr SLASH addr
607f03cb1d4Srmind 	{
608f03cb1d4Srmind 		$$ = npfctl_parse_fam_addr_mask($1, $3, NULL);
609f03cb1d4Srmind 	}
610f03cb1d4Srmind 	| addr
611f03cb1d4Srmind 	{
612f03cb1d4Srmind 		$$ = npfctl_parse_fam_addr_mask($1, NULL, NULL);
613f03cb1d4Srmind 	}
614f03cb1d4Srmind 	;
615f03cb1d4Srmind 
616348a4177Srmind addr_or_ifaddr
617f75d4435Srmind 	: addr_and_mask
618f75d4435Srmind 	{
619f75d4435Srmind 		assert($1 != NULL);
620f75d4435Srmind 		$$ = $1;
621f75d4435Srmind 	}
622348a4177Srmind 	| ifaddrs
6238094cc3dSrmind 	{
624ec3d0e07Srmind 		ifnet_addr_t *ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0);
625ec3d0e07Srmind 		$$ = ifna->ifna_addrs;
6268094cc3dSrmind 	}
6278094cc3dSrmind 	| VAR_ID
6288094cc3dSrmind 	{
6298094cc3dSrmind 		npfvar_t *vp = npfvar_lookup($1);
630f0ae964eSchristos 		int type = npfvar_get_type(vp, 0);
631ec3d0e07Srmind 		ifnet_addr_t *ifna;
6328094cc3dSrmind 
633f0ae964eSchristos again:
6348094cc3dSrmind 		switch (type) {
635f0ae964eSchristos 		case NPFVAR_IDENTIFIER:
636f0ae964eSchristos 		case NPFVAR_STRING:
637f0ae964eSchristos 			vp = npfctl_parse_ifnet(npfvar_expand_string(vp),
638f0ae964eSchristos 			    AF_UNSPEC);
639f0ae964eSchristos 			type = npfvar_get_type(vp, 0);
640f0ae964eSchristos 			goto again;
6418094cc3dSrmind 		case NPFVAR_FAM:
6428094cc3dSrmind 			$$ = vp;
6438094cc3dSrmind 			break;
644ec3d0e07Srmind 		case NPFVAR_INTERFACE:
645ec3d0e07Srmind 			ifna = npfvar_get_data(vp, type, 0);
646ec3d0e07Srmind 			$$ = ifna->ifna_addrs;
647ec3d0e07Srmind 			break;
6488094cc3dSrmind 		case -1:
649ec3d0e07Srmind 			yyerror("undefined variable '%s'", $1);
6508094cc3dSrmind 			break;
6518094cc3dSrmind 		default:
652ec3d0e07Srmind 			yyerror("wrong variable '%s' type '%s' for address "
653ec3d0e07Srmind 			    "or interface", $1, npfvar_type(type));
6548094cc3dSrmind 			break;
6558094cc3dSrmind 		}
6568094cc3dSrmind 	}
657f03cb1d4Srmind 	;
658f03cb1d4Srmind 
659f03cb1d4Srmind addr
660f03cb1d4Srmind 	: IPV4ADDR	{ $$ = $1; }
661f03cb1d4Srmind 	| IPV6ADDR	{ $$ = $1; }
662f03cb1d4Srmind 	;
663f03cb1d4Srmind 
664f03cb1d4Srmind port_range
665f03cb1d4Srmind 	: PORT port		/* just port */
666f03cb1d4Srmind 	{
667f03cb1d4Srmind 		$$ = npfctl_parse_port_range($2, $2);
668f03cb1d4Srmind 	}
669add921fbSrmind 	| PORT port MINUS port	/* port from-to */
670f03cb1d4Srmind 	{
671f03cb1d4Srmind 		$$ = npfctl_parse_port_range($2, $4);
672f03cb1d4Srmind 	}
673add921fbSrmind 	| PORT VAR_ID
674add921fbSrmind 	{
675ff24200fSchristos 		$$ = npfctl_parse_port_range_variable($2);
676ff24200fSchristos 	}
677f03cb1d4Srmind 	|
678f03cb1d4Srmind 	{
679f03cb1d4Srmind 		$$ = NULL;
680f03cb1d4Srmind 	}
681f03cb1d4Srmind 	;
682f03cb1d4Srmind 
683f03cb1d4Srmind port
684f2174d83Schristos 	: number	{ $$ = $1; }
685f03cb1d4Srmind 	| IDENTIFIER	{ $$ = npfctl_portno($1); }
686bd928debSchristos 	| STRING	{ $$ = npfctl_portno($1); }
687f03cb1d4Srmind 	;
688f03cb1d4Srmind 
689f03cb1d4Srmind icmp_type_and_code
690f03cb1d4Srmind 	: ICMPTYPE icmp_type
691f03cb1d4Srmind 	{
692afd9e22aSspz 		$$ = npfctl_parse_icmp($<num>0, $2, -1);
693f03cb1d4Srmind 	}
694f2174d83Schristos 	| ICMPTYPE icmp_type CODE number
695f03cb1d4Srmind 	{
696afd9e22aSspz 		$$ = npfctl_parse_icmp($<num>0, $2, $4);
697f03cb1d4Srmind 	}
698f03cb1d4Srmind 	| ICMPTYPE icmp_type CODE IDENTIFIER
699f03cb1d4Srmind 	{
700ec3d0e07Srmind 		$$ = npfctl_parse_icmp($<num>0, $2,
701ec3d0e07Srmind 		    npfctl_icmpcode($<num>0, $2, $4));
702f03cb1d4Srmind 	}
703f03cb1d4Srmind 	| ICMPTYPE icmp_type CODE VAR_ID
704f03cb1d4Srmind 	{
705f03cb1d4Srmind 		char *s = npfvar_expand_string(npfvar_lookup($4));
706ec3d0e07Srmind 		$$ = npfctl_parse_icmp($<num>0, $2,
707ec3d0e07Srmind 		    npfctl_icmpcode($<num>0, $2, s));
708f03cb1d4Srmind 	}
70911243735Srmind 	|		{ $$ = NULL; }
710f03cb1d4Srmind 	;
711f03cb1d4Srmind 
712f03cb1d4Srmind tcp_flags_and_mask
713f03cb1d4Srmind 	: FLAGS tcp_flags SLASH tcp_flags
714f03cb1d4Srmind 	{
715f03cb1d4Srmind 		npfvar_add_elements($2, $4);
716f03cb1d4Srmind 		$$ = $2;
717f03cb1d4Srmind 	}
718f03cb1d4Srmind 	| FLAGS tcp_flags
719f03cb1d4Srmind 	{
720f03cb1d4Srmind 		char *s = npfvar_get_data($2, NPFVAR_TCPFLAG, 0);
721f03cb1d4Srmind 		npfvar_add_elements($2, npfctl_parse_tcpflag(s));
722f03cb1d4Srmind 		$$ = $2;
723f03cb1d4Srmind 	}
724f03cb1d4Srmind 	|		{ $$ = NULL; }
725f03cb1d4Srmind 	;
726f03cb1d4Srmind 
727f03cb1d4Srmind tcp_flags
728f03cb1d4Srmind 	: IDENTIFIER	{ $$ = npfctl_parse_tcpflag($1); }
729f03cb1d4Srmind 	;
730f03cb1d4Srmind 
731f03cb1d4Srmind icmp_type
732f2174d83Schristos 	: number	{ $$ = $1; }
733afd9e22aSspz 	| IDENTIFIER	{ $$ = npfctl_icmptype($<num>-1, $1); }
734f03cb1d4Srmind 	| VAR_ID
735f03cb1d4Srmind 	{
736f03cb1d4Srmind 		char *s = npfvar_expand_string(npfvar_lookup($1));
737afd9e22aSspz 		$$ = npfctl_icmptype($<num>-1, s);
738f03cb1d4Srmind 	}
739f03cb1d4Srmind 	;
740f03cb1d4Srmind 
741d1d2e2c9Srmind ifname
742f75d4435Srmind 	: some_name
743f03cb1d4Srmind 	{
744d1d2e2c9Srmind 		npfctl_note_interface($1);
745d1d2e2c9Srmind 		$$ = $1;
746f03cb1d4Srmind 	}
747f03cb1d4Srmind 	| VAR_ID
748f03cb1d4Srmind 	{
749f03cb1d4Srmind 		npfvar_t *vp = npfvar_lookup($1);
750ff24200fSchristos 		const int type = npfvar_get_type(vp, 0);
751ec3d0e07Srmind 		ifnet_addr_t *ifna;
752f03cb1d4Srmind 
753f03cb1d4Srmind 		switch (type) {
754f03cb1d4Srmind 		case NPFVAR_STRING:
755ec3d0e07Srmind 		case NPFVAR_IDENTIFIER:
756d1d2e2c9Srmind 			$$ = npfvar_expand_string(vp);
757f03cb1d4Srmind 			break;
758ec3d0e07Srmind 		case NPFVAR_INTERFACE:
759ec3d0e07Srmind 			ifna = npfvar_get_data(vp, type, 0);
760d1d2e2c9Srmind 			$$ = ifna->ifna_name;
761ec3d0e07Srmind 			break;
762f03cb1d4Srmind 		case -1:
763f03cb1d4Srmind 			yyerror("undefined variable '%s' for interface", $1);
764f03cb1d4Srmind 			break;
765f03cb1d4Srmind 		default:
766f03cb1d4Srmind 			yyerror("wrong variable '%s' type '%s' for interface",
767f03cb1d4Srmind 			    $1, npfvar_type(type));
768f03cb1d4Srmind 			break;
769f03cb1d4Srmind 		}
770d1d2e2c9Srmind 		npfctl_note_interface($$);
771f03cb1d4Srmind 	}
772f03cb1d4Srmind 	;
773f03cb1d4Srmind 
774348a4177Srmind ifaddrs
775348a4177Srmind 	: afamily PAR_OPEN ifname PAR_CLOSE
776348a4177Srmind 	{
777348a4177Srmind 		$$ = npfctl_parse_ifnet($3, $1);
778348a4177Srmind 	}
779348a4177Srmind 	;
780348a4177Srmind 
781348a4177Srmind ifref
782348a4177Srmind 	: ifname
783348a4177Srmind 	| ifaddrs
784348a4177Srmind 	{
785348a4177Srmind 		ifnet_addr_t *ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0);
786348a4177Srmind 		npfctl_note_interface(ifna->ifna_name);
787348a4177Srmind 		$$ = ifna->ifna_name;
788348a4177Srmind 	}
789348a4177Srmind 	;
790348a4177Srmind 
791f2174d83Schristos number
792f2174d83Schristos 	: HEX		{ $$ = $1; }
793f2174d83Schristos 	| NUM		{ $$ = $1; }
794f2174d83Schristos 	;
795f2174d83Schristos 
796f75d4435Srmind some_name
797f03cb1d4Srmind 	: IDENTIFIER	{ $$ = $1; }
798f03cb1d4Srmind 	| STRING	{ $$ = $1; }
799f03cb1d4Srmind 	;
800f03cb1d4Srmind 
801f03cb1d4Srmind %%
802