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