npf_parse.y revision 1.42 1 /* $NetBSD: npf_parse.y,v 1.42 2017/01/19 20:18:17 rmind Exp $ */
2
3 /*-
4 * Copyright (c) 2011-2017 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Martin Husemann, Christos Zoulas and Mindaugas Rasiukevicius.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 %{
33
34 #include <err.h>
35 #include <netdb.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #ifdef __NetBSD__
40 #include <vis.h>
41 #endif
42
43 #include "npfctl.h"
44
45 #define YYSTACKSIZE 4096
46
47 int yyparsetarget;
48 const char * yyfilename;
49
50 extern int yylineno, yycolumn;
51 extern int yylex(void);
52
53 void
54 yyerror(const char *fmt, ...)
55 {
56 extern int yyleng;
57 extern char *yytext;
58
59 char *msg, *context = estrndup(yytext, yyleng);
60 bool eol = (*context == '\n');
61 va_list ap;
62
63 va_start(ap, fmt);
64 vasprintf(&msg, fmt, ap);
65 va_end(ap);
66
67 fprintf(stderr, "%s:%d:%d: %s", yyfilename,
68 yylineno - (int)eol, yycolumn, msg);
69 if (!eol) {
70 #ifdef __NetBSD__
71 size_t len = strlen(context);
72 char *dst = ecalloc(1, len * 4 + 1);
73
74 strvisx(dst, context, len, VIS_WHITE|VIS_CSTYLE);
75 context = dst
76 #endif
77 fprintf(stderr, " near '%s'", context);
78 }
79 fprintf(stderr, "\n");
80 exit(EXIT_FAILURE);
81 }
82
83 #define CHECK_PARSER_FILE \
84 if (yyparsetarget != NPFCTL_PARSE_FILE) \
85 yyerror("rule must be in the group");
86
87 #define CHECK_PARSER_STRING \
88 if (yyparsetarget != NPFCTL_PARSE_STRING) \
89 yyerror("invalid rule syntax");
90
91 %}
92
93 %token ALG
94 %token ALGO
95 %token ALL
96 %token ANY
97 %token APPLY
98 %token ARROWBOTH
99 %token ARROWLEFT
100 %token ARROWRIGHT
101 %token BLOCK
102 %token BPFJIT
103 %token CDB
104 %token CURLY_CLOSE
105 %token CURLY_OPEN
106 %token CODE
107 %token COLON
108 %token COMMA
109 %token DEFAULT
110 %token TDYNAMIC
111 %token TSTATIC
112 %token EQ
113 %token EXCL_MARK
114 %token TFILE
115 %token FLAGS
116 %token FROM
117 %token GROUP
118 %token HASH
119 %token ICMPTYPE
120 %token ID
121 %token IN
122 %token INET4
123 %token INET6
124 %token IFADDRS
125 %token INTERFACE
126 %token MAP
127 %token MINUS
128 %token NAME
129 %token NPT66
130 %token ON
131 %token OFF
132 %token OUT
133 %token PAR_CLOSE
134 %token PAR_OPEN
135 %token PASS
136 %token PCAP_FILTER
137 %token PORT
138 %token PROCEDURE
139 %token PROTO
140 %token FAMILY
141 %token FINAL
142 %token FORW
143 %token RETURN
144 %token RETURNICMP
145 %token RETURNRST
146 %token RULESET
147 %token SEPLINE
148 %token SET
149 %token SLASH
150 %token STATEFUL
151 %token STATEFUL_ENDS
152 %token TABLE
153 %token TCP
154 %token TO
155 %token TREE
156 %token TYPE
157 %token <num> ICMP
158 %token <num> ICMP6
159
160 %token <num> HEX
161 %token <str> IDENTIFIER
162 %token <str> IPV4ADDR
163 %token <str> IPV6ADDR
164 %token <num> NUM
165 %token <fpnum> FPNUM
166 %token <str> STRING
167 %token <str> TABLE_ID
168 %token <str> VAR_ID
169
170 %type <str> addr, some_name, table_store, dynamic_ifaddrs
171 %type <str> proc_param_val, opt_apply, ifname, on_ifname, ifref
172 %type <num> port, opt_final, number, afamily, opt_family
173 %type <num> block_or_pass, rule_dir, group_dir, block_opts
174 %type <num> maybe_not, opt_stateful, icmp_type, table_type
175 %type <num> map_sd, map_algo, map_type
176 %type <var> static_ifaddrs, addr_or_ifaddr
177 %type <var> port_range, icmp_type_and_code
178 %type <var> filt_addr, addr_and_mask, tcp_flags, tcp_flags_and_mask
179 %type <var> procs, proc_call, proc_param_list, proc_param
180 %type <var> element, list_elems, list, value
181 %type <addrport> mapseg
182 %type <filtopts> filt_opts, all_or_filt_opts
183 %type <optproto> opt_proto
184 %type <rulegroup> group_opts
185 %type <tf> onoff
186
187 %union {
188 char * str;
189 bool tf;
190 unsigned long num;
191 double fpnum;
192 npfvar_t * var;
193 addr_port_t addrport;
194 filt_opts_t filtopts;
195 opt_proto_t optproto;
196 rule_group_t rulegroup;
197 }
198
199 %%
200
201 input
202 : { CHECK_PARSER_FILE } lines
203 | { CHECK_PARSER_STRING } rule
204 ;
205
206 lines
207 : lines SEPLINE line
208 | line
209 ;
210
211 line
212 : vardef
213 | table
214 | map
215 | group
216 | rproc
217 | alg
218 | set
219 |
220 ;
221
222 alg
223 : ALG STRING
224 {
225 npfctl_build_alg($2);
226 }
227 ;
228
229 onoff
230 : ON {
231 $$ = true;
232 }
233 | OFF {
234 $$ = false;
235 }
236 ;
237
238 set
239 : SET BPFJIT onoff {
240 npfctl_bpfjit($3);
241 }
242 ;
243
244 /*
245 * A value - an element or a list of elements.
246 * Can be assigned to a variable or used inline.
247 */
248
249 vardef
250 : VAR_ID EQ value
251 {
252 npfvar_add($3, $1);
253 }
254 ;
255
256 value
257 : element
258 | list
259 ;
260
261 list
262 : CURLY_OPEN list_elems CURLY_CLOSE
263 {
264 $$ = $2;
265 }
266 ;
267
268 list_elems
269 : list_elems COMMA element
270 {
271 npfvar_add_elements($1, $3);
272 }
273 | element
274 ;
275
276 element
277 : IDENTIFIER
278 {
279 $$ = npfvar_create_from_string(NPFVAR_IDENTIFIER, $1);
280 }
281 | STRING
282 {
283 $$ = npfvar_create_from_string(NPFVAR_STRING, $1);
284 }
285 | number MINUS number
286 {
287 $$ = npfctl_parse_port_range($1, $3);
288 }
289 | number
290 {
291 $$ = npfvar_create_element(NPFVAR_NUM, &$1, sizeof($1));
292 }
293 | VAR_ID
294 {
295 $$ = npfvar_create_from_string(NPFVAR_VAR_ID, $1);
296 }
297 | TABLE_ID { $$ = npfctl_parse_table_id($1); }
298 | dynamic_ifaddrs { $$ = npfctl_ifnet_table($1); }
299 | static_ifaddrs { $$ = $1; }
300 | addr_and_mask { $$ = $1; }
301 ;
302
303 /*
304 * Table definition.
305 */
306
307 table
308 : TABLE TABLE_ID TYPE table_type table_store
309 {
310 npfctl_build_table($2, $4, $5);
311 }
312 ;
313
314 table_type
315 : HASH { $$ = NPF_TABLE_HASH; }
316 | TREE { $$ = NPF_TABLE_TREE; }
317 | CDB { $$ = NPF_TABLE_CDB; }
318 ;
319
320 table_store
321 : TDYNAMIC { $$ = NULL; }
322 | TFILE STRING { $$ = $2; }
323 ;
324
325 /*
326 * Map definition.
327 */
328
329 map_sd
330 : TSTATIC { $$ = NPFCTL_NAT_STATIC; }
331 | TDYNAMIC { $$ = NPFCTL_NAT_DYNAMIC; }
332 | { $$ = NPFCTL_NAT_DYNAMIC; }
333 ;
334
335 map_algo
336 : ALGO NPT66 { $$ = NPF_ALGO_NPT66; }
337 | { $$ = 0; }
338 ;
339
340 map_type
341 : ARROWBOTH { $$ = NPF_NATIN | NPF_NATOUT; }
342 | ARROWLEFT { $$ = NPF_NATIN; }
343 | ARROWRIGHT { $$ = NPF_NATOUT; }
344 ;
345
346 mapseg
347 : addr_or_ifaddr port_range
348 {
349 $$.ap_netaddr = $1;
350 $$.ap_portrange = $2;
351 }
352 ;
353
354 map
355 : MAP ifref map_sd map_algo mapseg map_type mapseg
356 PASS opt_proto filt_opts
357 {
358 npfctl_build_natseg($3, $6, $2, &$5, &$7, &$9, &$10, $4);
359 }
360 | MAP ifref map_sd map_algo opt_proto mapseg map_type mapseg
361 {
362 npfctl_build_natseg($3, $7, $2, &$6, &$8, &$5, NULL, $4);
363 }
364 | MAP RULESET group_opts
365 {
366 npfctl_build_maprset($3.rg_name, $3.rg_attr, $3.rg_ifname);
367 }
368 ;
369
370 /*
371 * Rule procedure definition and its parameters.
372 */
373
374 rproc
375 : PROCEDURE STRING CURLY_OPEN procs CURLY_CLOSE
376 {
377 npfctl_build_rproc($2, $4);
378 }
379 ;
380
381 procs
382 : procs SEPLINE proc_call
383 {
384 $$ = npfvar_add_elements($1, $3);
385 }
386 | proc_call { $$ = $1; }
387 ;
388
389 proc_call
390 : IDENTIFIER COLON proc_param_list
391 {
392 proc_call_t pc;
393
394 pc.pc_name = estrdup($1);
395 pc.pc_opts = $3;
396
397 $$ = npfvar_create_element(NPFVAR_PROC, &pc, sizeof(pc));
398 }
399 | { $$ = NULL; }
400 ;
401
402 proc_param_list
403 : proc_param_list COMMA proc_param
404 {
405 $$ = npfvar_add_elements($1, $3);
406 }
407 | proc_param { $$ = $1; }
408 | { $$ = NULL; }
409 ;
410
411 proc_param
412 : some_name proc_param_val
413 {
414 proc_param_t pp;
415
416 pp.pp_param = estrdup($1);
417 pp.pp_value = $2 ? estrdup($2) : NULL;
418
419 $$ = npfvar_create_element(NPFVAR_PROC_PARAM, &pp, sizeof(pp));
420 }
421 ;
422
423 proc_param_val
424 : some_name { $$ = $1; }
425 | number { (void)asprintf(&$$, "%ld", $1); }
426 | FPNUM { (void)asprintf(&$$, "%lf", $1); }
427 | { $$ = NULL; }
428 ;
429
430 /*
431 * Group and dynamic ruleset definition.
432 */
433
434 group
435 : GROUP group_opts
436 {
437 /* Build a group. Increase the nesting level. */
438 npfctl_build_group($2.rg_name, $2.rg_attr,
439 $2.rg_ifname, $2.rg_default);
440 }
441 ruleset_block
442 {
443 /* Decrease the nesting level. */
444 npfctl_build_group_end();
445 }
446 ;
447
448 ruleset
449 : RULESET group_opts
450 {
451 /* Ruleset is a dynamic group. */
452 npfctl_build_group($2.rg_name, $2.rg_attr | NPF_RULE_DYNAMIC,
453 $2.rg_ifname, $2.rg_default);
454 npfctl_build_group_end();
455 }
456 ;
457
458 group_dir
459 : FORW { $$ = NPF_RULE_FORW; }
460 | rule_dir
461 ;
462
463 group_opts
464 : DEFAULT
465 {
466 memset(&$$, 0, sizeof(rule_group_t));
467 $$.rg_default = true;
468 }
469 | STRING group_dir on_ifname
470 {
471 memset(&$$, 0, sizeof(rule_group_t));
472 $$.rg_name = $1;
473 $$.rg_attr = $2;
474 $$.rg_ifname = $3;
475 }
476 ;
477
478 ruleset_block
479 : CURLY_OPEN ruleset_def CURLY_CLOSE
480 ;
481
482 ruleset_def
483 : ruleset_def SEPLINE rule_group
484 | rule_group
485 ;
486
487 rule_group
488 : rule
489 | group
490 | ruleset
491 |
492 ;
493
494 /*
495 * Rule and misc.
496 */
497
498 rule
499 : block_or_pass opt_stateful rule_dir opt_final on_ifname
500 opt_family opt_proto all_or_filt_opts opt_apply
501 {
502 npfctl_build_rule($1 | $2 | $3 | $4, $5,
503 $6, &$7, &$8, NULL, $9);
504 }
505 | block_or_pass opt_stateful rule_dir opt_final on_ifname
506 PCAP_FILTER STRING opt_apply
507 {
508 npfctl_build_rule($1 | $2 | $3 | $4, $5,
509 AF_UNSPEC, NULL, NULL, $7, $8);
510 }
511 ;
512
513 block_or_pass
514 : BLOCK block_opts { $$ = $2; }
515 | PASS { $$ = NPF_RULE_PASS; }
516 ;
517
518 rule_dir
519 : IN { $$ = NPF_RULE_IN; }
520 | OUT { $$ = NPF_RULE_OUT; }
521 | { $$ = NPF_RULE_IN | NPF_RULE_OUT; }
522 ;
523
524 opt_final
525 : FINAL { $$ = NPF_RULE_FINAL; }
526 | { $$ = 0; }
527 ;
528
529 on_ifname
530 : ON ifref { $$ = $2; }
531 | { $$ = NULL; }
532 ;
533
534 afamily
535 : INET4 { $$ = AF_INET; }
536 | INET6 { $$ = AF_INET6; }
537 ;
538
539 maybe_not
540 : EXCL_MARK { $$ = true; }
541 | { $$ = false; }
542 ;
543
544 opt_family
545 : FAMILY afamily { $$ = $2; }
546 | { $$ = AF_UNSPEC; }
547 ;
548
549 opt_proto
550 : PROTO TCP tcp_flags_and_mask
551 {
552 $$.op_proto = IPPROTO_TCP;
553 $$.op_opts = $3;
554 }
555 | PROTO ICMP icmp_type_and_code
556 {
557 $$.op_proto = IPPROTO_ICMP;
558 $$.op_opts = $3;
559 }
560 | PROTO ICMP6 icmp_type_and_code
561 {
562 $$.op_proto = IPPROTO_ICMPV6;
563 $$.op_opts = $3;
564 }
565 | PROTO some_name
566 {
567 $$.op_proto = npfctl_protono($2);
568 $$.op_opts = NULL;
569 }
570 | PROTO number
571 {
572 $$.op_proto = $2;
573 $$.op_opts = NULL;
574 }
575 |
576 {
577 $$.op_proto = -1;
578 $$.op_opts = NULL;
579 }
580 ;
581
582 all_or_filt_opts
583 : ALL
584 {
585 $$.fo_finvert = false;
586 $$.fo_from.ap_netaddr = NULL;
587 $$.fo_from.ap_portrange = NULL;
588 $$.fo_tinvert = false;
589 $$.fo_to.ap_netaddr = NULL;
590 $$.fo_to.ap_portrange = NULL;
591 }
592 | filt_opts { $$ = $1; }
593 ;
594
595 opt_stateful
596 : STATEFUL { $$ = NPF_RULE_STATEFUL; }
597 | STATEFUL_ENDS { $$ = NPF_RULE_STATEFUL | NPF_RULE_MULTIENDS; }
598 | { $$ = 0; }
599 ;
600
601 opt_apply
602 : APPLY STRING { $$ = $2; }
603 | { $$ = NULL; }
604 ;
605
606 block_opts
607 : RETURNRST { $$ = NPF_RULE_RETRST; }
608 | RETURNICMP { $$ = NPF_RULE_RETICMP; }
609 | RETURN { $$ = NPF_RULE_RETRST | NPF_RULE_RETICMP; }
610 | { $$ = 0; }
611 ;
612
613 filt_opts
614 : FROM maybe_not filt_addr port_range TO maybe_not filt_addr port_range
615 {
616 $$.fo_finvert = $2;
617 $$.fo_from.ap_netaddr = $3;
618 $$.fo_from.ap_portrange = $4;
619 $$.fo_tinvert = $6;
620 $$.fo_to.ap_netaddr = $7;
621 $$.fo_to.ap_portrange = $8;
622 }
623 | FROM maybe_not filt_addr port_range
624 {
625 $$.fo_finvert = $2;
626 $$.fo_from.ap_netaddr = $3;
627 $$.fo_from.ap_portrange = $4;
628 $$.fo_tinvert = false;
629 $$.fo_to.ap_netaddr = NULL;
630 $$.fo_to.ap_portrange = NULL;
631 }
632 | TO maybe_not filt_addr port_range
633 {
634 $$.fo_finvert = false;
635 $$.fo_from.ap_netaddr = NULL;
636 $$.fo_from.ap_portrange = NULL;
637 $$.fo_tinvert = $2;
638 $$.fo_to.ap_netaddr = $3;
639 $$.fo_to.ap_portrange = $4;
640 }
641 ;
642
643 filt_addr
644 : list { $$ = $1; }
645 | addr_or_ifaddr { $$ = $1; }
646 | dynamic_ifaddrs { $$ = npfctl_ifnet_table($1); }
647 | TABLE_ID { $$ = npfctl_parse_table_id($1); }
648 | ANY { $$ = NULL; }
649 ;
650
651 addr_and_mask
652 : addr SLASH number
653 {
654 $$ = npfctl_parse_fam_addr_mask($1, NULL, &$3);
655 }
656 | addr SLASH addr
657 {
658 $$ = npfctl_parse_fam_addr_mask($1, $3, NULL);
659 }
660 | addr
661 {
662 $$ = npfctl_parse_fam_addr_mask($1, NULL, NULL);
663 }
664 ;
665
666 addr_or_ifaddr
667 : addr_and_mask
668 {
669 assert($1 != NULL);
670 $$ = $1;
671 }
672 | static_ifaddrs
673 {
674 if (npfvar_get_count($1) != 1)
675 yyerror("multiple interfaces are not supported");
676 ifnet_addr_t *ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0);
677 $$ = ifna->ifna_addrs;
678 }
679 | VAR_ID
680 {
681 npfvar_t *vp = npfvar_lookup($1);
682 int type = npfvar_get_type(vp, 0);
683 ifnet_addr_t *ifna;
684
685 again:
686 switch (type) {
687 case NPFVAR_IDENTIFIER:
688 case NPFVAR_STRING:
689 vp = npfctl_parse_ifnet(npfvar_expand_string(vp),
690 AF_UNSPEC);
691 type = npfvar_get_type(vp, 0);
692 goto again;
693 case NPFVAR_FAM:
694 case NPFVAR_TABLE:
695 $$ = vp;
696 break;
697 case NPFVAR_INTERFACE:
698 $$ = NULL;
699 for (u_int i = 0; i < npfvar_get_count(vp); i++) {
700 ifna = npfvar_get_data(vp, type, i);
701 $$ = npfvar_add_elements($$, ifna->ifna_addrs);
702 }
703 break;
704 case -1:
705 yyerror("undefined variable '%s'", $1);
706 break;
707 default:
708 yyerror("wrong variable '%s' type '%s' for address "
709 "or interface", $1, npfvar_type(type));
710 break;
711 }
712 }
713 ;
714
715 addr
716 : IPV4ADDR { $$ = $1; }
717 | IPV6ADDR { $$ = $1; }
718 ;
719
720 port_range
721 : PORT port /* just port */
722 {
723 $$ = npfctl_parse_port_range($2, $2);
724 }
725 | PORT port MINUS port /* port from-to */
726 {
727 $$ = npfctl_parse_port_range($2, $4);
728 }
729 | PORT VAR_ID
730 {
731 npfvar_t *vp = npfvar_lookup($2);
732 $$ = npfctl_parse_port_range_variable($2, vp);
733 }
734 | PORT list
735 {
736 $$ = npfctl_parse_port_range_variable(NULL, $2);
737 }
738 | { $$ = NULL; }
739 ;
740
741 port
742 : number { $$ = $1; }
743 | IDENTIFIER { $$ = npfctl_portno($1); }
744 | STRING { $$ = npfctl_portno($1); }
745 ;
746
747 icmp_type_and_code
748 : ICMPTYPE icmp_type
749 {
750 $$ = npfctl_parse_icmp($<num>0, $2, -1);
751 }
752 | ICMPTYPE icmp_type CODE number
753 {
754 $$ = npfctl_parse_icmp($<num>0, $2, $4);
755 }
756 | ICMPTYPE icmp_type CODE IDENTIFIER
757 {
758 $$ = npfctl_parse_icmp($<num>0, $2,
759 npfctl_icmpcode($<num>0, $2, $4));
760 }
761 | ICMPTYPE icmp_type CODE VAR_ID
762 {
763 char *s = npfvar_expand_string(npfvar_lookup($4));
764 $$ = npfctl_parse_icmp($<num>0, $2,
765 npfctl_icmpcode($<num>0, $2, s));
766 }
767 | { $$ = NULL; }
768 ;
769
770 tcp_flags_and_mask
771 : FLAGS tcp_flags SLASH tcp_flags
772 {
773 npfvar_add_elements($2, $4);
774 $$ = $2;
775 }
776 | FLAGS tcp_flags
777 {
778 if (npfvar_get_count($2) != 1)
779 yyerror("multiple tcpflags are not supported");
780 char *s = npfvar_get_data($2, NPFVAR_TCPFLAG, 0);
781 npfvar_add_elements($2, npfctl_parse_tcpflag(s));
782 $$ = $2;
783 }
784 | { $$ = NULL; }
785 ;
786
787 tcp_flags
788 : IDENTIFIER { $$ = npfctl_parse_tcpflag($1); }
789 ;
790
791 icmp_type
792 : number { $$ = $1; }
793 | IDENTIFIER { $$ = npfctl_icmptype($<num>-1, $1); }
794 | VAR_ID
795 {
796 char *s = npfvar_expand_string(npfvar_lookup($1));
797 $$ = npfctl_icmptype($<num>-1, s);
798 }
799 ;
800
801 ifname
802 : some_name
803 {
804 npfctl_note_interface($1);
805 $$ = $1;
806 }
807 | VAR_ID
808 {
809 npfvar_t *vp = npfvar_lookup($1);
810 const int type = npfvar_get_type(vp, 0);
811 ifnet_addr_t *ifna;
812
813 switch (type) {
814 case NPFVAR_STRING:
815 case NPFVAR_IDENTIFIER:
816 $$ = npfvar_expand_string(vp);
817 break;
818 case NPFVAR_INTERFACE:
819 if (npfvar_get_count(vp) != 1)
820 yyerror(
821 "multiple interfaces are not supported");
822 ifna = npfvar_get_data(vp, type, 0);
823 $$ = ifna->ifna_name;
824 break;
825 case -1:
826 yyerror("undefined variable '%s' for interface", $1);
827 break;
828 default:
829 yyerror("wrong variable '%s' type '%s' for interface",
830 $1, npfvar_type(type));
831 break;
832 }
833 npfctl_note_interface($$);
834 }
835 ;
836
837 static_ifaddrs
838 : afamily PAR_OPEN ifname PAR_CLOSE
839 {
840 $$ = npfctl_parse_ifnet($3, $1);
841 }
842 ;
843
844 dynamic_ifaddrs
845 : IFADDRS PAR_OPEN ifname PAR_CLOSE
846 {
847 $$ = $3;
848 }
849 ;
850
851 ifref
852 : ifname
853 | dynamic_ifaddrs
854 | static_ifaddrs
855 {
856 if (npfvar_get_count($1) != 1)
857 yyerror("multiple interfaces are not supported");
858 ifnet_addr_t *ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0);
859 npfctl_note_interface(ifna->ifna_name);
860 $$ = ifna->ifna_name;
861 }
862 ;
863
864 number
865 : HEX { $$ = $1; }
866 | NUM { $$ = $1; }
867 ;
868
869 some_name
870 : IDENTIFIER { $$ = $1; }
871 | STRING { $$ = $1; }
872 ;
873
874 %%
875