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