npf_parse.y revision 1.21 1 /* $NetBSD: npf_parse.y,v 1.21 2013/03/18 02:17:49 rmind Exp $ */
2
3 /*-
4 * Copyright (c) 2011-2012 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 and Christos Zoulas.
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 <stdio.h>
35 #include <err.h>
36 #include <vis.h>
37 #include <netdb.h>
38
39 #include "npfctl.h"
40
41 #define YYSTACKSIZE 4096
42
43 int yyparsetarget;
44 const char * yyfilename;
45
46 extern int yylineno, yycolumn;
47 extern int yylex(void);
48
49 /* Variable under construction (bottom up). */
50 static npfvar_t * cvar;
51
52 void
53 yyerror(const char *fmt, ...)
54 {
55 extern int yyleng;
56 extern char *yytext;
57
58 char *msg, *context = estrndup(yytext, yyleng);
59 bool eol = (*context == '\n');
60 va_list ap;
61
62 va_start(ap, fmt);
63 vasprintf(&msg, fmt, ap);
64 va_end(ap);
65
66 fprintf(stderr, "%s:%d:%d: %s", yyfilename,
67 yylineno - (int)eol, yycolumn, msg);
68 if (!eol) {
69 size_t len = strlen(context);
70 char *dst = ecalloc(1, len * 4 + 1);
71
72 strvisx(dst, context, len, VIS_WHITE|VIS_CSTYLE);
73 fprintf(stderr, " near '%s'", dst);
74 }
75 fprintf(stderr, "\n");
76 exit(EXIT_FAILURE);
77 }
78
79 #define CHECK_PARSER_FILE \
80 if (yyparsetarget != NPFCTL_PARSE_FILE) \
81 yyerror("rule must be in the group");
82
83 #define CHECK_PARSER_STRING \
84 if (yyparsetarget != NPFCTL_PARSE_STRING) \
85 yyerror("invalid rule syntax");
86
87 %}
88
89 %token ALL
90 %token ANY
91 %token APPLY
92 %token ARROWBOTH
93 %token ARROWLEFT
94 %token ARROWRIGHT
95 %token BLOCK
96 %token CURLY_CLOSE
97 %token CURLY_OPEN
98 %token CODE
99 %token COLON
100 %token COMMA
101 %token DEFAULT
102 %token TDYNAMIC
103 %token TSTATIC
104 %token EQ
105 %token TFILE
106 %token FLAGS
107 %token FROM
108 %token GROUP
109 %token HASH
110 %token ICMPTYPE
111 %token ID
112 %token IFNET
113 %token IN
114 %token INET
115 %token INET6
116 %token INTERFACE
117 %token MAP
118 %token MINUS
119 %token NAME
120 %token ON
121 %token OUT
122 %token PAR_CLOSE
123 %token PAR_OPEN
124 %token PASS
125 %token PORT
126 %token PROCEDURE
127 %token PROTO
128 %token FAMILY
129 %token FINAL
130 %token FORW
131 %token RETURN
132 %token RETURNICMP
133 %token RETURNRST
134 %token RULESET
135 %token SEPLINE
136 %token SLASH
137 %token STATEFUL
138 %token TABLE
139 %token TCP
140 %token TO
141 %token TREE
142 %token TYPE
143 %token <num> ICMP
144 %token <num> ICMP6
145
146 %token <num> HEX
147 %token <str> IDENTIFIER
148 %token <str> IPV4ADDR
149 %token <str> IPV6ADDR
150 %token <num> NUM
151 %token <fpnum> FPNUM
152 %token <str> STRING
153 %token <str> TABLE_ID
154 %token <str> VAR_ID
155
156 %type <str> addr, some_name, list_elem, table_store, string
157 %type <str> proc_param_val, opt_apply
158 %type <num> ifindex, port, opt_final, on_ifindex
159 %type <num> afamily, opt_family
160 %type <num> block_or_pass, rule_dir, block_opts
161 %type <num> opt_stateful, icmp_type, table_type, map_sd, map_type
162 %type <var> ifnet, addr_or_ifnet, port_range, icmp_type_and_code
163 %type <var> filt_addr, addr_and_mask, tcp_flags, tcp_flags_and_mask
164 %type <var> procs, proc_call, proc_param_list, proc_param
165 %type <addrport> mapseg
166 %type <filtopts> filt_opts, all_or_filt_opts
167 %type <optproto> opt_proto
168 %type <rulegroup> group_attr, group_opt
169
170 %union {
171 char * str;
172 unsigned long num;
173 double fpnum;
174 npfvar_t * var;
175 addr_port_t addrport;
176 filt_opts_t filtopts;
177 opt_proto_t optproto;
178 rule_group_t rulegroup;
179 }
180
181 %%
182
183 input
184 : { CHECK_PARSER_FILE } lines
185 | { CHECK_PARSER_STRING } rule
186 ;
187
188 lines
189 : line SEPLINE lines
190 | line
191 ;
192
193 line
194 : def
195 | table
196 | map
197 | group
198 | rproc
199 |
200 ;
201
202 def
203 : VAR_ID
204 {
205 cvar = npfvar_create($1);
206 npfvar_add(cvar);
207 }
208 EQ definition
209 {
210 cvar = NULL;
211 }
212 ;
213
214 definition
215 : list_elem
216 | listdef
217 ;
218
219 listdef
220 : CURLY_OPEN list_elems CURLY_CLOSE
221 ;
222
223 list_elems
224 : list_elem COMMA list_elems
225 | list_elem
226 ;
227
228 list_elem
229 : IDENTIFIER
230 {
231 npfvar_t *vp = npfvar_create(".identifier");
232 npfvar_add_element(vp, NPFVAR_IDENTIFIER, $1, strlen($1) + 1);
233 npfvar_add_elements(cvar, vp);
234 }
235 | STRING
236 {
237 npfvar_t *vp = npfvar_create(".string");
238 npfvar_add_element(vp, NPFVAR_STRING, $1, strlen($1) + 1);
239 npfvar_add_elements(cvar, vp);
240 }
241 | NUM MINUS NUM
242 {
243 npfvar_t *vp = npfctl_parse_port_range($1, $3);
244 npfvar_add_elements(cvar, vp);
245 }
246 | NUM
247 {
248 npfvar_t *vp = npfvar_create(".num");
249 npfvar_add_element(vp, NPFVAR_NUM, &$1, sizeof($1));
250 npfvar_add_elements(cvar, vp);
251 }
252 | VAR_ID
253 {
254 npfvar_t *vp = npfvar_create(".var_id");
255 npfvar_add_element(vp, NPFVAR_VAR_ID, $1, strlen($1) + 1);
256 npfvar_add_elements(cvar, vp);
257 }
258 | ifnet
259 {
260 npfvar_add_elements(cvar, $1);
261 }
262 | addr_and_mask
263 {
264 npfvar_add_elements(cvar, $1);
265 }
266 ;
267
268 table
269 : TABLE TABLE_ID TYPE table_type table_store
270 {
271 npfctl_build_table($2, $4, $5);
272 }
273 ;
274
275 table_type
276 : HASH { $$ = NPF_TABLE_HASH; }
277 | TREE { $$ = NPF_TABLE_TREE; }
278 ;
279
280 table_store
281 : TDYNAMIC { $$ = NULL; }
282 | TFILE STRING { $$ = $2; }
283 ;
284
285 map_sd
286 : TSTATIC { $$ = NPFCTL_NAT_STATIC; }
287 | TDYNAMIC { $$ = NPFCTL_NAT_DYNAMIC; }
288 | { $$ = NPFCTL_NAT_DYNAMIC; }
289 ;
290
291 map_type
292 : ARROWBOTH { $$ = NPF_NATIN | NPF_NATOUT; }
293 | ARROWLEFT { $$ = NPF_NATIN; }
294 | ARROWRIGHT { $$ = NPF_NATOUT; }
295 ;
296
297 mapseg
298 : addr_or_ifnet port_range
299 {
300 $$.ap_netaddr = $1;
301 $$.ap_portrange = $2;
302 }
303 ;
304
305 map
306 : MAP ifindex map_sd mapseg map_type mapseg PASS filt_opts
307 {
308 npfctl_build_natseg($3, $5, $2, &$4, &$6, &$8);
309 }
310 | MAP ifindex map_sd mapseg map_type mapseg
311 {
312 npfctl_build_natseg($3, $5, $2, &$4, &$6, NULL);
313 }
314 | MAP RULESET PAR_OPEN group_attr PAR_CLOSE
315 {
316 npfctl_build_maprset($4.rg_name, $4.rg_attr, $4.rg_ifnum);
317 }
318 ;
319
320 rproc
321 : PROCEDURE STRING CURLY_OPEN procs CURLY_CLOSE
322 {
323 npfctl_build_rproc($2, $4);
324 }
325 ;
326
327 procs
328 : proc_call SEPLINE procs
329 {
330 $$ = npfvar_add_elements($1, $3);
331 }
332 | proc_call { $$ = $1; }
333 ;
334
335 proc_call
336 : IDENTIFIER COLON proc_param_list
337 {
338 proc_call_t pc;
339
340 pc.pc_name = estrdup($1);
341 pc.pc_opts = $3;
342 $$ = npfvar_create(".proc_call");
343 npfvar_add_element($$, NPFVAR_PROC, &pc, sizeof(pc));
344 }
345 | { $$ = NULL; }
346 ;
347
348 proc_param_list
349 : proc_param COMMA proc_param_list
350 {
351 $$ = npfvar_add_elements($1, $3);
352 }
353 | proc_param { $$ = $1; }
354 | { $$ = NULL; }
355 ;
356
357 proc_param
358 /* Key and value pair. */
359 : some_name proc_param_val
360 {
361 proc_param_t pp;
362
363 pp.pp_param = estrdup($1);
364 pp.pp_value = $2 ? estrdup($2) : NULL;
365 $$ = npfvar_create(".proc_param");
366 npfvar_add_element($$, NPFVAR_PROC_PARAM, &pp, sizeof(pp));
367 }
368 ;
369
370 proc_param_val
371 : some_name { $$ = $1; }
372 | NUM { (void)asprintf(&$$, "%ld", $1); }
373 | FPNUM { (void)asprintf(&$$, "%lf", $1); }
374 | { $$ = NULL; }
375 ;
376
377 group
378 : GROUP PAR_OPEN group_attr PAR_CLOSE
379 {
380 /* Build a group. Increases the nesting level. */
381 npfctl_build_group($3.rg_name, $3.rg_attr,
382 $3.rg_ifnum, $3.rg_default);
383 }
384 ruleset_block
385 {
386 /* Decrease the nesting level. */
387 npfctl_build_group_end();
388 }
389 ;
390
391 ruleset
392 : RULESET PAR_OPEN group_attr PAR_CLOSE
393 {
394 /* Ruleset is a dynamic group. */
395 npfctl_build_group($3.rg_name, $3.rg_attr | NPF_RULE_DYNAMIC,
396 $3.rg_ifnum, $3.rg_default);
397 npfctl_build_group_end();
398 }
399
400 group_attr
401 : group_opt COMMA group_attr
402 {
403 $$ = $3;
404
405 if (($1.rg_name && $$.rg_name) ||
406 ($1.rg_ifnum && $$.rg_ifnum) ||
407 ($1.rg_attr & $$.rg_attr) != 0)
408 yyerror("duplicate group option");
409
410 if ($1.rg_name) {
411 $$.rg_name = $1.rg_name;
412 }
413 if ($1.rg_attr) {
414 $$.rg_attr |= $1.rg_attr;
415 }
416 if ($1.rg_ifnum) {
417 $$.rg_ifnum = $1.rg_ifnum;
418 }
419 if ($1.rg_default) {
420 $$.rg_default = $1.rg_default;
421 }
422 }
423 | group_opt { $$ = $1; }
424 ;
425
426 group_opt
427 : DEFAULT
428 {
429 memset(&$$, 0, sizeof(rule_group_t));
430 $$.rg_default = true;
431 }
432 | NAME STRING
433 {
434 memset(&$$, 0, sizeof(rule_group_t));
435 $$.rg_name = $2;
436 }
437 | INTERFACE ifindex
438 {
439 memset(&$$, 0, sizeof(rule_group_t));
440 $$.rg_ifnum = $2;
441 }
442 | TDYNAMIC
443 {
444 memset(&$$, 0, sizeof(rule_group_t));
445 $$.rg_attr = NPF_RULE_DYNAMIC;
446 }
447 | FORW
448 {
449 memset(&$$, 0, sizeof(rule_group_t));
450 $$.rg_attr = NPF_RULE_FORW;
451 }
452 | rule_dir
453 {
454 memset(&$$, 0, sizeof(rule_group_t));
455 $$.rg_attr = $1;
456 }
457 ;
458
459 ruleset_block
460 : CURLY_OPEN ruleset_def CURLY_CLOSE
461 ;
462
463 ruleset_def
464 : rule_group SEPLINE ruleset_def
465 | rule_group
466 ;
467
468 rule_group
469 : rule
470 | group
471 | ruleset
472 |
473
474 rule
475 : block_or_pass opt_stateful rule_dir opt_final on_ifindex
476 opt_family opt_proto all_or_filt_opts opt_apply
477 {
478 npfctl_build_rule($1 | $2 | $3 | $4, $5,
479 $6, &$7, &$8, $9);
480 }
481 ;
482
483 block_or_pass
484 : BLOCK block_opts { $$ = $2; }
485 | PASS { $$ = NPF_RULE_PASS; }
486 ;
487
488 rule_dir
489 : IN { $$ = NPF_RULE_IN; }
490 | OUT { $$ = NPF_RULE_OUT; }
491 | { $$ = NPF_RULE_IN | NPF_RULE_OUT; }
492 ;
493
494 opt_final
495 : FINAL { $$ = NPF_RULE_FINAL; }
496 | { $$ = 0; }
497 ;
498
499 on_ifindex
500 : ON ifindex { $$ = $2; }
501 | { $$ = 0; }
502 ;
503
504 afamily
505 : INET { $$ = AF_INET; }
506 | INET6 { $$ = AF_INET6; }
507 ;
508
509 opt_family
510 : FAMILY afamily { $$ = $2; }
511 | { $$ = AF_UNSPEC; }
512 ;
513
514 opt_proto
515 : PROTO TCP tcp_flags_and_mask
516 {
517 $$.op_proto = IPPROTO_TCP;
518 $$.op_opts = $3;
519 }
520 | PROTO ICMP icmp_type_and_code
521 {
522 $$.op_proto = IPPROTO_ICMP;
523 $$.op_opts = $3;
524 }
525 | PROTO ICMP6 icmp_type_and_code
526 {
527 $$.op_proto = IPPROTO_ICMPV6;
528 $$.op_opts = $3;
529 }
530 | PROTO some_name
531 {
532 $$.op_proto = npfctl_protono($2);
533 $$.op_opts = NULL;
534 }
535 | PROTO NUM
536 {
537 $$.op_proto = $2;
538 $$.op_opts = NULL;
539 }
540 |
541 {
542 $$.op_proto = -1;
543 $$.op_opts = NULL;
544 }
545 ;
546
547 all_or_filt_opts
548 : ALL
549 {
550 $$.fo_from.ap_netaddr = NULL;
551 $$.fo_from.ap_portrange = NULL;
552 $$.fo_to.ap_netaddr = NULL;
553 $$.fo_to.ap_portrange = NULL;
554 }
555 | filt_opts { $$ = $1; }
556 ;
557
558 opt_stateful
559 : STATEFUL { $$ = NPF_RULE_STATEFUL; }
560 | { $$ = 0; }
561 ;
562
563 opt_apply
564 : APPLY STRING { $$ = $2; }
565 | { $$ = NULL; }
566 ;
567
568 block_opts
569 : RETURNRST { $$ = NPF_RULE_RETRST; }
570 | RETURNICMP { $$ = NPF_RULE_RETICMP; }
571 | RETURN { $$ = NPF_RULE_RETRST | NPF_RULE_RETICMP; }
572 | { $$ = 0; }
573 ;
574
575 filt_opts
576 : FROM filt_addr port_range TO filt_addr port_range
577 {
578 $$.fo_from.ap_netaddr = $2;
579 $$.fo_from.ap_portrange = $3;
580 $$.fo_to.ap_netaddr = $5;
581 $$.fo_to.ap_portrange = $6;
582 }
583 | FROM filt_addr port_range
584 {
585 $$.fo_from.ap_netaddr = $2;
586 $$.fo_from.ap_portrange = $3;
587 $$.fo_to.ap_netaddr = NULL;
588 $$.fo_to.ap_portrange = NULL;
589 }
590 | TO filt_addr port_range
591 {
592 $$.fo_from.ap_netaddr = NULL;
593 $$.fo_from.ap_portrange = NULL;
594 $$.fo_to.ap_netaddr = $2;
595 $$.fo_to.ap_portrange = $3;
596 }
597 ;
598
599 filt_addr
600 : addr_or_ifnet { $$ = $1; }
601 | TABLE_ID { $$ = npfctl_parse_table_id($1); }
602 | ANY { $$ = NULL; }
603 ;
604
605 addr_and_mask
606 : addr SLASH NUM
607 {
608 $$ = npfctl_parse_fam_addr_mask($1, NULL, &$3);
609 }
610 | addr SLASH HEX
611 {
612 $$ = npfctl_parse_fam_addr_mask($1, NULL, &$3);
613 }
614 | addr SLASH addr
615 {
616 $$ = npfctl_parse_fam_addr_mask($1, $3, NULL);
617 }
618 | addr
619 {
620 $$ = npfctl_parse_fam_addr_mask($1, NULL, NULL);
621 }
622 ;
623
624 addr_or_ifnet
625 : addr_and_mask
626 {
627 assert($1 != NULL);
628 $$ = $1;
629 }
630 | ifnet
631 {
632 ifnet_addr_t *ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0);
633 $$ = ifna->ifna_addrs;
634 }
635 | VAR_ID
636 {
637 npfvar_t *vp = npfvar_lookup($1);
638 int type = npfvar_get_type(vp, 0);
639 ifnet_addr_t *ifna;
640
641 again:
642 switch (type) {
643 case NPFVAR_IDENTIFIER:
644 case NPFVAR_STRING:
645 vp = npfctl_parse_ifnet(npfvar_expand_string(vp),
646 AF_UNSPEC);
647 type = npfvar_get_type(vp, 0);
648 goto again;
649 case NPFVAR_FAM:
650 $$ = vp;
651 break;
652 case NPFVAR_INTERFACE:
653 ifna = npfvar_get_data(vp, type, 0);
654 $$ = ifna->ifna_addrs;
655 break;
656 case -1:
657 yyerror("undefined variable '%s'", $1);
658 break;
659 default:
660 yyerror("wrong variable '%s' type '%s' for address "
661 "or interface", $1, npfvar_type(type));
662 break;
663 }
664 }
665 ;
666
667 addr
668 : IPV4ADDR { $$ = $1; }
669 | IPV6ADDR { $$ = $1; }
670 ;
671
672 port_range
673 : PORT port /* just port */
674 {
675 $$ = npfctl_parse_port_range($2, $2);
676 }
677 | PORT port MINUS port /* port from-to */
678 {
679 $$ = npfctl_parse_port_range($2, $4);
680 }
681 | PORT VAR_ID
682 {
683 $$ = npfctl_parse_port_range_variable($2);
684 }
685 |
686 {
687 $$ = NULL;
688 }
689 ;
690
691 port
692 : NUM { $$ = $1; }
693 | IDENTIFIER { $$ = npfctl_portno($1); }
694 | STRING { $$ = npfctl_portno($1); }
695 ;
696
697 icmp_type_and_code
698 : ICMPTYPE icmp_type
699 {
700 $$ = npfctl_parse_icmp($<num>0, $2, -1);
701 }
702 | ICMPTYPE icmp_type CODE NUM
703 {
704 $$ = npfctl_parse_icmp($<num>0, $2, $4);
705 }
706 | ICMPTYPE icmp_type CODE IDENTIFIER
707 {
708 $$ = npfctl_parse_icmp($<num>0, $2,
709 npfctl_icmpcode($<num>0, $2, $4));
710 }
711 | ICMPTYPE icmp_type CODE VAR_ID
712 {
713 char *s = npfvar_expand_string(npfvar_lookup($4));
714 $$ = npfctl_parse_icmp($<num>0, $2,
715 npfctl_icmpcode($<num>0, $2, s));
716 }
717 |
718 {
719 $$ = npfctl_parse_icmp($<num>0, -1, -1);
720 }
721 ;
722
723 tcp_flags_and_mask
724 : FLAGS tcp_flags SLASH tcp_flags
725 {
726 npfvar_add_elements($2, $4);
727 $$ = $2;
728 }
729 | FLAGS tcp_flags
730 {
731 char *s = npfvar_get_data($2, NPFVAR_TCPFLAG, 0);
732 npfvar_add_elements($2, npfctl_parse_tcpflag(s));
733 $$ = $2;
734 }
735 | { $$ = NULL; }
736 ;
737
738 tcp_flags
739 : IDENTIFIER { $$ = npfctl_parse_tcpflag($1); }
740 ;
741
742 icmp_type
743 : NUM { $$ = $1; }
744 | IDENTIFIER { $$ = npfctl_icmptype($<num>-1, $1); }
745 | VAR_ID
746 {
747 char *s = npfvar_expand_string(npfvar_lookup($1));
748 $$ = npfctl_icmptype($<num>-1, s);
749 }
750 ;
751
752 string
753 : IDENTIFIER
754 {
755 $$ = $1;
756 }
757 | VAR_ID
758 {
759 npfvar_t *vp = npfvar_lookup($1);
760 const int type = npfvar_get_type(vp, 0);
761
762 switch (type) {
763 case NPFVAR_STRING:
764 case NPFVAR_IDENTIFIER:
765 $$ = npfvar_expand_string(vp);
766 break;
767 case -1:
768 yyerror("undefined variable '%s' for interface", $1);
769 break;
770 default:
771 yyerror("wrong variable '%s' type '%s' for string",
772 $1, npfvar_type(type));
773 break;
774 }
775 }
776 ;
777
778 ifnet
779 : IFNET PAR_OPEN string PAR_CLOSE
780 {
781 $$ = npfctl_parse_ifnet($3, AF_UNSPEC);
782 }
783 | afamily PAR_OPEN string PAR_CLOSE
784 {
785 $$ = npfctl_parse_ifnet($3, $1);
786 }
787 ;
788
789 ifindex
790 : some_name
791 {
792 $$ = npfctl_find_ifindex($1);
793 }
794 | ifnet
795 {
796 ifnet_addr_t *ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0);
797 $$ = ifna->ifna_index;
798 }
799 | VAR_ID
800 {
801 npfvar_t *vp = npfvar_lookup($1);
802 const int type = npfvar_get_type(vp, 0);
803 ifnet_addr_t *ifna;
804
805 switch (type) {
806 case NPFVAR_STRING:
807 case NPFVAR_IDENTIFIER:
808 $$ = npfctl_find_ifindex(npfvar_expand_string(vp));
809 break;
810 case NPFVAR_INTERFACE:
811 ifna = npfvar_get_data(vp, type, 0);
812 $$ = ifna->ifna_index;
813 break;
814 case -1:
815 yyerror("undefined variable '%s' for interface", $1);
816 break;
817 default:
818 yyerror("wrong variable '%s' type '%s' for interface",
819 $1, npfvar_type(type));
820 break;
821 }
822 }
823 ;
824
825 some_name
826 : IDENTIFIER { $$ = $1; }
827 | STRING { $$ = $1; }
828 ;
829
830 %%
831