xref: /netbsd/usr.sbin/npf/npfctl/npf_parse.y (revision bf40bfa8)
1*bf40bfa8Srmind /*	$NetBSD: npf_parse.y,v 1.46 2017/12/10 22:04:41 rmind Exp $	*/
2f03cb1d4Srmind 
3f03cb1d4Srmind /*-
4df8b1943Srmind  * Copyright (c) 2011-2017 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 <err.h>
35f03cb1d4Srmind #include <netdb.h>
366a296064Sjoerg #include <stdio.h>
376a296064Sjoerg #include <stdlib.h>
386a296064Sjoerg #include <string.h>
396c441296Srmind #ifdef __NetBSD__
406a296064Sjoerg #include <vis.h>
416c441296Srmind #endif
42f03cb1d4Srmind 
43f03cb1d4Srmind #include "npfctl.h"
44f03cb1d4Srmind 
458b3f8af5Srmind #define	YYSTACKSIZE	4096
468b3f8af5Srmind 
4737527ec6Srmind int			yyparsetarget;
48f03cb1d4Srmind const char *		yyfilename;
49f03cb1d4Srmind 
50f03cb1d4Srmind extern int		yylineno, yycolumn;
51f03cb1d4Srmind extern int		yylex(void);
52f03cb1d4Srmind 
53f03cb1d4Srmind void
54f03cb1d4Srmind yyerror(const char *fmt, ...)
55f03cb1d4Srmind {
56f03cb1d4Srmind 	extern int yyleng;
57f03cb1d4Srmind 	extern char *yytext;
58f03cb1d4Srmind 
597c0a5ca2Srmind 	char *msg, *context = estrndup(yytext, yyleng);
604e3d5046Srmind 	bool eol = (*context == '\n');
61f03cb1d4Srmind 	va_list ap;
62f03cb1d4Srmind 
63f03cb1d4Srmind 	va_start(ap, fmt);
64f03cb1d4Srmind 	vasprintf(&msg, fmt, ap);
65f03cb1d4Srmind 	va_end(ap);
66f03cb1d4Srmind 
674e3d5046Srmind 	fprintf(stderr, "%s:%d:%d: %s", yyfilename,
684e3d5046Srmind 	    yylineno - (int)eol, yycolumn, msg);
694e3d5046Srmind 	if (!eol) {
706c441296Srmind #ifdef __NetBSD__
714e3d5046Srmind 		size_t len = strlen(context);
723c7c5558Srmind 		char *dst = ecalloc(1, len * 4 + 1);
734e3d5046Srmind 
74f03cb1d4Srmind 		strvisx(dst, context, len, VIS_WHITE|VIS_CSTYLE);
75f0764fe1Skre 		context = dst;
766c441296Srmind #endif
776c441296Srmind 		fprintf(stderr, " near '%s'", context);
784e3d5046Srmind 	}
794e3d5046Srmind 	fprintf(stderr, "\n");
80f03cb1d4Srmind 	exit(EXIT_FAILURE);
81f03cb1d4Srmind }
82f03cb1d4Srmind 
8337527ec6Srmind #define	CHECK_PARSER_FILE				\
8437527ec6Srmind 	if (yyparsetarget != NPFCTL_PARSE_FILE)		\
8537527ec6Srmind 		yyerror("rule must be in the group");
8637527ec6Srmind 
8737527ec6Srmind #define	CHECK_PARSER_STRING				\
8837527ec6Srmind 	if (yyparsetarget != NPFCTL_PARSE_STRING)	\
8937527ec6Srmind 		yyerror("invalid rule syntax");
9037527ec6Srmind 
91f03cb1d4Srmind %}
92f03cb1d4Srmind 
933b895110Schristos %token			ALG
94a894e3f7Srmind %token			ALGO
95f03cb1d4Srmind %token			ALL
96f03cb1d4Srmind %token			ANY
97f03cb1d4Srmind %token			APPLY
98add921fbSrmind %token			ARROWBOTH
99add921fbSrmind %token			ARROWLEFT
100add921fbSrmind %token			ARROWRIGHT
101f03cb1d4Srmind %token			BLOCK
10293bbacf8Schristos %token			BPFJIT
103820aad11Srmind %token			CDB
104f03cb1d4Srmind %token			CURLY_CLOSE
105f03cb1d4Srmind %token			CURLY_OPEN
106f03cb1d4Srmind %token			CODE
107f03cb1d4Srmind %token			COLON
108f03cb1d4Srmind %token			COMMA
109f03cb1d4Srmind %token			DEFAULT
110f03cb1d4Srmind %token			TDYNAMIC
111add921fbSrmind %token			TSTATIC
112f03cb1d4Srmind %token			EQ
11335bd148cSrmind %token			EXCL_MARK
114f03cb1d4Srmind %token			TFILE
115f03cb1d4Srmind %token			FLAGS
116f03cb1d4Srmind %token			FROM
117f03cb1d4Srmind %token			GROUP
118f03cb1d4Srmind %token			HASH
119f03cb1d4Srmind %token			ICMPTYPE
120f03cb1d4Srmind %token			ID
121f03cb1d4Srmind %token			IN
122348a4177Srmind %token			INET4
123f03cb1d4Srmind %token			INET6
124df8b1943Srmind %token			IFADDRS
125f03cb1d4Srmind %token			INTERFACE
126add921fbSrmind %token			MAP
127*bf40bfa8Srmind %token			NO_PORTS
128f03cb1d4Srmind %token			MINUS
129f03cb1d4Srmind %token			NAME
130a894e3f7Srmind %token			NPT66
131f03cb1d4Srmind %token			ON
13293bbacf8Schristos %token			OFF
133f03cb1d4Srmind %token			OUT
134f03cb1d4Srmind %token			PAR_CLOSE
135f03cb1d4Srmind %token			PAR_OPEN
136f03cb1d4Srmind %token			PASS
137c6e77e2aSrmind %token			PCAP_FILTER
138f03cb1d4Srmind %token			PORT
139f03cb1d4Srmind %token			PROCEDURE
140f03cb1d4Srmind %token			PROTO
141f03cb1d4Srmind %token			FAMILY
142ba11b3c0Srmind %token			FINAL
14337527ec6Srmind %token			FORW
144f03cb1d4Srmind %token			RETURN
145f03cb1d4Srmind %token			RETURNICMP
146f03cb1d4Srmind %token			RETURNRST
1477b486642Srmind %token			RULESET
148f03cb1d4Srmind %token			SEPLINE
14993bbacf8Schristos %token			SET
150f03cb1d4Srmind %token			SLASH
151ba11b3c0Srmind %token			STATEFUL
152196178afSrmind %token			STATEFUL_ENDS
153f03cb1d4Srmind %token			TABLE
154f03cb1d4Srmind %token			TCP
155f03cb1d4Srmind %token			TO
156f03cb1d4Srmind %token			TREE
157f03cb1d4Srmind %token			TYPE
158afd9e22aSspz %token	<num>		ICMP
159afd9e22aSspz %token	<num>		ICMP6
160f03cb1d4Srmind 
161f03cb1d4Srmind %token	<num>		HEX
162f03cb1d4Srmind %token	<str>		IDENTIFIER
163f03cb1d4Srmind %token	<str>		IPV4ADDR
164f03cb1d4Srmind %token	<str>		IPV6ADDR
165f03cb1d4Srmind %token	<num>		NUM
16648a1ec7dSrmind %token	<fpnum>		FPNUM
167f03cb1d4Srmind %token	<str>		STRING
168f03cb1d4Srmind %token	<str>		TABLE_ID
169f03cb1d4Srmind %token	<str>		VAR_ID
170f03cb1d4Srmind 
171df8b1943Srmind %type	<str>		addr, some_name, table_store, dynamic_ifaddrs
172348a4177Srmind %type	<str>		proc_param_val, opt_apply, ifname, on_ifname, ifref
173d1d2e2c9Srmind %type	<num>		port, opt_final, number, afamily, opt_family
174c6e77e2aSrmind %type	<num>		block_or_pass, rule_dir, group_dir, block_opts
17535bd148cSrmind %type	<num>		maybe_not, opt_stateful, icmp_type, table_type
176*bf40bfa8Srmind %type	<num>		map_sd, map_algo, map_flags, map_type
177df8b1943Srmind %type	<var>		static_ifaddrs, addr_or_ifaddr
178df8b1943Srmind %type	<var>		port_range, icmp_type_and_code
179f03cb1d4Srmind %type	<var>		filt_addr, addr_and_mask, tcp_flags, tcp_flags_and_mask
18048a1ec7dSrmind %type	<var>		procs, proc_call, proc_param_list, proc_param
181348a4177Srmind %type	<var>		element, list_elems, list, value
182add921fbSrmind %type	<addrport>	mapseg
183f03cb1d4Srmind %type	<filtopts>	filt_opts, all_or_filt_opts
184a6f5b6a3Srmind %type	<optproto>	proto opt_proto
185c6e77e2aSrmind %type	<rulegroup>	group_opts
18693bbacf8Schristos %type	<tf>		onoff
187f03cb1d4Srmind 
188f03cb1d4Srmind %union {
189f03cb1d4Srmind 	char *		str;
19093bbacf8Schristos 	bool		tf;
191f03cb1d4Srmind 	unsigned long	num;
19248a1ec7dSrmind 	double		fpnum;
193ec3d0e07Srmind 	npfvar_t *	var;
194add921fbSrmind 	addr_port_t	addrport;
195f03cb1d4Srmind 	filt_opts_t	filtopts;
196f03cb1d4Srmind 	opt_proto_t	optproto;
197f03cb1d4Srmind 	rule_group_t	rulegroup;
198f03cb1d4Srmind }
199f03cb1d4Srmind 
200f03cb1d4Srmind %%
201f03cb1d4Srmind 
202f03cb1d4Srmind input
20337527ec6Srmind 	: { CHECK_PARSER_FILE	} lines
20437527ec6Srmind 	| { CHECK_PARSER_STRING	} rule
205f03cb1d4Srmind 	;
206f03cb1d4Srmind 
207f03cb1d4Srmind lines
2089ff93001Sriastradh 	: lines SEPLINE line
209f03cb1d4Srmind 	| line
210f03cb1d4Srmind 	;
211f03cb1d4Srmind 
212f03cb1d4Srmind line
2138f6547d8Srmind 	: vardef
214f03cb1d4Srmind 	| table
215add921fbSrmind 	| map
216f03cb1d4Srmind 	| group
217f03cb1d4Srmind 	| rproc
2183b895110Schristos 	| alg
21993bbacf8Schristos 	| set
220f03cb1d4Srmind 	|
221f03cb1d4Srmind 	;
222f03cb1d4Srmind 
2238f6547d8Srmind alg
2248f6547d8Srmind 	: ALG STRING
2258f6547d8Srmind 	{
2268f6547d8Srmind 		npfctl_build_alg($2);
2278f6547d8Srmind 	}
2288f6547d8Srmind 	;
2298f6547d8Srmind 
23093bbacf8Schristos onoff
23193bbacf8Schristos 	: ON {
23293bbacf8Schristos 		$$ = true;
23393bbacf8Schristos 	}
23493bbacf8Schristos 	| OFF {
23593bbacf8Schristos 		$$ = false;
23693bbacf8Schristos 	}
23793bbacf8Schristos 	;
23893bbacf8Schristos 
23993bbacf8Schristos set
24093bbacf8Schristos 	: SET BPFJIT onoff {
24193bbacf8Schristos 		npfctl_bpfjit($3);
24293bbacf8Schristos 	}
24393bbacf8Schristos 	;
24493bbacf8Schristos 
2458f6547d8Srmind /*
2468f6547d8Srmind  * A value - an element or a list of elements.
2478f6547d8Srmind  * Can be assigned to a variable or used inline.
2488f6547d8Srmind  */
2498f6547d8Srmind 
2508f6547d8Srmind vardef
251348a4177Srmind 	: VAR_ID EQ value
252f03cb1d4Srmind 	{
253348a4177Srmind 		npfvar_add($3, $1);
254f03cb1d4Srmind 	}
255f03cb1d4Srmind 	;
256f03cb1d4Srmind 
2578f6547d8Srmind value
2588f6547d8Srmind 	: element
2598f6547d8Srmind 	| list
260f03cb1d4Srmind 	;
261f03cb1d4Srmind 
2628f6547d8Srmind list
263f03cb1d4Srmind 	: CURLY_OPEN list_elems CURLY_CLOSE
264348a4177Srmind 	{
265348a4177Srmind 		$$ = $2;
266348a4177Srmind 	}
267f03cb1d4Srmind 	;
268f03cb1d4Srmind 
269f03cb1d4Srmind list_elems
2709ff93001Sriastradh 	: list_elems COMMA element
271348a4177Srmind 	{
272348a4177Srmind 		npfvar_add_elements($1, $3);
273348a4177Srmind 	}
2748f6547d8Srmind 	| element
275f03cb1d4Srmind 	;
276f03cb1d4Srmind 
2778f6547d8Srmind element
278f03cb1d4Srmind 	: IDENTIFIER
279f03cb1d4Srmind 	{
280348a4177Srmind 		$$ = npfvar_create_from_string(NPFVAR_IDENTIFIER, $1);
281f03cb1d4Srmind 	}
282f03cb1d4Srmind 	| STRING
283f03cb1d4Srmind 	{
284348a4177Srmind 		$$ = npfvar_create_from_string(NPFVAR_STRING, $1);
285f03cb1d4Srmind 	}
286f2174d83Schristos 	| number MINUS number
287ff24200fSchristos 	{
288348a4177Srmind 		$$ = npfctl_parse_port_range($1, $3);
289ff24200fSchristos 	}
290f2174d83Schristos 	| number
291f03cb1d4Srmind 	{
292348a4177Srmind 		$$ = npfvar_create_element(NPFVAR_NUM, &$1, sizeof($1));
293f03cb1d4Srmind 	}
294f03cb1d4Srmind 	| VAR_ID
295f03cb1d4Srmind 	{
296348a4177Srmind 		$$ = npfvar_create_from_string(NPFVAR_VAR_ID, $1);
297f03cb1d4Srmind 	}
298348a4177Srmind 	| TABLE_ID		{ $$ = npfctl_parse_table_id($1); }
299df8b1943Srmind 	| dynamic_ifaddrs	{ $$ = npfctl_ifnet_table($1); }
300df8b1943Srmind 	| static_ifaddrs	{ $$ = $1; }
301348a4177Srmind 	| addr_and_mask		{ $$ = $1; }
302f03cb1d4Srmind 	;
303f03cb1d4Srmind 
3048f6547d8Srmind /*
3058f6547d8Srmind  * Table definition.
3068f6547d8Srmind  */
3078f6547d8Srmind 
308f03cb1d4Srmind table
309f03cb1d4Srmind 	: TABLE TABLE_ID TYPE table_type table_store
310f03cb1d4Srmind 	{
311f03cb1d4Srmind 		npfctl_build_table($2, $4, $5);
312f03cb1d4Srmind 	}
313f03cb1d4Srmind 	;
314f03cb1d4Srmind 
315f03cb1d4Srmind table_type
316f03cb1d4Srmind 	: HASH		{ $$ = NPF_TABLE_HASH; }
317664900efSrmind 	| TREE		{ $$ = NPF_TABLE_TREE; }
318820aad11Srmind 	| CDB		{ $$ = NPF_TABLE_CDB; }
319f03cb1d4Srmind 	;
320f03cb1d4Srmind 
321f03cb1d4Srmind table_store
322f03cb1d4Srmind 	: TDYNAMIC	{ $$ = NULL; }
323f03cb1d4Srmind 	| TFILE STRING	{ $$ = $2; }
324f03cb1d4Srmind 	;
325f03cb1d4Srmind 
3268f6547d8Srmind /*
3278f6547d8Srmind  * Map definition.
3288f6547d8Srmind  */
3298f6547d8Srmind 
330add921fbSrmind map_sd
331add921fbSrmind 	: TSTATIC	{ $$ = NPFCTL_NAT_STATIC; }
332add921fbSrmind 	| TDYNAMIC	{ $$ = NPFCTL_NAT_DYNAMIC; }
333add921fbSrmind 	|		{ $$ = NPFCTL_NAT_DYNAMIC; }
334f03cb1d4Srmind 	;
335f03cb1d4Srmind 
336a894e3f7Srmind map_algo
337a894e3f7Srmind 	: ALGO NPT66	{ $$ = NPF_ALGO_NPT66; }
338a894e3f7Srmind 	|		{ $$ = 0; }
339a894e3f7Srmind 	;
340a894e3f7Srmind 
341*bf40bfa8Srmind map_flags
342*bf40bfa8Srmind 	: NO_PORTS	{ $$ = NPF_NAT_PORTS; }
343*bf40bfa8Srmind 	|		{ $$ = 0; }
344*bf40bfa8Srmind 	;
345*bf40bfa8Srmind 
346add921fbSrmind map_type
347add921fbSrmind 	: ARROWBOTH	{ $$ = NPF_NATIN | NPF_NATOUT; }
348add921fbSrmind 	| ARROWLEFT	{ $$ = NPF_NATIN; }
349add921fbSrmind 	| ARROWRIGHT	{ $$ = NPF_NATOUT; }
350add921fbSrmind 	;
351add921fbSrmind 
352add921fbSrmind mapseg
353348a4177Srmind 	: addr_or_ifaddr port_range
354f03cb1d4Srmind 	{
355add921fbSrmind 		$$.ap_netaddr = $1;
356add921fbSrmind 		$$.ap_portrange = $2;
357f03cb1d4Srmind 	}
358f03cb1d4Srmind 	;
359f03cb1d4Srmind 
360add921fbSrmind map
361*bf40bfa8Srmind 	: MAP ifref map_sd map_algo map_flags mapseg map_type mapseg
36275cf8dc1Smlelstv 	  PASS opt_proto all_or_filt_opts
363f03cb1d4Srmind 	{
364*bf40bfa8Srmind 		npfctl_build_natseg($3, $7, $5, $2, &$6, &$8, &$10, &$11, $4);
365f03cb1d4Srmind 	}
366*bf40bfa8Srmind 	| MAP ifref map_sd map_algo map_flags mapseg map_type mapseg
367a6f5b6a3Srmind 	{
368*bf40bfa8Srmind 		npfctl_build_natseg($3, $7, $5, $2, &$6, &$8, NULL, NULL, $4);
369a6f5b6a3Srmind 	}
370*bf40bfa8Srmind 	| MAP ifref map_sd map_algo map_flags proto mapseg map_type mapseg
371f03cb1d4Srmind 	{
372*bf40bfa8Srmind 		npfctl_build_natseg($3, $8, $5, $2, &$7, &$9, &$6, NULL, $4);
373f03cb1d4Srmind 	}
374c6e77e2aSrmind 	| MAP RULESET group_opts
3757b486642Srmind 	{
376d1d2e2c9Srmind 		npfctl_build_maprset($3.rg_name, $3.rg_attr, $3.rg_ifname);
3777b486642Srmind 	}
378f03cb1d4Srmind 	;
379f03cb1d4Srmind 
3808f6547d8Srmind /*
3818f6547d8Srmind  * Rule procedure definition and its parameters.
3828f6547d8Srmind  */
3838f6547d8Srmind 
384f03cb1d4Srmind rproc
385f03cb1d4Srmind 	: PROCEDURE STRING CURLY_OPEN procs CURLY_CLOSE
386f03cb1d4Srmind 	{
387f03cb1d4Srmind 		npfctl_build_rproc($2, $4);
388f03cb1d4Srmind 	}
389f03cb1d4Srmind 	;
390f03cb1d4Srmind 
391f03cb1d4Srmind procs
3929ff93001Sriastradh 	: procs SEPLINE proc_call
393f03cb1d4Srmind 	{
394f03cb1d4Srmind 		$$ = npfvar_add_elements($1, $3);
395f03cb1d4Srmind 	}
39648a1ec7dSrmind 	| proc_call	{ $$ = $1; }
39748a1ec7dSrmind 	;
39848a1ec7dSrmind 
39948a1ec7dSrmind proc_call
40048a1ec7dSrmind 	: IDENTIFIER COLON proc_param_list
40148a1ec7dSrmind 	{
40248a1ec7dSrmind 		proc_call_t pc;
40348a1ec7dSrmind 
4047c0a5ca2Srmind 		pc.pc_name = estrdup($1);
40548a1ec7dSrmind 		pc.pc_opts = $3;
406348a4177Srmind 
407348a4177Srmind 		$$ = npfvar_create_element(NPFVAR_PROC, &pc, sizeof(pc));
40848a1ec7dSrmind 	}
409f03cb1d4Srmind 	|		{ $$ = NULL; }
410f03cb1d4Srmind 	;
411f03cb1d4Srmind 
41248a1ec7dSrmind proc_param_list
4139ff93001Sriastradh 	: proc_param_list COMMA proc_param
414f03cb1d4Srmind 	{
41548a1ec7dSrmind 		$$ = npfvar_add_elements($1, $3);
41648a1ec7dSrmind 	}
41748a1ec7dSrmind 	| proc_param	{ $$ = $1; }
41848a1ec7dSrmind 	|		{ $$ = NULL; }
41948a1ec7dSrmind 	;
420f03cb1d4Srmind 
42148a1ec7dSrmind proc_param
42248a1ec7dSrmind 	: some_name proc_param_val
42348a1ec7dSrmind 	{
42448a1ec7dSrmind 		proc_param_t pp;
42548a1ec7dSrmind 
4267c0a5ca2Srmind 		pp.pp_param = estrdup($1);
4277c0a5ca2Srmind 		pp.pp_value = $2 ? estrdup($2) : NULL;
428348a4177Srmind 
429348a4177Srmind 		$$ = npfvar_create_element(NPFVAR_PROC_PARAM, &pp, sizeof(pp));
430f03cb1d4Srmind 	}
431f03cb1d4Srmind 	;
432f03cb1d4Srmind 
43348a1ec7dSrmind proc_param_val
43448a1ec7dSrmind 	: some_name	{ $$ = $1; }
435f2174d83Schristos 	| number	{ (void)asprintf(&$$, "%ld", $1); }
43648a1ec7dSrmind 	| FPNUM		{ (void)asprintf(&$$, "%lf", $1); }
437f03cb1d4Srmind 	|		{ $$ = NULL; }
438f03cb1d4Srmind 	;
439f03cb1d4Srmind 
4408f6547d8Srmind /*
4418f6547d8Srmind  * Group and dynamic ruleset definition.
4428f6547d8Srmind  */
4438f6547d8Srmind 
444f03cb1d4Srmind group
445c6e77e2aSrmind 	: GROUP group_opts
446f03cb1d4Srmind 	{
447348a4177Srmind 		/* Build a group.  Increase the nesting level. */
448c6e77e2aSrmind 		npfctl_build_group($2.rg_name, $2.rg_attr,
449d1d2e2c9Srmind 		    $2.rg_ifname, $2.rg_default);
450f03cb1d4Srmind 	}
45137527ec6Srmind 	  ruleset_block
45237527ec6Srmind 	{
45337527ec6Srmind 		/* Decrease the nesting level. */
45437527ec6Srmind 		npfctl_build_group_end();
45537527ec6Srmind 	}
456f03cb1d4Srmind 	;
457f03cb1d4Srmind 
4587b486642Srmind ruleset
459c6e77e2aSrmind 	: RULESET group_opts
4607b486642Srmind 	{
4617b486642Srmind 		/* Ruleset is a dynamic group. */
462c6e77e2aSrmind 		npfctl_build_group($2.rg_name, $2.rg_attr | NPF_RULE_DYNAMIC,
463d1d2e2c9Srmind 		    $2.rg_ifname, $2.rg_default);
4647b486642Srmind 		npfctl_build_group_end();
4657b486642Srmind 	}
466f03cb1d4Srmind 	;
467f03cb1d4Srmind 
468c6e77e2aSrmind group_dir
469c6e77e2aSrmind 	: FORW		{ $$ = NPF_RULE_FORW; }
470c6e77e2aSrmind 	| rule_dir
471c6e77e2aSrmind 	;
472c6e77e2aSrmind 
473c6e77e2aSrmind group_opts
474f03cb1d4Srmind 	: DEFAULT
475f03cb1d4Srmind 	{
47637527ec6Srmind 		memset(&$$, 0, sizeof(rule_group_t));
47737527ec6Srmind 		$$.rg_default = true;
478f03cb1d4Srmind 	}
479d1d2e2c9Srmind 	| STRING group_dir on_ifname
480f03cb1d4Srmind 	{
48137527ec6Srmind 		memset(&$$, 0, sizeof(rule_group_t));
482c6e77e2aSrmind 		$$.rg_name = $1;
483c6e77e2aSrmind 		$$.rg_attr = $2;
484d1d2e2c9Srmind 		$$.rg_ifname = $3;
485f03cb1d4Srmind 	}
486f03cb1d4Srmind 	;
487f03cb1d4Srmind 
48837527ec6Srmind ruleset_block
4897b486642Srmind 	: CURLY_OPEN ruleset_def CURLY_CLOSE
490f03cb1d4Srmind 	;
491f03cb1d4Srmind 
4927b486642Srmind ruleset_def
4939ff93001Sriastradh 	: ruleset_def SEPLINE rule_group
49437527ec6Srmind 	| rule_group
495f03cb1d4Srmind 	;
496f03cb1d4Srmind 
49737527ec6Srmind rule_group
49837527ec6Srmind 	: rule
49937527ec6Srmind 	| group
5007b486642Srmind 	| ruleset
50137527ec6Srmind 	|
50285aa89dfSrmind 	;
50337527ec6Srmind 
5048f6547d8Srmind /*
5058f6547d8Srmind  * Rule and misc.
5068f6547d8Srmind  */
5078f6547d8Srmind 
508f03cb1d4Srmind rule
509d1d2e2c9Srmind 	: block_or_pass opt_stateful rule_dir opt_final on_ifname
510ec3d0e07Srmind 	  opt_family opt_proto all_or_filt_opts opt_apply
511f03cb1d4Srmind 	{
512ba11b3c0Srmind 		npfctl_build_rule($1 | $2 | $3 | $4, $5,
513c6e77e2aSrmind 		    $6, &$7, &$8, NULL, $9);
514c6e77e2aSrmind 	}
515d1d2e2c9Srmind 	| block_or_pass opt_stateful rule_dir opt_final on_ifname
516c6e77e2aSrmind 	  PCAP_FILTER STRING opt_apply
517c6e77e2aSrmind 	{
518c6e77e2aSrmind 		npfctl_build_rule($1 | $2 | $3 | $4, $5,
519c6e77e2aSrmind 		    AF_UNSPEC, NULL, NULL, $7, $8);
520f03cb1d4Srmind 	}
521f03cb1d4Srmind 	;
522f03cb1d4Srmind 
523f03cb1d4Srmind block_or_pass
524f03cb1d4Srmind 	: BLOCK block_opts	{ $$ = $2; }
525f03cb1d4Srmind 	| PASS			{ $$ = NPF_RULE_PASS; }
526f03cb1d4Srmind 	;
527f03cb1d4Srmind 
528f03cb1d4Srmind rule_dir
529f03cb1d4Srmind 	: IN			{ $$ = NPF_RULE_IN; }
530f03cb1d4Srmind 	| OUT			{ $$ = NPF_RULE_OUT; }
531f03cb1d4Srmind 	|			{ $$ = NPF_RULE_IN | NPF_RULE_OUT; }
532f03cb1d4Srmind 	;
533f03cb1d4Srmind 
534ba11b3c0Srmind opt_final
535ba11b3c0Srmind 	: FINAL			{ $$ = NPF_RULE_FINAL; }
536f03cb1d4Srmind 	|			{ $$ = 0; }
537f03cb1d4Srmind 	;
538f03cb1d4Srmind 
539d1d2e2c9Srmind on_ifname
540348a4177Srmind 	: ON ifref		{ $$ = $2; }
541d1d2e2c9Srmind 	|			{ $$ = NULL; }
542f03cb1d4Srmind 	;
543f03cb1d4Srmind 
544ec3d0e07Srmind afamily
545348a4177Srmind 	: INET4			{ $$ = AF_INET; }
546ec3d0e07Srmind 	| INET6			{ $$ = AF_INET6; }
547ec3d0e07Srmind 	;
548ec3d0e07Srmind 
54935bd148cSrmind maybe_not
55035bd148cSrmind 	: EXCL_MARK		{ $$ = true; }
55135bd148cSrmind 	|			{ $$ = false; }
55235bd148cSrmind 	;
55335bd148cSrmind 
554f75d4435Srmind opt_family
555ec3d0e07Srmind 	: FAMILY afamily	{ $$ = $2; }
556f75d4435Srmind 	|			{ $$ = AF_UNSPEC; }
557f03cb1d4Srmind 	;
558f03cb1d4Srmind 
559a6f5b6a3Srmind proto
560f03cb1d4Srmind 	: PROTO TCP tcp_flags_and_mask
561f03cb1d4Srmind 	{
562f03cb1d4Srmind 		$$.op_proto = IPPROTO_TCP;
563f03cb1d4Srmind 		$$.op_opts = $3;
564f03cb1d4Srmind 	}
565f03cb1d4Srmind 	| PROTO ICMP icmp_type_and_code
566f03cb1d4Srmind 	{
567f03cb1d4Srmind 		$$.op_proto = IPPROTO_ICMP;
568f03cb1d4Srmind 		$$.op_opts = $3;
569f03cb1d4Srmind 	}
570afd9e22aSspz 	| PROTO ICMP6 icmp_type_and_code
571afd9e22aSspz 	{
572afd9e22aSspz 		$$.op_proto = IPPROTO_ICMPV6;
573afd9e22aSspz 		$$.op_opts = $3;
574afd9e22aSspz 	}
575f75d4435Srmind 	| PROTO some_name
576f03cb1d4Srmind 	{
577f75d4435Srmind 		$$.op_proto = npfctl_protono($2);
578f75d4435Srmind 		$$.op_opts = NULL;
579f75d4435Srmind 	}
580f2174d83Schristos 	| PROTO number
581f75d4435Srmind 	{
582f75d4435Srmind 		$$.op_proto = $2;
583f03cb1d4Srmind 		$$.op_opts = NULL;
584f03cb1d4Srmind 	}
585a6f5b6a3Srmind 	;
586a6f5b6a3Srmind 
587a6f5b6a3Srmind opt_proto
588a6f5b6a3Srmind 	: proto			{ $$ = $1; }
589f03cb1d4Srmind 	|
590f03cb1d4Srmind 	{
591f03cb1d4Srmind 		$$.op_proto = -1;
592f03cb1d4Srmind 		$$.op_opts = NULL;
593f03cb1d4Srmind 	}
594f03cb1d4Srmind 	;
595f03cb1d4Srmind 
596f03cb1d4Srmind all_or_filt_opts
597f03cb1d4Srmind 	: ALL
598f03cb1d4Srmind 	{
59935bd148cSrmind 		$$.fo_finvert = false;
600add921fbSrmind 		$$.fo_from.ap_netaddr = NULL;
601add921fbSrmind 		$$.fo_from.ap_portrange = NULL;
60235bd148cSrmind 		$$.fo_tinvert = false;
603add921fbSrmind 		$$.fo_to.ap_netaddr = NULL;
604add921fbSrmind 		$$.fo_to.ap_portrange = NULL;
605f03cb1d4Srmind 	}
606f03cb1d4Srmind 	| filt_opts	{ $$ = $1; }
607f03cb1d4Srmind 	;
608f03cb1d4Srmind 
609ba11b3c0Srmind opt_stateful
610f75d4435Srmind 	: STATEFUL	{ $$ = NPF_RULE_STATEFUL; }
611196178afSrmind 	| STATEFUL_ENDS	{ $$ = NPF_RULE_STATEFUL | NPF_RULE_MULTIENDS; }
612f03cb1d4Srmind 	|		{ $$ = 0; }
613f03cb1d4Srmind 	;
614f03cb1d4Srmind 
615f03cb1d4Srmind opt_apply
616f03cb1d4Srmind 	: APPLY STRING	{ $$ = $2; }
617f03cb1d4Srmind 	|		{ $$ = NULL; }
618f03cb1d4Srmind 	;
619f03cb1d4Srmind 
620f03cb1d4Srmind block_opts
621f03cb1d4Srmind 	: RETURNRST	{ $$ = NPF_RULE_RETRST; }
622f03cb1d4Srmind 	| RETURNICMP	{ $$ = NPF_RULE_RETICMP; }
623f03cb1d4Srmind 	| RETURN	{ $$ = NPF_RULE_RETRST | NPF_RULE_RETICMP; }
624f03cb1d4Srmind 	|		{ $$ = 0; }
625f03cb1d4Srmind 	;
626f03cb1d4Srmind 
627f03cb1d4Srmind filt_opts
62835bd148cSrmind 	: FROM maybe_not filt_addr port_range TO maybe_not filt_addr port_range
629f03cb1d4Srmind 	{
63035bd148cSrmind 		$$.fo_finvert = $2;
63135bd148cSrmind 		$$.fo_from.ap_netaddr = $3;
63235bd148cSrmind 		$$.fo_from.ap_portrange = $4;
63335bd148cSrmind 		$$.fo_tinvert = $6;
63435bd148cSrmind 		$$.fo_to.ap_netaddr = $7;
63535bd148cSrmind 		$$.fo_to.ap_portrange = $8;
636f03cb1d4Srmind 	}
63735bd148cSrmind 	| FROM maybe_not filt_addr port_range
638f03cb1d4Srmind 	{
63935bd148cSrmind 		$$.fo_finvert = $2;
64035bd148cSrmind 		$$.fo_from.ap_netaddr = $3;
64135bd148cSrmind 		$$.fo_from.ap_portrange = $4;
64235bd148cSrmind 		$$.fo_tinvert = false;
643add921fbSrmind 		$$.fo_to.ap_netaddr = NULL;
644add921fbSrmind 		$$.fo_to.ap_portrange = NULL;
645f03cb1d4Srmind 	}
64635bd148cSrmind 	| TO maybe_not filt_addr port_range
647f03cb1d4Srmind 	{
64835bd148cSrmind 		$$.fo_finvert = false;
649add921fbSrmind 		$$.fo_from.ap_netaddr = NULL;
650add921fbSrmind 		$$.fo_from.ap_portrange = NULL;
65135bd148cSrmind 		$$.fo_tinvert = $2;
65235bd148cSrmind 		$$.fo_to.ap_netaddr = $3;
65335bd148cSrmind 		$$.fo_to.ap_portrange = $4;
654f03cb1d4Srmind 	}
655f03cb1d4Srmind 	;
656f03cb1d4Srmind 
657f03cb1d4Srmind filt_addr
658dceaabc9Schristos 	: list			{ $$ = $1; }
659dceaabc9Schristos 	| addr_or_ifaddr	{ $$ = $1; }
660df8b1943Srmind 	| dynamic_ifaddrs	{ $$ = npfctl_ifnet_table($1); }
661f03cb1d4Srmind 	| TABLE_ID		{ $$ = npfctl_parse_table_id($1); }
662f03cb1d4Srmind 	| ANY			{ $$ = NULL; }
663f03cb1d4Srmind 	;
664f03cb1d4Srmind 
665f03cb1d4Srmind addr_and_mask
666f2174d83Schristos 	: addr SLASH number
667f03cb1d4Srmind 	{
668f03cb1d4Srmind 		$$ = npfctl_parse_fam_addr_mask($1, NULL, &$3);
669f03cb1d4Srmind 	}
670f03cb1d4Srmind 	| addr SLASH addr
671f03cb1d4Srmind 	{
672f03cb1d4Srmind 		$$ = npfctl_parse_fam_addr_mask($1, $3, NULL);
673f03cb1d4Srmind 	}
674f03cb1d4Srmind 	| addr
675f03cb1d4Srmind 	{
676f03cb1d4Srmind 		$$ = npfctl_parse_fam_addr_mask($1, NULL, NULL);
677f03cb1d4Srmind 	}
678f03cb1d4Srmind 	;
679f03cb1d4Srmind 
680348a4177Srmind addr_or_ifaddr
681f75d4435Srmind 	: addr_and_mask
682f75d4435Srmind 	{
683f75d4435Srmind 		assert($1 != NULL);
684f75d4435Srmind 		$$ = $1;
685f75d4435Srmind 	}
686df8b1943Srmind 	| static_ifaddrs
6878094cc3dSrmind 	{
6885a32644fSchristos 		if (npfvar_get_count($1) != 1)
6895a32644fSchristos 			yyerror("multiple interfaces are not supported");
690ec3d0e07Srmind 		ifnet_addr_t *ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0);
691ec3d0e07Srmind 		$$ = ifna->ifna_addrs;
6928094cc3dSrmind 	}
6938094cc3dSrmind 	| VAR_ID
6948094cc3dSrmind 	{
6958094cc3dSrmind 		npfvar_t *vp = npfvar_lookup($1);
696f0ae964eSchristos 		int type = npfvar_get_type(vp, 0);
697ec3d0e07Srmind 		ifnet_addr_t *ifna;
6988094cc3dSrmind 
699f0ae964eSchristos again:
7008094cc3dSrmind 		switch (type) {
701f0ae964eSchristos 		case NPFVAR_IDENTIFIER:
702f0ae964eSchristos 		case NPFVAR_STRING:
703f0ae964eSchristos 			vp = npfctl_parse_ifnet(npfvar_expand_string(vp),
704f0ae964eSchristos 			    AF_UNSPEC);
705f0ae964eSchristos 			type = npfvar_get_type(vp, 0);
706f0ae964eSchristos 			goto again;
7078094cc3dSrmind 		case NPFVAR_FAM:
708df8b1943Srmind 		case NPFVAR_TABLE:
7098094cc3dSrmind 			$$ = vp;
7108094cc3dSrmind 			break;
711ec3d0e07Srmind 		case NPFVAR_INTERFACE:
71215718026Srmind 			$$ = NULL;
71315718026Srmind 			for (u_int i = 0; i < npfvar_get_count(vp); i++) {
71415718026Srmind 				ifna = npfvar_get_data(vp, type, i);
71515718026Srmind 				$$ = npfvar_add_elements($$, ifna->ifna_addrs);
71615718026Srmind 			}
717ec3d0e07Srmind 			break;
7188094cc3dSrmind 		case -1:
719ec3d0e07Srmind 			yyerror("undefined variable '%s'", $1);
7208094cc3dSrmind 			break;
7218094cc3dSrmind 		default:
722ec3d0e07Srmind 			yyerror("wrong variable '%s' type '%s' for address "
723ec3d0e07Srmind 			    "or interface", $1, npfvar_type(type));
7248094cc3dSrmind 			break;
7258094cc3dSrmind 		}
7268094cc3dSrmind 	}
727f03cb1d4Srmind 	;
728f03cb1d4Srmind 
729f03cb1d4Srmind addr
730f03cb1d4Srmind 	: IPV4ADDR	{ $$ = $1; }
731f03cb1d4Srmind 	| IPV6ADDR	{ $$ = $1; }
732f03cb1d4Srmind 	;
733f03cb1d4Srmind 
734f03cb1d4Srmind port_range
735f03cb1d4Srmind 	: PORT port		/* just port */
736f03cb1d4Srmind 	{
737f03cb1d4Srmind 		$$ = npfctl_parse_port_range($2, $2);
738f03cb1d4Srmind 	}
739add921fbSrmind 	| PORT port MINUS port	/* port from-to */
740f03cb1d4Srmind 	{
741f03cb1d4Srmind 		$$ = npfctl_parse_port_range($2, $4);
742f03cb1d4Srmind 	}
743add921fbSrmind 	| PORT VAR_ID
744add921fbSrmind 	{
7456c441296Srmind 		npfvar_t *vp = npfvar_lookup($2);
7466c441296Srmind 		$$ = npfctl_parse_port_range_variable($2, vp);
747ff24200fSchristos 	}
7486c441296Srmind 	| PORT list
749f03cb1d4Srmind 	{
7506c441296Srmind 		$$ = npfctl_parse_port_range_variable(NULL, $2);
751f03cb1d4Srmind 	}
7526c441296Srmind 	|			{ $$ = NULL; }
753f03cb1d4Srmind 	;
754f03cb1d4Srmind 
755f03cb1d4Srmind port
756f2174d83Schristos 	: number	{ $$ = $1; }
757f03cb1d4Srmind 	| IDENTIFIER	{ $$ = npfctl_portno($1); }
758bd928debSchristos 	| STRING	{ $$ = npfctl_portno($1); }
759f03cb1d4Srmind 	;
760f03cb1d4Srmind 
761f03cb1d4Srmind icmp_type_and_code
762f03cb1d4Srmind 	: ICMPTYPE icmp_type
763f03cb1d4Srmind 	{
764afd9e22aSspz 		$$ = npfctl_parse_icmp($<num>0, $2, -1);
765f03cb1d4Srmind 	}
766f2174d83Schristos 	| ICMPTYPE icmp_type CODE number
767f03cb1d4Srmind 	{
768afd9e22aSspz 		$$ = npfctl_parse_icmp($<num>0, $2, $4);
769f03cb1d4Srmind 	}
770f03cb1d4Srmind 	| ICMPTYPE icmp_type CODE IDENTIFIER
771f03cb1d4Srmind 	{
772ec3d0e07Srmind 		$$ = npfctl_parse_icmp($<num>0, $2,
773ec3d0e07Srmind 		    npfctl_icmpcode($<num>0, $2, $4));
774f03cb1d4Srmind 	}
775f03cb1d4Srmind 	| ICMPTYPE icmp_type CODE VAR_ID
776f03cb1d4Srmind 	{
777f03cb1d4Srmind 		char *s = npfvar_expand_string(npfvar_lookup($4));
778ec3d0e07Srmind 		$$ = npfctl_parse_icmp($<num>0, $2,
779ec3d0e07Srmind 		    npfctl_icmpcode($<num>0, $2, s));
780f03cb1d4Srmind 	}
78111243735Srmind 	|		{ $$ = NULL; }
782f03cb1d4Srmind 	;
783f03cb1d4Srmind 
784f03cb1d4Srmind tcp_flags_and_mask
785f03cb1d4Srmind 	: FLAGS tcp_flags SLASH tcp_flags
786f03cb1d4Srmind 	{
787f03cb1d4Srmind 		npfvar_add_elements($2, $4);
788f03cb1d4Srmind 		$$ = $2;
789f03cb1d4Srmind 	}
790f03cb1d4Srmind 	| FLAGS tcp_flags
791f03cb1d4Srmind 	{
7925a32644fSchristos 		if (npfvar_get_count($2) != 1)
7935a32644fSchristos 			yyerror("multiple tcpflags are not supported");
794f03cb1d4Srmind 		char *s = npfvar_get_data($2, NPFVAR_TCPFLAG, 0);
795f03cb1d4Srmind 		npfvar_add_elements($2, npfctl_parse_tcpflag(s));
796f03cb1d4Srmind 		$$ = $2;
797f03cb1d4Srmind 	}
798f03cb1d4Srmind 	|		{ $$ = NULL; }
799f03cb1d4Srmind 	;
800f03cb1d4Srmind 
801f03cb1d4Srmind tcp_flags
802f03cb1d4Srmind 	: IDENTIFIER	{ $$ = npfctl_parse_tcpflag($1); }
803f03cb1d4Srmind 	;
804f03cb1d4Srmind 
805f03cb1d4Srmind icmp_type
806f2174d83Schristos 	: number	{ $$ = $1; }
807afd9e22aSspz 	| IDENTIFIER	{ $$ = npfctl_icmptype($<num>-1, $1); }
808f03cb1d4Srmind 	| VAR_ID
809f03cb1d4Srmind 	{
810f03cb1d4Srmind 		char *s = npfvar_expand_string(npfvar_lookup($1));
811afd9e22aSspz 		$$ = npfctl_icmptype($<num>-1, s);
812f03cb1d4Srmind 	}
813f03cb1d4Srmind 	;
814f03cb1d4Srmind 
815d1d2e2c9Srmind ifname
816f75d4435Srmind 	: some_name
817f03cb1d4Srmind 	{
818d1d2e2c9Srmind 		npfctl_note_interface($1);
819d1d2e2c9Srmind 		$$ = $1;
820f03cb1d4Srmind 	}
821f03cb1d4Srmind 	| VAR_ID
822f03cb1d4Srmind 	{
823f03cb1d4Srmind 		npfvar_t *vp = npfvar_lookup($1);
824ff24200fSchristos 		const int type = npfvar_get_type(vp, 0);
825ec3d0e07Srmind 		ifnet_addr_t *ifna;
826f03cb1d4Srmind 
827f03cb1d4Srmind 		switch (type) {
828f03cb1d4Srmind 		case NPFVAR_STRING:
829ec3d0e07Srmind 		case NPFVAR_IDENTIFIER:
830d1d2e2c9Srmind 			$$ = npfvar_expand_string(vp);
831f03cb1d4Srmind 			break;
832ec3d0e07Srmind 		case NPFVAR_INTERFACE:
8335a32644fSchristos 			if (npfvar_get_count(vp) != 1)
8345a32644fSchristos 				yyerror(
8355a32644fSchristos 				    "multiple interfaces are not supported");
836ec3d0e07Srmind 			ifna = npfvar_get_data(vp, type, 0);
837d1d2e2c9Srmind 			$$ = ifna->ifna_name;
838ec3d0e07Srmind 			break;
839f03cb1d4Srmind 		case -1:
840f03cb1d4Srmind 			yyerror("undefined variable '%s' for interface", $1);
841f03cb1d4Srmind 			break;
842f03cb1d4Srmind 		default:
843f03cb1d4Srmind 			yyerror("wrong variable '%s' type '%s' for interface",
844f03cb1d4Srmind 			    $1, npfvar_type(type));
845f03cb1d4Srmind 			break;
846f03cb1d4Srmind 		}
847d1d2e2c9Srmind 		npfctl_note_interface($$);
848f03cb1d4Srmind 	}
849f03cb1d4Srmind 	;
850f03cb1d4Srmind 
851df8b1943Srmind static_ifaddrs
852348a4177Srmind 	: afamily PAR_OPEN ifname PAR_CLOSE
853348a4177Srmind 	{
854348a4177Srmind 		$$ = npfctl_parse_ifnet($3, $1);
855348a4177Srmind 	}
856348a4177Srmind 	;
857348a4177Srmind 
858df8b1943Srmind dynamic_ifaddrs
859df8b1943Srmind 	: IFADDRS PAR_OPEN ifname PAR_CLOSE
860df8b1943Srmind 	{
861df8b1943Srmind 		$$ = $3;
862df8b1943Srmind 	}
863df8b1943Srmind 	;
864df8b1943Srmind 
865348a4177Srmind ifref
866348a4177Srmind 	: ifname
867df8b1943Srmind 	| dynamic_ifaddrs
868df8b1943Srmind 	| static_ifaddrs
869348a4177Srmind 	{
8705a32644fSchristos 		if (npfvar_get_count($1) != 1)
8715a32644fSchristos 			yyerror("multiple interfaces are not supported");
872348a4177Srmind 		ifnet_addr_t *ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0);
873348a4177Srmind 		npfctl_note_interface(ifna->ifna_name);
874348a4177Srmind 		$$ = ifna->ifna_name;
875348a4177Srmind 	}
876348a4177Srmind 	;
877348a4177Srmind 
878f2174d83Schristos number
879f2174d83Schristos 	: HEX		{ $$ = $1; }
880f2174d83Schristos 	| NUM		{ $$ = $1; }
881f2174d83Schristos 	;
882f2174d83Schristos 
883f75d4435Srmind some_name
884f03cb1d4Srmind 	: IDENTIFIER	{ $$ = $1; }
885f03cb1d4Srmind 	| STRING	{ $$ = $1; }
886f03cb1d4Srmind 	;
887f03cb1d4Srmind 
888f03cb1d4Srmind %%
889