xref: /netbsd-src/usr.sbin/npf/npfctl/npf_parse.y (revision b899bfd96fd2cbaf2befc9ce4aaed9b9c230837a)
1d3c56566Srmind /*-
2*b899bfd9Srmind  * Copyright (c) 2011-2020 The NetBSD Foundation, Inc.
3d3c56566Srmind  * All rights reserved.
4d3c56566Srmind  *
5d3c56566Srmind  * This code is derived from software contributed to The NetBSD Foundation
6f797733aSrmind  * by Martin Husemann, Christos Zoulas and Mindaugas Rasiukevicius.
7d3c56566Srmind  *
8d3c56566Srmind  * Redistribution and use in source and binary forms, with or without
9d3c56566Srmind  * modification, are permitted provided that the following conditions
10d3c56566Srmind  * are met:
11d3c56566Srmind  * 1. Redistributions of source code must retain the above copyright
12d3c56566Srmind  *    notice, this list of conditions and the following disclaimer.
13d3c56566Srmind  * 2. Redistributions in binary form must reproduce the above copyright
14d3c56566Srmind  *    notice, this list of conditions and the following disclaimer in the
15d3c56566Srmind  *    documentation and/or other materials provided with the distribution.
16d3c56566Srmind  *
17d3c56566Srmind  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18d3c56566Srmind  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19d3c56566Srmind  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20d3c56566Srmind  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21d3c56566Srmind  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22d3c56566Srmind  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23d3c56566Srmind  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24d3c56566Srmind  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25d3c56566Srmind  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26d3c56566Srmind  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27d3c56566Srmind  * POSSIBILITY OF SUCH DAMAGE.
28d3c56566Srmind  */
29d3c56566Srmind 
30d3c56566Srmind %{
31d3c56566Srmind 
32d3c56566Srmind #include <err.h>
33d3c56566Srmind #include <netdb.h>
34a668c47eSjoerg #include <stdio.h>
35a668c47eSjoerg #include <stdlib.h>
36a668c47eSjoerg #include <string.h>
3760a0ec10Srmind #ifdef __NetBSD__
38a668c47eSjoerg #include <vis.h>
3960a0ec10Srmind #endif
40d3c56566Srmind 
41d3c56566Srmind #include "npfctl.h"
42d3c56566Srmind 
4363f44833Srmind #define	YYSTACKSIZE	4096
4463f44833Srmind 
4504cb50acSrmind int			yystarttoken;
46d3c56566Srmind const char *		yyfilename;
47d3c56566Srmind 
48d3c56566Srmind extern int		yylineno, yycolumn;
4904cb50acSrmind extern int		yylex(int);
50d3c56566Srmind 
51d3c56566Srmind void
yyerror(const char * fmt,...)52d3c56566Srmind yyerror(const char *fmt, ...)
53d3c56566Srmind {
54d3c56566Srmind 	extern int yyleng;
55d3c56566Srmind 	extern char *yytext;
56d3c56566Srmind 
577b016567Srmind 	char *msg, *context = estrndup(yytext, yyleng);
58e7cdd21fSrmind 	bool eol = (*context == '\n');
59d3c56566Srmind 	va_list ap;
60d3c56566Srmind 
61d3c56566Srmind 	va_start(ap, fmt);
62d3c56566Srmind 	vasprintf(&msg, fmt, ap);
63d3c56566Srmind 	va_end(ap);
64d3c56566Srmind 
65e7cdd21fSrmind 	fprintf(stderr, "%s:%d:%d: %s", yyfilename,
66e7cdd21fSrmind 	    yylineno - (int)eol, yycolumn, msg);
67e7cdd21fSrmind 	if (!eol) {
6860a0ec10Srmind #ifdef __NetBSD__
69e7cdd21fSrmind 		size_t len = strlen(context);
70b4a9940eSrmind 		char *dst = ecalloc(1, len * 4 + 1);
71e7cdd21fSrmind 
72d3c56566Srmind 		strvisx(dst, context, len, VIS_WHITE|VIS_CSTYLE);
73786e7497Skre 		context = dst;
7460a0ec10Srmind #endif
7560a0ec10Srmind 		fprintf(stderr, " near '%s'", context);
76e7cdd21fSrmind 	}
77e7cdd21fSrmind 	fprintf(stderr, "\n");
78d3c56566Srmind 	exit(EXIT_FAILURE);
79d3c56566Srmind }
80d3c56566Srmind 
81d3c56566Srmind %}
82d3c56566Srmind 
833d9a792dSrmind /*
843d9a792dSrmind  * No conflicts allowed.  Keep it this way.
853d9a792dSrmind  */
863d9a792dSrmind %expect 0
873d9a792dSrmind %expect-rr 0
883d9a792dSrmind 
8904cb50acSrmind /*
9004cb50acSrmind  * Depending on the mode of operation, set a different start symbol.
9104cb50acSrmind  * Workaround yacc limitation by passing the start token.
9204cb50acSrmind  */
9304cb50acSrmind %start input
9404cb50acSrmind %token RULE_ENTRY_TOKEN MAP_ENTRY_TOKEN
9504cb50acSrmind %lex-param { int yystarttoken }
9604cb50acSrmind 
9704cb50acSrmind /*
9804cb50acSrmind  * General tokens.
9904cb50acSrmind  */
100bc0f55deSchristos %token			ALG
101068cee29Srmind %token			ALGO
102d3c56566Srmind %token			ALL
103d3c56566Srmind %token			ANY
104d3c56566Srmind %token			APPLY
1057a3e0c21Srmind %token			ARROWBOTH
1067a3e0c21Srmind %token			ARROWLEFT
1077a3e0c21Srmind %token			ARROWRIGHT
108d3c56566Srmind %token			BLOCK
109ffcdc4afSrmind %token			CDB
1103d9a792dSrmind %token			CONST
111d3c56566Srmind %token			CURLY_CLOSE
112d3c56566Srmind %token			CURLY_OPEN
113d3c56566Srmind %token			CODE
114d3c56566Srmind %token			COLON
115d3c56566Srmind %token			COMMA
116d3c56566Srmind %token			DEFAULT
117d3c56566Srmind %token			TDYNAMIC
1187a3e0c21Srmind %token			TSTATIC
119d3c56566Srmind %token			EQ
1208334b9bcSrmind %token			EXCL_MARK
121d3c56566Srmind %token			TFILE
122d3c56566Srmind %token			FLAGS
123d3c56566Srmind %token			FROM
124d3c56566Srmind %token			GROUP
125d3c56566Srmind %token			HASH
126d3c56566Srmind %token			ICMPTYPE
127d3c56566Srmind %token			ID
1283d9a792dSrmind %token			IFADDRS
129d3c56566Srmind %token			IN
130d116583eSrmind %token			INET4
131d3c56566Srmind %token			INET6
132d3c56566Srmind %token			INTERFACE
133*b899bfd9Srmind %token			INVALID
1343d9a792dSrmind %token			IPHASH
1353d9a792dSrmind %token			IPSET
1363d9a792dSrmind %token			LPM
1377a3e0c21Srmind %token			MAP
138bd05c4c4Srmind %token			NO_PORTS
139d3c56566Srmind %token			MINUS
140d3c56566Srmind %token			NAME
1413d9a792dSrmind %token			NETMAP
142068cee29Srmind %token			NPT66
143d3c56566Srmind %token			ON
144a08b1ebdSchristos %token			OFF
145d3c56566Srmind %token			OUT
146d3c56566Srmind %token			PAR_CLOSE
147d3c56566Srmind %token			PAR_OPEN
148d3c56566Srmind %token			PASS
149f797733aSrmind %token			PCAP_FILTER
150d3c56566Srmind %token			PORT
151d3c56566Srmind %token			PROCEDURE
152d3c56566Srmind %token			PROTO
153d3c56566Srmind %token			FAMILY
154ac69c0c3Srmind %token			FINAL
1550e218254Srmind %token			FORW
156d3c56566Srmind %token			RETURN
157d3c56566Srmind %token			RETURNICMP
158d3c56566Srmind %token			RETURNRST
1593d9a792dSrmind %token			ROUNDROBIN
160543d2971Srmind %token			RULESET
161d3c56566Srmind %token			SEPLINE
162a08b1ebdSchristos %token			SET
163d3c56566Srmind %token			SLASH
164ac69c0c3Srmind %token			STATEFUL
165dadc88e3Srmind %token			STATEFUL_ALL
166d3c56566Srmind %token			TABLE
167d3c56566Srmind %token			TCP
168d3c56566Srmind %token			TO
169d3c56566Srmind %token			TREE
170d3c56566Srmind %token			TYPE
1717cf84a83Sspz %token	<num>		ICMP
1727cf84a83Sspz %token	<num>		ICMP6
173d3c56566Srmind 
174d3c56566Srmind %token	<num>		HEX
175d3c56566Srmind %token	<str>		IDENTIFIER
176d3c56566Srmind %token	<str>		IPV4ADDR
177d3c56566Srmind %token	<str>		IPV6ADDR
178d3c56566Srmind %token	<num>		NUM
1798c6e21bfSrmind %token	<fpnum>		FPNUM
180d3c56566Srmind %token	<str>		STRING
181dadc88e3Srmind %token	<str>		PARAM
182d3c56566Srmind %token	<str>		TABLE_ID
183d3c56566Srmind %token	<str>		VAR_ID
184d3c56566Srmind 
1853d9a792dSrmind %type	<str>		addr some_name table_store dynamic_ifaddrs
1863d9a792dSrmind %type	<str>		proc_param_val opt_apply ifname on_ifname ifref
1873d9a792dSrmind %type	<num>		port opt_final number afamily opt_family
1883d9a792dSrmind %type	<num>		block_or_pass rule_dir group_dir block_opts
1893d9a792dSrmind %type	<num>		maybe_not opt_stateful icmp_type table_type
1903d9a792dSrmind %type	<num>		map_sd map_algo map_flags map_type
191dadc88e3Srmind %type	<num>		param_val
192*b899bfd9Srmind %type	<var>		static_ifaddrs filt_addr_element
193*b899bfd9Srmind %type	<var>		filt_port filt_port_list port_range icmp_type_and_code
1943d9a792dSrmind %type	<var>		filt_addr addr_and_mask tcp_flags tcp_flags_and_mask
1953d9a792dSrmind %type	<var>		procs proc_call proc_param_list proc_param
196*b899bfd9Srmind %type	<var>		element list_elems list value filt_addr_list
197*b899bfd9Srmind %type	<var>		opt_proto proto proto_elems
1987a3e0c21Srmind %type	<addrport>	mapseg
1993d9a792dSrmind %type	<filtopts>	filt_opts all_or_filt_opts
200*b899bfd9Srmind %type	<optproto>	rawproto
201f797733aSrmind %type	<rulegroup>	group_opts
202d3c56566Srmind 
203d3c56566Srmind %union {
204d3c56566Srmind 	char *		str;
205d3c56566Srmind 	unsigned long	num;
2068c6e21bfSrmind 	double		fpnum;
2075111d7eaSrmind 	npfvar_t *	var;
2087a3e0c21Srmind 	addr_port_t	addrport;
209d3c56566Srmind 	filt_opts_t	filtopts;
210d3c56566Srmind 	opt_proto_t	optproto;
211d3c56566Srmind 	rule_group_t	rulegroup;
212d3c56566Srmind }
213d3c56566Srmind 
214d3c56566Srmind %%
215d3c56566Srmind 
216d3c56566Srmind input
21704cb50acSrmind 	: lines
21804cb50acSrmind 	| RULE_ENTRY_TOKEN	rule
21904cb50acSrmind 	| MAP_ENTRY_TOKEN	map
220d3c56566Srmind 	;
221d3c56566Srmind 
222d3c56566Srmind lines
2234ec7cf26Sriastradh 	: lines SEPLINE line
224d3c56566Srmind 	| line
225d3c56566Srmind 	;
226d3c56566Srmind 
227d3c56566Srmind line
2283fb1890bSrmind 	: vardef
229d3c56566Srmind 	| table
2307a3e0c21Srmind 	| map
231d3c56566Srmind 	| group
232d3c56566Srmind 	| rproc
233bc0f55deSchristos 	| alg
234a08b1ebdSchristos 	| set
235d3c56566Srmind 	|
236d3c56566Srmind 	;
237d3c56566Srmind 
2383fb1890bSrmind alg
2393fb1890bSrmind 	: ALG STRING
2403fb1890bSrmind 	{
2413fb1890bSrmind 		npfctl_build_alg($2);
2423fb1890bSrmind 	}
2433fb1890bSrmind 	;
2443fb1890bSrmind 
245dadc88e3Srmind param_val
246dadc88e3Srmind 	: number	{ $$ = $1; }
247dadc88e3Srmind 	| ON		{ $$ = true; }
248dadc88e3Srmind 	| OFF		{ $$ = false; }
249a08b1ebdSchristos 	;
250a08b1ebdSchristos 
251a08b1ebdSchristos set
252dadc88e3Srmind 	: SET PARAM param_val {
253dadc88e3Srmind 		npfctl_setparam($2, $3);
254a08b1ebdSchristos 	}
255a08b1ebdSchristos 	;
256a08b1ebdSchristos 
2573fb1890bSrmind /*
2583fb1890bSrmind  * A value - an element or a list of elements.
2593fb1890bSrmind  * Can be assigned to a variable or used inline.
2603fb1890bSrmind  */
2613fb1890bSrmind 
2623fb1890bSrmind vardef
263d116583eSrmind 	: VAR_ID EQ value
264d3c56566Srmind 	{
265d116583eSrmind 		npfvar_add($3, $1);
266d3c56566Srmind 	}
267d3c56566Srmind 	;
268d3c56566Srmind 
2693fb1890bSrmind value
2703fb1890bSrmind 	: element
2713fb1890bSrmind 	| list
272d3c56566Srmind 	;
273d3c56566Srmind 
2743fb1890bSrmind list
275d3c56566Srmind 	: CURLY_OPEN list_elems CURLY_CLOSE
276d116583eSrmind 	{
277d116583eSrmind 		$$ = $2;
278d116583eSrmind 	}
279d3c56566Srmind 	;
280d3c56566Srmind 
281d3c56566Srmind list_elems
2824ec7cf26Sriastradh 	: list_elems COMMA element
283d116583eSrmind 	{
284d116583eSrmind 		npfvar_add_elements($1, $3);
285d116583eSrmind 	}
2863fb1890bSrmind 	| element
287d3c56566Srmind 	;
288d3c56566Srmind 
2893fb1890bSrmind element
290d3c56566Srmind 	: IDENTIFIER
291d3c56566Srmind 	{
292d116583eSrmind 		$$ = npfvar_create_from_string(NPFVAR_IDENTIFIER, $1);
293d3c56566Srmind 	}
294d3c56566Srmind 	| STRING
295d3c56566Srmind 	{
296d116583eSrmind 		$$ = npfvar_create_from_string(NPFVAR_STRING, $1);
297d3c56566Srmind 	}
298464306f9Schristos 	| number MINUS number
299394473e7Schristos 	{
300d116583eSrmind 		$$ = npfctl_parse_port_range($1, $3);
301394473e7Schristos 	}
302464306f9Schristos 	| number
303d3c56566Srmind 	{
304d116583eSrmind 		$$ = npfvar_create_element(NPFVAR_NUM, &$1, sizeof($1));
305d3c56566Srmind 	}
306d3c56566Srmind 	| VAR_ID
307d3c56566Srmind 	{
308d116583eSrmind 		$$ = npfvar_create_from_string(NPFVAR_VAR_ID, $1);
309d3c56566Srmind 	}
310d116583eSrmind 	| TABLE_ID		{ $$ = npfctl_parse_table_id($1); }
311f095afd7Srmind 	| dynamic_ifaddrs	{ $$ = npfctl_ifnet_table($1); }
312f095afd7Srmind 	| static_ifaddrs	{ $$ = $1; }
313d116583eSrmind 	| addr_and_mask		{ $$ = $1; }
314d3c56566Srmind 	;
315d3c56566Srmind 
3163fb1890bSrmind /*
3173fb1890bSrmind  * Table definition.
3183fb1890bSrmind  */
3193fb1890bSrmind 
320d3c56566Srmind table
321d3c56566Srmind 	: TABLE TABLE_ID TYPE table_type table_store
322d3c56566Srmind 	{
323d3c56566Srmind 		npfctl_build_table($2, $4, $5);
324d3c56566Srmind 	}
325d3c56566Srmind 	;
326d3c56566Srmind 
327d3c56566Srmind table_type
3283d9a792dSrmind 	: IPSET		{ $$ = NPF_TABLE_IPSET; }
3293d9a792dSrmind 	| HASH
3303d9a792dSrmind 	{
3313d9a792dSrmind 		warnx("warning - table type \"hash\" is deprecated and may be "
3323d9a792dSrmind 		    "deleted in\nthe future; please use the \"ipset\" type "
3333d9a792dSrmind 		    "instead.");
3343d9a792dSrmind 		$$ = NPF_TABLE_IPSET;
3353d9a792dSrmind 	}
3363d9a792dSrmind 	| LPM		{ $$ = NPF_TABLE_LPM; }
3373d9a792dSrmind 	| TREE
3383d9a792dSrmind 	{
3393d9a792dSrmind 		warnx("warning - table type \"tree\" is deprecated and may be "
3403d9a792dSrmind 		    "deleted in\nthe future; please use the \"lpm\" type "
3413d9a792dSrmind 		    "instead.");
3423d9a792dSrmind 		$$ = NPF_TABLE_LPM;
3433d9a792dSrmind 	}
3443d9a792dSrmind 	| CONST		{ $$ = NPF_TABLE_CONST; }
3453d9a792dSrmind 	| CDB
3463d9a792dSrmind 	{
3473d9a792dSrmind 		warnx("warning -- table type \"cdb\" is deprecated and may be "
3483d9a792dSrmind 		    "deleted in\nthe future; please use the \"const\" type "
3493d9a792dSrmind 		    "instead.");
3503d9a792dSrmind 		$$ = NPF_TABLE_CONST;
3513d9a792dSrmind 	}
352d3c56566Srmind 	;
353d3c56566Srmind 
354d3c56566Srmind table_store
3553d9a792dSrmind 	: TFILE STRING	{ $$ = $2; }
3563d9a792dSrmind 	| TDYNAMIC
3573d9a792dSrmind 	{
3583d9a792dSrmind 		warnx("warning - the \"dynamic\" keyword for tables is obsolete");
3593d9a792dSrmind 		$$ = NULL;
3603d9a792dSrmind 	}
3613d9a792dSrmind 	|		{ $$ = NULL; }
362d3c56566Srmind 	;
363d3c56566Srmind 
3643fb1890bSrmind /*
3653fb1890bSrmind  * Map definition.
3663fb1890bSrmind  */
3673fb1890bSrmind 
3687a3e0c21Srmind map_sd
3697a3e0c21Srmind 	: TSTATIC	{ $$ = NPFCTL_NAT_STATIC; }
3707a3e0c21Srmind 	| TDYNAMIC	{ $$ = NPFCTL_NAT_DYNAMIC; }
3717a3e0c21Srmind 	|		{ $$ = NPFCTL_NAT_DYNAMIC; }
372d3c56566Srmind 	;
373d3c56566Srmind 
374068cee29Srmind map_algo
3753d9a792dSrmind 	: ALGO NETMAP		{ $$ = NPF_ALGO_NETMAP; }
3763d9a792dSrmind 	| ALGO IPHASH		{ $$ = NPF_ALGO_IPHASH; }
3773d9a792dSrmind 	| ALGO ROUNDROBIN	{ $$ = NPF_ALGO_RR; }
3783d9a792dSrmind 	| ALGO NPT66		{ $$ = NPF_ALGO_NPT66; }
379068cee29Srmind 	|			{ $$ = 0; }
380068cee29Srmind 	;
381068cee29Srmind 
382bd05c4c4Srmind map_flags
383bd05c4c4Srmind 	: NO_PORTS	{ $$ = NPF_NAT_PORTS; }
384bd05c4c4Srmind 	|		{ $$ = 0; }
385bd05c4c4Srmind 	;
386bd05c4c4Srmind 
3877a3e0c21Srmind map_type
3887a3e0c21Srmind 	: ARROWBOTH	{ $$ = NPF_NATIN | NPF_NATOUT; }
3897a3e0c21Srmind 	| ARROWLEFT	{ $$ = NPF_NATIN; }
3907a3e0c21Srmind 	| ARROWRIGHT	{ $$ = NPF_NATOUT; }
3917a3e0c21Srmind 	;
3927a3e0c21Srmind 
3937a3e0c21Srmind mapseg
394*b899bfd9Srmind 	: filt_addr filt_port
395d3c56566Srmind 	{
3967a3e0c21Srmind 		$$.ap_netaddr = $1;
3977a3e0c21Srmind 		$$.ap_portrange = $2;
398d3c56566Srmind 	}
399d3c56566Srmind 	;
400d3c56566Srmind 
4017a3e0c21Srmind map
402bd05c4c4Srmind 	: MAP ifref map_sd map_algo map_flags mapseg map_type mapseg
4033d9a792dSrmind 	  PASS opt_family opt_proto all_or_filt_opts
404d3c56566Srmind 	{
405*b899bfd9Srmind 		npfctl_build_natseg($3, $7, $5, $2, &$6, &$8, $11, &$12, $4);
406d3c56566Srmind 	}
407bd05c4c4Srmind 	| MAP ifref map_sd map_algo map_flags mapseg map_type mapseg
40882fad0d6Srmind 	{
409bd05c4c4Srmind 		npfctl_build_natseg($3, $7, $5, $2, &$6, &$8, NULL, NULL, $4);
41082fad0d6Srmind 	}
411bd05c4c4Srmind 	| MAP ifref map_sd map_algo map_flags proto mapseg map_type mapseg
412d3c56566Srmind 	{
413*b899bfd9Srmind 		npfctl_build_natseg($3, $8, $5, $2, &$7, &$9, $6, NULL, $4);
414d3c56566Srmind 	}
415f797733aSrmind 	| MAP RULESET group_opts
416543d2971Srmind 	{
417a79812eaSrmind 		npfctl_build_maprset($3.rg_name, $3.rg_attr, $3.rg_ifname);
418543d2971Srmind 	}
419d3c56566Srmind 	;
420d3c56566Srmind 
4213fb1890bSrmind /*
4223fb1890bSrmind  * Rule procedure definition and its parameters.
4233fb1890bSrmind  */
4243fb1890bSrmind 
425d3c56566Srmind rproc
426d3c56566Srmind 	: PROCEDURE STRING CURLY_OPEN procs CURLY_CLOSE
427d3c56566Srmind 	{
428d3c56566Srmind 		npfctl_build_rproc($2, $4);
429d3c56566Srmind 	}
430d3c56566Srmind 	;
431d3c56566Srmind 
432d3c56566Srmind procs
4334ec7cf26Sriastradh 	: procs SEPLINE proc_call
434d3c56566Srmind 	{
435d3c56566Srmind 		$$ = npfvar_add_elements($1, $3);
436d3c56566Srmind 	}
4378c6e21bfSrmind 	| proc_call	{ $$ = $1; }
4388c6e21bfSrmind 	;
4398c6e21bfSrmind 
4408c6e21bfSrmind proc_call
4418c6e21bfSrmind 	: IDENTIFIER COLON proc_param_list
4428c6e21bfSrmind 	{
4438c6e21bfSrmind 		proc_call_t pc;
4448c6e21bfSrmind 
4457b016567Srmind 		pc.pc_name = estrdup($1);
4468c6e21bfSrmind 		pc.pc_opts = $3;
447d116583eSrmind 
448d116583eSrmind 		$$ = npfvar_create_element(NPFVAR_PROC, &pc, sizeof(pc));
4498c6e21bfSrmind 	}
450d3c56566Srmind 	|		{ $$ = NULL; }
451d3c56566Srmind 	;
452d3c56566Srmind 
4538c6e21bfSrmind proc_param_list
4544ec7cf26Sriastradh 	: proc_param_list COMMA proc_param
455d3c56566Srmind 	{
4568c6e21bfSrmind 		$$ = npfvar_add_elements($1, $3);
4578c6e21bfSrmind 	}
4588c6e21bfSrmind 	| proc_param	{ $$ = $1; }
4598c6e21bfSrmind 	|		{ $$ = NULL; }
4608c6e21bfSrmind 	;
461d3c56566Srmind 
4628c6e21bfSrmind proc_param
4638c6e21bfSrmind 	: some_name proc_param_val
4648c6e21bfSrmind 	{
4658c6e21bfSrmind 		proc_param_t pp;
4668c6e21bfSrmind 
4677b016567Srmind 		pp.pp_param = estrdup($1);
4687b016567Srmind 		pp.pp_value = $2 ? estrdup($2) : NULL;
469d116583eSrmind 
470d116583eSrmind 		$$ = npfvar_create_element(NPFVAR_PROC_PARAM, &pp, sizeof(pp));
471d3c56566Srmind 	}
472d3c56566Srmind 	;
473d3c56566Srmind 
4748c6e21bfSrmind proc_param_val
4758c6e21bfSrmind 	: some_name	{ $$ = $1; }
476464306f9Schristos 	| number	{ (void)asprintf(&$$, "%ld", $1); }
4778c6e21bfSrmind 	| FPNUM		{ (void)asprintf(&$$, "%lf", $1); }
478d3c56566Srmind 	|		{ $$ = NULL; }
479d3c56566Srmind 	;
480d3c56566Srmind 
4813fb1890bSrmind /*
4823fb1890bSrmind  * Group and dynamic ruleset definition.
4833fb1890bSrmind  */
4843fb1890bSrmind 
485d3c56566Srmind group
486f797733aSrmind 	: GROUP group_opts
487d3c56566Srmind 	{
488d116583eSrmind 		/* Build a group.  Increase the nesting level. */
489f797733aSrmind 		npfctl_build_group($2.rg_name, $2.rg_attr,
490a79812eaSrmind 		    $2.rg_ifname, $2.rg_default);
491d3c56566Srmind 	}
4920e218254Srmind 	  ruleset_block
4930e218254Srmind 	{
4940e218254Srmind 		/* Decrease the nesting level. */
4950e218254Srmind 		npfctl_build_group_end();
4960e218254Srmind 	}
497d3c56566Srmind 	;
498d3c56566Srmind 
499543d2971Srmind ruleset
500f797733aSrmind 	: RULESET group_opts
501543d2971Srmind 	{
502543d2971Srmind 		/* Ruleset is a dynamic group. */
503f797733aSrmind 		npfctl_build_group($2.rg_name, $2.rg_attr | NPF_RULE_DYNAMIC,
504a79812eaSrmind 		    $2.rg_ifname, $2.rg_default);
505543d2971Srmind 		npfctl_build_group_end();
506543d2971Srmind 	}
507d3c56566Srmind 	;
508d3c56566Srmind 
509f797733aSrmind group_dir
510f797733aSrmind 	: FORW		{ $$ = NPF_RULE_FORW; }
511f797733aSrmind 	| rule_dir
512f797733aSrmind 	;
513f797733aSrmind 
514f797733aSrmind group_opts
515d3c56566Srmind 	: DEFAULT
516d3c56566Srmind 	{
5170e218254Srmind 		memset(&$$, 0, sizeof(rule_group_t));
5180e218254Srmind 		$$.rg_default = true;
519d3c56566Srmind 	}
520a79812eaSrmind 	| STRING group_dir on_ifname
521d3c56566Srmind 	{
5220e218254Srmind 		memset(&$$, 0, sizeof(rule_group_t));
523f797733aSrmind 		$$.rg_name = $1;
524f797733aSrmind 		$$.rg_attr = $2;
525a79812eaSrmind 		$$.rg_ifname = $3;
526d3c56566Srmind 	}
527d3c56566Srmind 	;
528d3c56566Srmind 
5290e218254Srmind ruleset_block
530543d2971Srmind 	: CURLY_OPEN ruleset_def CURLY_CLOSE
531d3c56566Srmind 	;
532d3c56566Srmind 
533543d2971Srmind ruleset_def
5344ec7cf26Sriastradh 	: ruleset_def SEPLINE rule_group
5350e218254Srmind 	| rule_group
536d3c56566Srmind 	;
537d3c56566Srmind 
5380e218254Srmind rule_group
5390e218254Srmind 	: rule
5400e218254Srmind 	| group
541543d2971Srmind 	| ruleset
5420e218254Srmind 	|
543ce389782Srmind 	;
5440e218254Srmind 
5453fb1890bSrmind /*
5463fb1890bSrmind  * Rule and misc.
5473fb1890bSrmind  */
5483fb1890bSrmind 
549d3c56566Srmind rule
550a79812eaSrmind 	: block_or_pass opt_stateful rule_dir opt_final on_ifname
5515111d7eaSrmind 	  opt_family opt_proto all_or_filt_opts opt_apply
552d3c56566Srmind 	{
553ac69c0c3Srmind 		npfctl_build_rule($1 | $2 | $3 | $4, $5,
554*b899bfd9Srmind 		    $6, $7, &$8, NULL, $9);
555f797733aSrmind 	}
556a79812eaSrmind 	| block_or_pass opt_stateful rule_dir opt_final on_ifname
557f797733aSrmind 	  PCAP_FILTER STRING opt_apply
558f797733aSrmind 	{
559f797733aSrmind 		npfctl_build_rule($1 | $2 | $3 | $4, $5,
560f797733aSrmind 		    AF_UNSPEC, NULL, NULL, $7, $8);
561d3c56566Srmind 	}
562d3c56566Srmind 	;
563d3c56566Srmind 
564d3c56566Srmind block_or_pass
565d3c56566Srmind 	: BLOCK block_opts	{ $$ = $2; }
566d3c56566Srmind 	| PASS			{ $$ = NPF_RULE_PASS; }
567d3c56566Srmind 	;
568d3c56566Srmind 
569d3c56566Srmind rule_dir
570d3c56566Srmind 	: IN			{ $$ = NPF_RULE_IN; }
571d3c56566Srmind 	| OUT			{ $$ = NPF_RULE_OUT; }
572d3c56566Srmind 	|			{ $$ = NPF_RULE_IN | NPF_RULE_OUT; }
573d3c56566Srmind 	;
574d3c56566Srmind 
575ac69c0c3Srmind opt_final
576ac69c0c3Srmind 	: FINAL			{ $$ = NPF_RULE_FINAL; }
577d3c56566Srmind 	|			{ $$ = 0; }
578d3c56566Srmind 	;
579d3c56566Srmind 
580a79812eaSrmind on_ifname
581d116583eSrmind 	: ON ifref		{ $$ = $2; }
582a79812eaSrmind 	|			{ $$ = NULL; }
583d3c56566Srmind 	;
584d3c56566Srmind 
5855111d7eaSrmind afamily
586d116583eSrmind 	: INET4			{ $$ = AF_INET; }
5875111d7eaSrmind 	| INET6			{ $$ = AF_INET6; }
5885111d7eaSrmind 	;
5895111d7eaSrmind 
5908334b9bcSrmind maybe_not
5918334b9bcSrmind 	: EXCL_MARK		{ $$ = true; }
5928334b9bcSrmind 	|			{ $$ = false; }
5938334b9bcSrmind 	;
5948334b9bcSrmind 
59533b678d7Srmind opt_family
5965111d7eaSrmind 	: FAMILY afamily	{ $$ = $2; }
59733b678d7Srmind 	|			{ $$ = AF_UNSPEC; }
598d3c56566Srmind 	;
599d3c56566Srmind 
600*b899bfd9Srmind rawproto
601*b899bfd9Srmind 	: TCP tcp_flags_and_mask
602d3c56566Srmind 	{
603d3c56566Srmind 		$$.op_proto = IPPROTO_TCP;
604*b899bfd9Srmind 		$$.op_opts = $2;
605d3c56566Srmind 	}
606*b899bfd9Srmind 	| ICMP icmp_type_and_code
607d3c56566Srmind 	{
608d3c56566Srmind 		$$.op_proto = IPPROTO_ICMP;
609*b899bfd9Srmind 		$$.op_opts = $2;
610d3c56566Srmind 	}
611*b899bfd9Srmind 	| ICMP6 icmp_type_and_code
6127cf84a83Sspz 	{
6137cf84a83Sspz 		$$.op_proto = IPPROTO_ICMPV6;
614*b899bfd9Srmind 		$$.op_opts = $2;
6157cf84a83Sspz 	}
616*b899bfd9Srmind 	| some_name
617d3c56566Srmind 	{
618*b899bfd9Srmind 		$$.op_proto = npfctl_protono($1);
61933b678d7Srmind 		$$.op_opts = NULL;
62033b678d7Srmind 	}
621*b899bfd9Srmind 	| number
62233b678d7Srmind 	{
623*b899bfd9Srmind 		$$.op_proto = $1;
624d3c56566Srmind 		$$.op_opts = NULL;
625d3c56566Srmind 	}
62682fad0d6Srmind 	;
62782fad0d6Srmind 
628*b899bfd9Srmind proto_elems
629*b899bfd9Srmind 	: proto_elems COMMA rawproto
630*b899bfd9Srmind 	{
631*b899bfd9Srmind 		npfvar_t *pvar = npfvar_create_element(
632*b899bfd9Srmind 		    NPFVAR_PROTO, &$3, sizeof($3));
633*b899bfd9Srmind 		$$ = npfvar_add_elements($1, pvar);
634*b899bfd9Srmind 	}
635*b899bfd9Srmind 	| rawproto
636*b899bfd9Srmind 	{
637*b899bfd9Srmind 		$$ = npfvar_create_element(NPFVAR_PROTO, &$1, sizeof($1));
638*b899bfd9Srmind 	}
639*b899bfd9Srmind 	;
640*b899bfd9Srmind 
641*b899bfd9Srmind proto
642*b899bfd9Srmind 	: PROTO rawproto
643*b899bfd9Srmind 	{
644*b899bfd9Srmind 		$$ = npfvar_create_element(NPFVAR_PROTO, &$2, sizeof($2));
645*b899bfd9Srmind 	}
646*b899bfd9Srmind 	| PROTO CURLY_OPEN proto_elems CURLY_CLOSE
647*b899bfd9Srmind 	{
648*b899bfd9Srmind 		$$ = $3;
649*b899bfd9Srmind 	}
650*b899bfd9Srmind 	;
651*b899bfd9Srmind 
65282fad0d6Srmind opt_proto
65382fad0d6Srmind 	: proto			{ $$ = $1; }
654*b899bfd9Srmind 	|			{ $$ = NULL; }
655d3c56566Srmind 	;
656d3c56566Srmind 
657d3c56566Srmind all_or_filt_opts
658d3c56566Srmind 	: ALL
659d3c56566Srmind 	{
6608334b9bcSrmind 		$$.fo_finvert = false;
6617a3e0c21Srmind 		$$.fo_from.ap_netaddr = NULL;
6627a3e0c21Srmind 		$$.fo_from.ap_portrange = NULL;
6638334b9bcSrmind 		$$.fo_tinvert = false;
6647a3e0c21Srmind 		$$.fo_to.ap_netaddr = NULL;
6657a3e0c21Srmind 		$$.fo_to.ap_portrange = NULL;
666d3c56566Srmind 	}
667d3c56566Srmind 	| filt_opts	{ $$ = $1; }
668d3c56566Srmind 	;
669d3c56566Srmind 
670ac69c0c3Srmind opt_stateful
67133b678d7Srmind 	: STATEFUL	{ $$ = NPF_RULE_STATEFUL; }
672dadc88e3Srmind 	| STATEFUL_ALL	{ $$ = NPF_RULE_STATEFUL | NPF_RULE_GSTATEFUL; }
673d3c56566Srmind 	|		{ $$ = 0; }
674d3c56566Srmind 	;
675d3c56566Srmind 
676d3c56566Srmind opt_apply
677d3c56566Srmind 	: APPLY STRING	{ $$ = $2; }
678d3c56566Srmind 	|		{ $$ = NULL; }
679d3c56566Srmind 	;
680d3c56566Srmind 
681d3c56566Srmind block_opts
682d3c56566Srmind 	: RETURNRST	{ $$ = NPF_RULE_RETRST; }
683d3c56566Srmind 	| RETURNICMP	{ $$ = NPF_RULE_RETICMP; }
684d3c56566Srmind 	| RETURN	{ $$ = NPF_RULE_RETRST | NPF_RULE_RETICMP; }
685d3c56566Srmind 	|		{ $$ = 0; }
686d3c56566Srmind 	;
687d3c56566Srmind 
688d3c56566Srmind filt_opts
689*b899bfd9Srmind 	: FROM maybe_not filt_addr filt_port TO maybe_not filt_addr filt_port
690d3c56566Srmind 	{
6918334b9bcSrmind 		$$.fo_finvert = $2;
6928334b9bcSrmind 		$$.fo_from.ap_netaddr = $3;
6938334b9bcSrmind 		$$.fo_from.ap_portrange = $4;
6948334b9bcSrmind 		$$.fo_tinvert = $6;
6958334b9bcSrmind 		$$.fo_to.ap_netaddr = $7;
6968334b9bcSrmind 		$$.fo_to.ap_portrange = $8;
697d3c56566Srmind 	}
698*b899bfd9Srmind 	| FROM maybe_not filt_addr filt_port
699d3c56566Srmind 	{
7008334b9bcSrmind 		$$.fo_finvert = $2;
7018334b9bcSrmind 		$$.fo_from.ap_netaddr = $3;
7028334b9bcSrmind 		$$.fo_from.ap_portrange = $4;
7038334b9bcSrmind 		$$.fo_tinvert = false;
7047a3e0c21Srmind 		$$.fo_to.ap_netaddr = NULL;
7057a3e0c21Srmind 		$$.fo_to.ap_portrange = NULL;
706d3c56566Srmind 	}
707*b899bfd9Srmind 	| TO maybe_not filt_addr filt_port
708d3c56566Srmind 	{
7098334b9bcSrmind 		$$.fo_finvert = false;
7107a3e0c21Srmind 		$$.fo_from.ap_netaddr = NULL;
7117a3e0c21Srmind 		$$.fo_from.ap_portrange = NULL;
7128334b9bcSrmind 		$$.fo_tinvert = $2;
7138334b9bcSrmind 		$$.fo_to.ap_netaddr = $3;
7148334b9bcSrmind 		$$.fo_to.ap_portrange = $4;
715d3c56566Srmind 	}
716d3c56566Srmind 	;
717d3c56566Srmind 
718*b899bfd9Srmind filt_addr_list
719*b899bfd9Srmind 	: filt_addr_list COMMA filt_addr_element
720*b899bfd9Srmind 	{
721*b899bfd9Srmind 		npfvar_add_elements($1, $3);
722*b899bfd9Srmind 	}
723*b899bfd9Srmind 	| filt_addr_element
724*b899bfd9Srmind 	;
725*b899bfd9Srmind 
726d3c56566Srmind filt_addr
727*b899bfd9Srmind 	: CURLY_OPEN filt_addr_list CURLY_CLOSE
728*b899bfd9Srmind 	{
729*b899bfd9Srmind 		$$ = $2;
730*b899bfd9Srmind 	}
731*b899bfd9Srmind 	| filt_addr_element	{ $$ = $1; }
732d3c56566Srmind 	| ANY			{ $$ = NULL; }
733d3c56566Srmind 	;
734d3c56566Srmind 
735d3c56566Srmind addr_and_mask
736464306f9Schristos 	: addr SLASH number
737d3c56566Srmind 	{
738d3c56566Srmind 		$$ = npfctl_parse_fam_addr_mask($1, NULL, &$3);
739d3c56566Srmind 	}
740d3c56566Srmind 	| addr SLASH addr
741d3c56566Srmind 	{
742d3c56566Srmind 		$$ = npfctl_parse_fam_addr_mask($1, $3, NULL);
743d3c56566Srmind 	}
744d3c56566Srmind 	| addr
745d3c56566Srmind 	{
746d3c56566Srmind 		$$ = npfctl_parse_fam_addr_mask($1, NULL, NULL);
747d3c56566Srmind 	}
748d3c56566Srmind 	;
749d3c56566Srmind 
750*b899bfd9Srmind filt_addr_element
7513d9a792dSrmind 	: addr_and_mask		{ assert($1 != NULL); $$ = $1; }
752f095afd7Srmind 	| static_ifaddrs
7532d942d9dSrmind 	{
754f0775766Schristos 		if (npfvar_get_count($1) != 1)
755f0775766Schristos 			yyerror("multiple interfaces are not supported");
7565111d7eaSrmind 		ifnet_addr_t *ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0);
7575111d7eaSrmind 		$$ = ifna->ifna_addrs;
7582d942d9dSrmind 	}
7593d9a792dSrmind 	| dynamic_ifaddrs	{ $$ = npfctl_ifnet_table($1); }
7603d9a792dSrmind 	| TABLE_ID		{ $$ = npfctl_parse_table_id($1); }
7612d942d9dSrmind 	| VAR_ID
7622d942d9dSrmind 	{
7632d942d9dSrmind 		npfvar_t *vp = npfvar_lookup($1);
764e0620b41Schristos 		int type = npfvar_get_type(vp, 0);
7655111d7eaSrmind 		ifnet_addr_t *ifna;
766e0620b41Schristos again:
7672d942d9dSrmind 		switch (type) {
768e0620b41Schristos 		case NPFVAR_IDENTIFIER:
769e0620b41Schristos 		case NPFVAR_STRING:
770e0620b41Schristos 			vp = npfctl_parse_ifnet(npfvar_expand_string(vp),
771e0620b41Schristos 			    AF_UNSPEC);
772e0620b41Schristos 			type = npfvar_get_type(vp, 0);
773e0620b41Schristos 			goto again;
7742d942d9dSrmind 		case NPFVAR_FAM:
775f095afd7Srmind 		case NPFVAR_TABLE:
7762d942d9dSrmind 			$$ = vp;
7772d942d9dSrmind 			break;
7785111d7eaSrmind 		case NPFVAR_INTERFACE:
779247d8613Srmind 			$$ = NULL;
780247d8613Srmind 			for (u_int i = 0; i < npfvar_get_count(vp); i++) {
781247d8613Srmind 				ifna = npfvar_get_data(vp, type, i);
782247d8613Srmind 				$$ = npfvar_add_elements($$, ifna->ifna_addrs);
783247d8613Srmind 			}
7845111d7eaSrmind 			break;
7852d942d9dSrmind 		case -1:
7865111d7eaSrmind 			yyerror("undefined variable '%s'", $1);
7872d942d9dSrmind 			break;
7882d942d9dSrmind 		default:
7895111d7eaSrmind 			yyerror("wrong variable '%s' type '%s' for address "
7905111d7eaSrmind 			    "or interface", $1, npfvar_type(type));
7912d942d9dSrmind 			break;
7922d942d9dSrmind 		}
7932d942d9dSrmind 	}
794d3c56566Srmind 	;
795d3c56566Srmind 
796d3c56566Srmind addr
797d3c56566Srmind 	: IPV4ADDR	{ $$ = $1; }
798d3c56566Srmind 	| IPV6ADDR	{ $$ = $1; }
799d3c56566Srmind 	;
800d3c56566Srmind 
801*b899bfd9Srmind filt_port
802*b899bfd9Srmind 	: PORT CURLY_OPEN filt_port_list CURLY_CLOSE
803d3c56566Srmind 	{
804*b899bfd9Srmind 		$$ = npfctl_parse_port_range_variable(NULL, $3);
805d3c56566Srmind 	}
806*b899bfd9Srmind 	| PORT port_range	{ $$ = $2; }
80760a0ec10Srmind 	|			{ $$ = NULL; }
808d3c56566Srmind 	;
809d3c56566Srmind 
810*b899bfd9Srmind filt_port_list
811*b899bfd9Srmind 	: filt_port_list COMMA port_range
812*b899bfd9Srmind 	{
813*b899bfd9Srmind 		npfvar_add_elements($1, $3);
814*b899bfd9Srmind 	}
815*b899bfd9Srmind 	| port_range
816*b899bfd9Srmind 	;
817*b899bfd9Srmind 
818*b899bfd9Srmind port_range
819*b899bfd9Srmind 	: port		/* just port */
820*b899bfd9Srmind 	{
821*b899bfd9Srmind 		$$ = npfctl_parse_port_range($1, $1);
822*b899bfd9Srmind 	}
823*b899bfd9Srmind 	| port MINUS port	/* port from-to */
824*b899bfd9Srmind 	{
825*b899bfd9Srmind 		$$ = npfctl_parse_port_range($1, $3);
826*b899bfd9Srmind 	}
827*b899bfd9Srmind 	| VAR_ID
828*b899bfd9Srmind 	{
829*b899bfd9Srmind 		npfvar_t *vp = npfvar_lookup($1);
830*b899bfd9Srmind 		$$ = npfctl_parse_port_range_variable($1, vp);
831*b899bfd9Srmind 	}
832*b899bfd9Srmind 	;
833*b899bfd9Srmind 
834d3c56566Srmind port
835464306f9Schristos 	: number	{ $$ = $1; }
836d3c56566Srmind 	| IDENTIFIER	{ $$ = npfctl_portno($1); }
83758bc4d4eSchristos 	| STRING	{ $$ = npfctl_portno($1); }
838d3c56566Srmind 	;
839d3c56566Srmind 
840d3c56566Srmind icmp_type_and_code
841d3c56566Srmind 	: ICMPTYPE icmp_type
842d3c56566Srmind 	{
8437cf84a83Sspz 		$$ = npfctl_parse_icmp($<num>0, $2, -1);
844d3c56566Srmind 	}
845464306f9Schristos 	| ICMPTYPE icmp_type CODE number
846d3c56566Srmind 	{
8477cf84a83Sspz 		$$ = npfctl_parse_icmp($<num>0, $2, $4);
848d3c56566Srmind 	}
849d3c56566Srmind 	| ICMPTYPE icmp_type CODE IDENTIFIER
850d3c56566Srmind 	{
8515111d7eaSrmind 		$$ = npfctl_parse_icmp($<num>0, $2,
8525111d7eaSrmind 		    npfctl_icmpcode($<num>0, $2, $4));
853d3c56566Srmind 	}
854d3c56566Srmind 	| ICMPTYPE icmp_type CODE VAR_ID
855d3c56566Srmind 	{
856d3c56566Srmind 		char *s = npfvar_expand_string(npfvar_lookup($4));
8575111d7eaSrmind 		$$ = npfctl_parse_icmp($<num>0, $2,
8585111d7eaSrmind 		    npfctl_icmpcode($<num>0, $2, s));
859d3c56566Srmind 	}
8604e592132Srmind 	|		{ $$ = NULL; }
861d3c56566Srmind 	;
862d3c56566Srmind 
863d3c56566Srmind tcp_flags_and_mask
864d3c56566Srmind 	: FLAGS tcp_flags SLASH tcp_flags
865d3c56566Srmind 	{
866d3c56566Srmind 		npfvar_add_elements($2, $4);
867d3c56566Srmind 		$$ = $2;
868d3c56566Srmind 	}
869d3c56566Srmind 	| FLAGS tcp_flags
870d3c56566Srmind 	{
871f0775766Schristos 		if (npfvar_get_count($2) != 1)
872f0775766Schristos 			yyerror("multiple tcpflags are not supported");
873d3c56566Srmind 		char *s = npfvar_get_data($2, NPFVAR_TCPFLAG, 0);
874d3c56566Srmind 		npfvar_add_elements($2, npfctl_parse_tcpflag(s));
875d3c56566Srmind 		$$ = $2;
876d3c56566Srmind 	}
877d3c56566Srmind 	|		{ $$ = NULL; }
878d3c56566Srmind 	;
879d3c56566Srmind 
880d3c56566Srmind tcp_flags
881d3c56566Srmind 	: IDENTIFIER	{ $$ = npfctl_parse_tcpflag($1); }
882d3c56566Srmind 	;
883d3c56566Srmind 
884d3c56566Srmind icmp_type
885464306f9Schristos 	: number	{ $$ = $1; }
8867cf84a83Sspz 	| IDENTIFIER	{ $$ = npfctl_icmptype($<num>-1, $1); }
887d3c56566Srmind 	| VAR_ID
888d3c56566Srmind 	{
889d3c56566Srmind 		char *s = npfvar_expand_string(npfvar_lookup($1));
8907cf84a83Sspz 		$$ = npfctl_icmptype($<num>-1, s);
891d3c56566Srmind 	}
892d3c56566Srmind 	;
893d3c56566Srmind 
894a79812eaSrmind ifname
89533b678d7Srmind 	: some_name
896d3c56566Srmind 	{
897a79812eaSrmind 		npfctl_note_interface($1);
898a79812eaSrmind 		$$ = $1;
899d3c56566Srmind 	}
900d3c56566Srmind 	| VAR_ID
901d3c56566Srmind 	{
902d3c56566Srmind 		npfvar_t *vp = npfvar_lookup($1);
903394473e7Schristos 		const int type = npfvar_get_type(vp, 0);
9045111d7eaSrmind 		ifnet_addr_t *ifna;
9053d9a792dSrmind 		const char *name;
9063d9a792dSrmind 		unsigned *tid;
9073d9a792dSrmind 		bool ifaddr;
908d3c56566Srmind 
909d3c56566Srmind 		switch (type) {
910d3c56566Srmind 		case NPFVAR_STRING:
9115111d7eaSrmind 		case NPFVAR_IDENTIFIER:
912a79812eaSrmind 			$$ = npfvar_expand_string(vp);
913d3c56566Srmind 			break;
9145111d7eaSrmind 		case NPFVAR_INTERFACE:
915f0775766Schristos 			if (npfvar_get_count(vp) != 1)
916f0775766Schristos 				yyerror(
917f0775766Schristos 				    "multiple interfaces are not supported");
9185111d7eaSrmind 			ifna = npfvar_get_data(vp, type, 0);
919a79812eaSrmind 			$$ = ifna->ifna_name;
9205111d7eaSrmind 			break;
9213d9a792dSrmind 		case NPFVAR_TABLE:
9223d9a792dSrmind 			tid = npfvar_get_data(vp, type, 0);
9233d9a792dSrmind 			name = npfctl_table_getname(npfctl_config_ref(),
9243d9a792dSrmind 			    *tid, &ifaddr);
9253d9a792dSrmind 			if (!ifaddr) {
9263d9a792dSrmind 				yyerror("variable '%s' references a table "
9273d9a792dSrmind 				    "%s instead of an interface", $1, name);
9283d9a792dSrmind 			}
9293d9a792dSrmind 			$$ = estrdup(name);
9303d9a792dSrmind 			break;
931d3c56566Srmind 		case -1:
932d3c56566Srmind 			yyerror("undefined variable '%s' for interface", $1);
933d3c56566Srmind 			break;
934d3c56566Srmind 		default:
935d3c56566Srmind 			yyerror("wrong variable '%s' type '%s' for interface",
936d3c56566Srmind 			    $1, npfvar_type(type));
937d3c56566Srmind 			break;
938d3c56566Srmind 		}
939a79812eaSrmind 		npfctl_note_interface($$);
940d3c56566Srmind 	}
941d3c56566Srmind 	;
942d3c56566Srmind 
943f095afd7Srmind static_ifaddrs
944d116583eSrmind 	: afamily PAR_OPEN ifname PAR_CLOSE
945d116583eSrmind 	{
946d116583eSrmind 		$$ = npfctl_parse_ifnet($3, $1);
947d116583eSrmind 	}
948d116583eSrmind 	;
949d116583eSrmind 
950f095afd7Srmind dynamic_ifaddrs
951f095afd7Srmind 	: IFADDRS PAR_OPEN ifname PAR_CLOSE
952f095afd7Srmind 	{
953f095afd7Srmind 		$$ = $3;
954f095afd7Srmind 	}
955f095afd7Srmind 	;
956f095afd7Srmind 
957d116583eSrmind ifref
958d116583eSrmind 	: ifname
959f095afd7Srmind 	| dynamic_ifaddrs
960f095afd7Srmind 	| static_ifaddrs
961d116583eSrmind 	{
962dadc88e3Srmind 		ifnet_addr_t *ifna;
963dadc88e3Srmind 
964dadc88e3Srmind 		if (npfvar_get_count($1) != 1) {
965f0775766Schristos 			yyerror("multiple interfaces are not supported");
966dadc88e3Srmind 		}
967dadc88e3Srmind 		ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0);
968d116583eSrmind 		npfctl_note_interface(ifna->ifna_name);
969d116583eSrmind 		$$ = ifna->ifna_name;
970d116583eSrmind 	}
971d116583eSrmind 	;
972d116583eSrmind 
973464306f9Schristos number
974464306f9Schristos 	: HEX		{ $$ = $1; }
975464306f9Schristos 	| NUM		{ $$ = $1; }
976464306f9Schristos 	;
977464306f9Schristos 
97833b678d7Srmind some_name
979d3c56566Srmind 	: IDENTIFIER	{ $$ = $1; }
980d3c56566Srmind 	| STRING	{ $$ = $1; }
981d3c56566Srmind 	;
982d3c56566Srmind 
983d3c56566Srmind %%
984