1*a894e3f7Srmind /* $NetBSD: npf_parse.y,v 1.32 2014/02/13 03:34:40 rmind Exp $ */ 2f03cb1d4Srmind 3f03cb1d4Srmind /*- 4*a894e3f7Srmind * Copyright (c) 2011-2014 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 <stdio.h> 35f03cb1d4Srmind #include <err.h> 36f03cb1d4Srmind #include <vis.h> 37f03cb1d4Srmind #include <netdb.h> 38f03cb1d4Srmind 39f03cb1d4Srmind #include "npfctl.h" 40f03cb1d4Srmind 418b3f8af5Srmind #define YYSTACKSIZE 4096 428b3f8af5Srmind 4337527ec6Srmind int yyparsetarget; 44f03cb1d4Srmind const char * yyfilename; 45f03cb1d4Srmind 46f03cb1d4Srmind extern int yylineno, yycolumn; 47f03cb1d4Srmind extern int yylex(void); 48f03cb1d4Srmind 49f03cb1d4Srmind void 50f03cb1d4Srmind yyerror(const char *fmt, ...) 51f03cb1d4Srmind { 52f03cb1d4Srmind extern int yyleng; 53f03cb1d4Srmind extern char *yytext; 54f03cb1d4Srmind 557c0a5ca2Srmind char *msg, *context = estrndup(yytext, yyleng); 564e3d5046Srmind bool eol = (*context == '\n'); 57f03cb1d4Srmind va_list ap; 58f03cb1d4Srmind 59f03cb1d4Srmind va_start(ap, fmt); 60f03cb1d4Srmind vasprintf(&msg, fmt, ap); 61f03cb1d4Srmind va_end(ap); 62f03cb1d4Srmind 634e3d5046Srmind fprintf(stderr, "%s:%d:%d: %s", yyfilename, 644e3d5046Srmind yylineno - (int)eol, yycolumn, msg); 654e3d5046Srmind if (!eol) { 664e3d5046Srmind size_t len = strlen(context); 673c7c5558Srmind char *dst = ecalloc(1, len * 4 + 1); 684e3d5046Srmind 69f03cb1d4Srmind strvisx(dst, context, len, VIS_WHITE|VIS_CSTYLE); 704e3d5046Srmind fprintf(stderr, " near '%s'", dst); 714e3d5046Srmind } 724e3d5046Srmind fprintf(stderr, "\n"); 73f03cb1d4Srmind exit(EXIT_FAILURE); 74f03cb1d4Srmind } 75f03cb1d4Srmind 7637527ec6Srmind #define CHECK_PARSER_FILE \ 7737527ec6Srmind if (yyparsetarget != NPFCTL_PARSE_FILE) \ 7837527ec6Srmind yyerror("rule must be in the group"); 7937527ec6Srmind 8037527ec6Srmind #define CHECK_PARSER_STRING \ 8137527ec6Srmind if (yyparsetarget != NPFCTL_PARSE_STRING) \ 8237527ec6Srmind yyerror("invalid rule syntax"); 8337527ec6Srmind 84f03cb1d4Srmind %} 85f03cb1d4Srmind 863b895110Schristos %token ALG 87*a894e3f7Srmind %token ALGO 88f03cb1d4Srmind %token ALL 89f03cb1d4Srmind %token ANY 90f03cb1d4Srmind %token APPLY 91add921fbSrmind %token ARROWBOTH 92add921fbSrmind %token ARROWLEFT 93add921fbSrmind %token ARROWRIGHT 94f03cb1d4Srmind %token BLOCK 95820aad11Srmind %token CDB 96f03cb1d4Srmind %token CURLY_CLOSE 97f03cb1d4Srmind %token CURLY_OPEN 98f03cb1d4Srmind %token CODE 99f03cb1d4Srmind %token COLON 100f03cb1d4Srmind %token COMMA 101f03cb1d4Srmind %token DEFAULT 102f03cb1d4Srmind %token TDYNAMIC 103add921fbSrmind %token TSTATIC 104f03cb1d4Srmind %token EQ 105f03cb1d4Srmind %token TFILE 106f03cb1d4Srmind %token FLAGS 107f03cb1d4Srmind %token FROM 108f03cb1d4Srmind %token GROUP 109f03cb1d4Srmind %token HASH 110f03cb1d4Srmind %token ICMPTYPE 111f03cb1d4Srmind %token ID 112f03cb1d4Srmind %token IN 113348a4177Srmind %token INET4 114f03cb1d4Srmind %token INET6 115f03cb1d4Srmind %token INTERFACE 116add921fbSrmind %token MAP 117f03cb1d4Srmind %token MINUS 118f03cb1d4Srmind %token NAME 119*a894e3f7Srmind %token NPT66 120f03cb1d4Srmind %token ON 121f03cb1d4Srmind %token OUT 122f03cb1d4Srmind %token PAR_CLOSE 123f03cb1d4Srmind %token PAR_OPEN 124f03cb1d4Srmind %token PASS 125c6e77e2aSrmind %token PCAP_FILTER 126f03cb1d4Srmind %token PORT 127f03cb1d4Srmind %token PROCEDURE 128f03cb1d4Srmind %token PROTO 129f03cb1d4Srmind %token FAMILY 130ba11b3c0Srmind %token FINAL 13137527ec6Srmind %token FORW 132f03cb1d4Srmind %token RETURN 133f03cb1d4Srmind %token RETURNICMP 134f03cb1d4Srmind %token RETURNRST 1357b486642Srmind %token RULESET 136f03cb1d4Srmind %token SEPLINE 137f03cb1d4Srmind %token SLASH 138ba11b3c0Srmind %token STATEFUL 139f03cb1d4Srmind %token TABLE 140f03cb1d4Srmind %token TCP 141f03cb1d4Srmind %token TO 142f03cb1d4Srmind %token TREE 143f03cb1d4Srmind %token TYPE 144afd9e22aSspz %token <num> ICMP 145afd9e22aSspz %token <num> ICMP6 146f03cb1d4Srmind 147f03cb1d4Srmind %token <num> HEX 148f03cb1d4Srmind %token <str> IDENTIFIER 149f03cb1d4Srmind %token <str> IPV4ADDR 150f03cb1d4Srmind %token <str> IPV6ADDR 151f03cb1d4Srmind %token <num> NUM 15248a1ec7dSrmind %token <fpnum> FPNUM 153f03cb1d4Srmind %token <str> STRING 154f03cb1d4Srmind %token <str> TABLE_ID 155f03cb1d4Srmind %token <str> VAR_ID 156f03cb1d4Srmind 157348a4177Srmind %type <str> addr, some_name, table_store 158348a4177Srmind %type <str> proc_param_val, opt_apply, ifname, on_ifname, ifref 159d1d2e2c9Srmind %type <num> port, opt_final, number, afamily, opt_family 160c6e77e2aSrmind %type <num> block_or_pass, rule_dir, group_dir, block_opts 161*a894e3f7Srmind %type <num> opt_stateful, icmp_type, table_type 162*a894e3f7Srmind %type <num> map_sd, map_algo, map_type 163348a4177Srmind %type <var> ifaddrs, addr_or_ifaddr, port_range, icmp_type_and_code 164f03cb1d4Srmind %type <var> filt_addr, addr_and_mask, tcp_flags, tcp_flags_and_mask 16548a1ec7dSrmind %type <var> procs, proc_call, proc_param_list, proc_param 166348a4177Srmind %type <var> element, list_elems, list, value 167add921fbSrmind %type <addrport> mapseg 168f03cb1d4Srmind %type <filtopts> filt_opts, all_or_filt_opts 169f03cb1d4Srmind %type <optproto> opt_proto 170c6e77e2aSrmind %type <rulegroup> group_opts 171f03cb1d4Srmind 172f03cb1d4Srmind %union { 173f03cb1d4Srmind char * str; 174f03cb1d4Srmind unsigned long num; 17548a1ec7dSrmind double fpnum; 176ec3d0e07Srmind npfvar_t * var; 177add921fbSrmind addr_port_t addrport; 178f03cb1d4Srmind filt_opts_t filtopts; 179f03cb1d4Srmind opt_proto_t optproto; 180f03cb1d4Srmind rule_group_t rulegroup; 181f03cb1d4Srmind } 182f03cb1d4Srmind 183f03cb1d4Srmind %% 184f03cb1d4Srmind 185f03cb1d4Srmind input 18637527ec6Srmind : { CHECK_PARSER_FILE } lines 18737527ec6Srmind | { CHECK_PARSER_STRING } rule 188f03cb1d4Srmind ; 189f03cb1d4Srmind 190f03cb1d4Srmind lines 191f03cb1d4Srmind : line SEPLINE lines 192f03cb1d4Srmind | line 193f03cb1d4Srmind ; 194f03cb1d4Srmind 195f03cb1d4Srmind line 1968f6547d8Srmind : vardef 197f03cb1d4Srmind | table 198add921fbSrmind | map 199f03cb1d4Srmind | group 200f03cb1d4Srmind | rproc 2013b895110Schristos | alg 202f03cb1d4Srmind | 203f03cb1d4Srmind ; 204f03cb1d4Srmind 2058f6547d8Srmind alg 2068f6547d8Srmind : ALG STRING 2078f6547d8Srmind { 2088f6547d8Srmind npfctl_build_alg($2); 2098f6547d8Srmind } 2108f6547d8Srmind ; 2118f6547d8Srmind 2128f6547d8Srmind /* 2138f6547d8Srmind * A value - an element or a list of elements. 2148f6547d8Srmind * Can be assigned to a variable or used inline. 2158f6547d8Srmind */ 2168f6547d8Srmind 2178f6547d8Srmind vardef 218348a4177Srmind : VAR_ID EQ value 219f03cb1d4Srmind { 220348a4177Srmind npfvar_add($3, $1); 221f03cb1d4Srmind } 222f03cb1d4Srmind ; 223f03cb1d4Srmind 2248f6547d8Srmind value 2258f6547d8Srmind : element 2268f6547d8Srmind | list 227f03cb1d4Srmind ; 228f03cb1d4Srmind 2298f6547d8Srmind list 230f03cb1d4Srmind : CURLY_OPEN list_elems CURLY_CLOSE 231348a4177Srmind { 232348a4177Srmind $$ = $2; 233348a4177Srmind } 234f03cb1d4Srmind ; 235f03cb1d4Srmind 236f03cb1d4Srmind list_elems 2378f6547d8Srmind : element COMMA list_elems 238348a4177Srmind { 239348a4177Srmind npfvar_add_elements($1, $3); 240348a4177Srmind } 2418f6547d8Srmind | element 242f03cb1d4Srmind ; 243f03cb1d4Srmind 2448f6547d8Srmind element 245f03cb1d4Srmind : IDENTIFIER 246f03cb1d4Srmind { 247348a4177Srmind $$ = npfvar_create_from_string(NPFVAR_IDENTIFIER, $1); 248f03cb1d4Srmind } 249f03cb1d4Srmind | STRING 250f03cb1d4Srmind { 251348a4177Srmind $$ = npfvar_create_from_string(NPFVAR_STRING, $1); 252f03cb1d4Srmind } 253f2174d83Schristos | number MINUS number 254ff24200fSchristos { 255348a4177Srmind $$ = npfctl_parse_port_range($1, $3); 256ff24200fSchristos } 257f2174d83Schristos | number 258f03cb1d4Srmind { 259348a4177Srmind $$ = npfvar_create_element(NPFVAR_NUM, &$1, sizeof($1)); 260f03cb1d4Srmind } 261f03cb1d4Srmind | VAR_ID 262f03cb1d4Srmind { 263348a4177Srmind $$ = npfvar_create_from_string(NPFVAR_VAR_ID, $1); 264f03cb1d4Srmind } 265348a4177Srmind | TABLE_ID { $$ = npfctl_parse_table_id($1); } 266348a4177Srmind | ifaddrs { $$ = $1; } 267348a4177Srmind | addr_and_mask { $$ = $1; } 268f03cb1d4Srmind ; 269f03cb1d4Srmind 2708f6547d8Srmind /* 2718f6547d8Srmind * Table definition. 2728f6547d8Srmind */ 2738f6547d8Srmind 274f03cb1d4Srmind table 275f03cb1d4Srmind : TABLE TABLE_ID TYPE table_type table_store 276f03cb1d4Srmind { 277f03cb1d4Srmind npfctl_build_table($2, $4, $5); 278f03cb1d4Srmind } 279f03cb1d4Srmind ; 280f03cb1d4Srmind 281f03cb1d4Srmind table_type 282f03cb1d4Srmind : HASH { $$ = NPF_TABLE_HASH; } 283664900efSrmind | TREE { $$ = NPF_TABLE_TREE; } 284820aad11Srmind | CDB { $$ = NPF_TABLE_CDB; } 285f03cb1d4Srmind ; 286f03cb1d4Srmind 287f03cb1d4Srmind table_store 288f03cb1d4Srmind : TDYNAMIC { $$ = NULL; } 289f03cb1d4Srmind | TFILE STRING { $$ = $2; } 290f03cb1d4Srmind ; 291f03cb1d4Srmind 2928f6547d8Srmind /* 2938f6547d8Srmind * Map definition. 2948f6547d8Srmind */ 2958f6547d8Srmind 296add921fbSrmind map_sd 297add921fbSrmind : TSTATIC { $$ = NPFCTL_NAT_STATIC; } 298add921fbSrmind | TDYNAMIC { $$ = NPFCTL_NAT_DYNAMIC; } 299add921fbSrmind | { $$ = NPFCTL_NAT_DYNAMIC; } 300f03cb1d4Srmind ; 301f03cb1d4Srmind 302*a894e3f7Srmind map_algo 303*a894e3f7Srmind : ALGO NPT66 { $$ = NPF_ALGO_NPT66; } 304*a894e3f7Srmind | { $$ = 0; } 305*a894e3f7Srmind ; 306*a894e3f7Srmind 307add921fbSrmind map_type 308add921fbSrmind : ARROWBOTH { $$ = NPF_NATIN | NPF_NATOUT; } 309add921fbSrmind | ARROWLEFT { $$ = NPF_NATIN; } 310add921fbSrmind | ARROWRIGHT { $$ = NPF_NATOUT; } 311add921fbSrmind ; 312add921fbSrmind 313add921fbSrmind mapseg 314348a4177Srmind : addr_or_ifaddr port_range 315f03cb1d4Srmind { 316add921fbSrmind $$.ap_netaddr = $1; 317add921fbSrmind $$.ap_portrange = $2; 318f03cb1d4Srmind } 319f03cb1d4Srmind ; 320f03cb1d4Srmind 321add921fbSrmind map 322*a894e3f7Srmind : MAP ifref map_sd map_algo mapseg map_type mapseg PASS filt_opts 323f03cb1d4Srmind { 324*a894e3f7Srmind npfctl_build_natseg($3, $6, $2, &$5, &$7, &$9, $4); 325f03cb1d4Srmind } 326*a894e3f7Srmind | MAP ifref map_sd map_algo mapseg map_type mapseg 327f03cb1d4Srmind { 328*a894e3f7Srmind npfctl_build_natseg($3, $6, $2, &$5, &$7, NULL, $4); 329f03cb1d4Srmind } 330c6e77e2aSrmind | MAP RULESET group_opts 3317b486642Srmind { 332d1d2e2c9Srmind npfctl_build_maprset($3.rg_name, $3.rg_attr, $3.rg_ifname); 3337b486642Srmind } 334f03cb1d4Srmind ; 335f03cb1d4Srmind 3368f6547d8Srmind /* 3378f6547d8Srmind * Rule procedure definition and its parameters. 3388f6547d8Srmind */ 3398f6547d8Srmind 340f03cb1d4Srmind rproc 341f03cb1d4Srmind : PROCEDURE STRING CURLY_OPEN procs CURLY_CLOSE 342f03cb1d4Srmind { 343f03cb1d4Srmind npfctl_build_rproc($2, $4); 344f03cb1d4Srmind } 345f03cb1d4Srmind ; 346f03cb1d4Srmind 347f03cb1d4Srmind procs 34848a1ec7dSrmind : proc_call SEPLINE procs 349f03cb1d4Srmind { 350f03cb1d4Srmind $$ = npfvar_add_elements($1, $3); 351f03cb1d4Srmind } 35248a1ec7dSrmind | proc_call { $$ = $1; } 35348a1ec7dSrmind ; 35448a1ec7dSrmind 35548a1ec7dSrmind proc_call 35648a1ec7dSrmind : IDENTIFIER COLON proc_param_list 35748a1ec7dSrmind { 35848a1ec7dSrmind proc_call_t pc; 35948a1ec7dSrmind 3607c0a5ca2Srmind pc.pc_name = estrdup($1); 36148a1ec7dSrmind pc.pc_opts = $3; 362348a4177Srmind 363348a4177Srmind $$ = npfvar_create_element(NPFVAR_PROC, &pc, sizeof(pc)); 36448a1ec7dSrmind } 365f03cb1d4Srmind | { $$ = NULL; } 366f03cb1d4Srmind ; 367f03cb1d4Srmind 36848a1ec7dSrmind proc_param_list 36948a1ec7dSrmind : proc_param COMMA proc_param_list 370f03cb1d4Srmind { 37148a1ec7dSrmind $$ = npfvar_add_elements($1, $3); 37248a1ec7dSrmind } 37348a1ec7dSrmind | proc_param { $$ = $1; } 37448a1ec7dSrmind | { $$ = NULL; } 37548a1ec7dSrmind ; 376f03cb1d4Srmind 37748a1ec7dSrmind proc_param 37848a1ec7dSrmind : some_name proc_param_val 37948a1ec7dSrmind { 38048a1ec7dSrmind proc_param_t pp; 38148a1ec7dSrmind 3827c0a5ca2Srmind pp.pp_param = estrdup($1); 3837c0a5ca2Srmind pp.pp_value = $2 ? estrdup($2) : NULL; 384348a4177Srmind 385348a4177Srmind $$ = npfvar_create_element(NPFVAR_PROC_PARAM, &pp, sizeof(pp)); 386f03cb1d4Srmind } 387f03cb1d4Srmind ; 388f03cb1d4Srmind 38948a1ec7dSrmind proc_param_val 39048a1ec7dSrmind : some_name { $$ = $1; } 391f2174d83Schristos | number { (void)asprintf(&$$, "%ld", $1); } 39248a1ec7dSrmind | FPNUM { (void)asprintf(&$$, "%lf", $1); } 393f03cb1d4Srmind | { $$ = NULL; } 394f03cb1d4Srmind ; 395f03cb1d4Srmind 3968f6547d8Srmind /* 3978f6547d8Srmind * Group and dynamic ruleset definition. 3988f6547d8Srmind */ 3998f6547d8Srmind 400f03cb1d4Srmind group 401c6e77e2aSrmind : GROUP group_opts 402f03cb1d4Srmind { 403348a4177Srmind /* Build a group. Increase the nesting level. */ 404c6e77e2aSrmind npfctl_build_group($2.rg_name, $2.rg_attr, 405d1d2e2c9Srmind $2.rg_ifname, $2.rg_default); 406f03cb1d4Srmind } 40737527ec6Srmind ruleset_block 40837527ec6Srmind { 40937527ec6Srmind /* Decrease the nesting level. */ 41037527ec6Srmind npfctl_build_group_end(); 41137527ec6Srmind } 412f03cb1d4Srmind ; 413f03cb1d4Srmind 4147b486642Srmind ruleset 415c6e77e2aSrmind : RULESET group_opts 4167b486642Srmind { 4177b486642Srmind /* Ruleset is a dynamic group. */ 418c6e77e2aSrmind npfctl_build_group($2.rg_name, $2.rg_attr | NPF_RULE_DYNAMIC, 419d1d2e2c9Srmind $2.rg_ifname, $2.rg_default); 4207b486642Srmind npfctl_build_group_end(); 4217b486642Srmind } 422f03cb1d4Srmind ; 423f03cb1d4Srmind 424c6e77e2aSrmind group_dir 425c6e77e2aSrmind : FORW { $$ = NPF_RULE_FORW; } 426c6e77e2aSrmind | rule_dir 427c6e77e2aSrmind ; 428c6e77e2aSrmind 429c6e77e2aSrmind group_opts 430f03cb1d4Srmind : DEFAULT 431f03cb1d4Srmind { 43237527ec6Srmind memset(&$$, 0, sizeof(rule_group_t)); 43337527ec6Srmind $$.rg_default = true; 434f03cb1d4Srmind } 435d1d2e2c9Srmind | STRING group_dir on_ifname 436f03cb1d4Srmind { 43737527ec6Srmind memset(&$$, 0, sizeof(rule_group_t)); 438c6e77e2aSrmind $$.rg_name = $1; 439c6e77e2aSrmind $$.rg_attr = $2; 440d1d2e2c9Srmind $$.rg_ifname = $3; 441f03cb1d4Srmind } 442f03cb1d4Srmind ; 443f03cb1d4Srmind 44437527ec6Srmind ruleset_block 4457b486642Srmind : CURLY_OPEN ruleset_def CURLY_CLOSE 446f03cb1d4Srmind ; 447f03cb1d4Srmind 4487b486642Srmind ruleset_def 4497b486642Srmind : rule_group SEPLINE ruleset_def 45037527ec6Srmind | rule_group 451f03cb1d4Srmind ; 452f03cb1d4Srmind 45337527ec6Srmind rule_group 45437527ec6Srmind : rule 45537527ec6Srmind | group 4567b486642Srmind | ruleset 45737527ec6Srmind | 45885aa89dfSrmind ; 45937527ec6Srmind 4608f6547d8Srmind /* 4618f6547d8Srmind * Rule and misc. 4628f6547d8Srmind */ 4638f6547d8Srmind 464f03cb1d4Srmind rule 465d1d2e2c9Srmind : block_or_pass opt_stateful rule_dir opt_final on_ifname 466ec3d0e07Srmind opt_family opt_proto all_or_filt_opts opt_apply 467f03cb1d4Srmind { 468ba11b3c0Srmind npfctl_build_rule($1 | $2 | $3 | $4, $5, 469c6e77e2aSrmind $6, &$7, &$8, NULL, $9); 470c6e77e2aSrmind } 471d1d2e2c9Srmind | block_or_pass opt_stateful rule_dir opt_final on_ifname 472c6e77e2aSrmind PCAP_FILTER STRING opt_apply 473c6e77e2aSrmind { 474c6e77e2aSrmind npfctl_build_rule($1 | $2 | $3 | $4, $5, 475c6e77e2aSrmind AF_UNSPEC, NULL, NULL, $7, $8); 476f03cb1d4Srmind } 477f03cb1d4Srmind ; 478f03cb1d4Srmind 479f03cb1d4Srmind block_or_pass 480f03cb1d4Srmind : BLOCK block_opts { $$ = $2; } 481f03cb1d4Srmind | PASS { $$ = NPF_RULE_PASS; } 482f03cb1d4Srmind ; 483f03cb1d4Srmind 484f03cb1d4Srmind rule_dir 485f03cb1d4Srmind : IN { $$ = NPF_RULE_IN; } 486f03cb1d4Srmind | OUT { $$ = NPF_RULE_OUT; } 487f03cb1d4Srmind | { $$ = NPF_RULE_IN | NPF_RULE_OUT; } 488f03cb1d4Srmind ; 489f03cb1d4Srmind 490ba11b3c0Srmind opt_final 491ba11b3c0Srmind : FINAL { $$ = NPF_RULE_FINAL; } 492f03cb1d4Srmind | { $$ = 0; } 493f03cb1d4Srmind ; 494f03cb1d4Srmind 495d1d2e2c9Srmind on_ifname 496348a4177Srmind : ON ifref { $$ = $2; } 497d1d2e2c9Srmind | { $$ = NULL; } 498f03cb1d4Srmind ; 499f03cb1d4Srmind 500ec3d0e07Srmind afamily 501348a4177Srmind : INET4 { $$ = AF_INET; } 502ec3d0e07Srmind | INET6 { $$ = AF_INET6; } 503ec3d0e07Srmind ; 504ec3d0e07Srmind 505f75d4435Srmind opt_family 506ec3d0e07Srmind : FAMILY afamily { $$ = $2; } 507f75d4435Srmind | { $$ = AF_UNSPEC; } 508f03cb1d4Srmind ; 509f03cb1d4Srmind 510f03cb1d4Srmind opt_proto 511f03cb1d4Srmind : PROTO TCP tcp_flags_and_mask 512f03cb1d4Srmind { 513f03cb1d4Srmind $$.op_proto = IPPROTO_TCP; 514f03cb1d4Srmind $$.op_opts = $3; 515f03cb1d4Srmind } 516f03cb1d4Srmind | PROTO ICMP icmp_type_and_code 517f03cb1d4Srmind { 518f03cb1d4Srmind $$.op_proto = IPPROTO_ICMP; 519f03cb1d4Srmind $$.op_opts = $3; 520f03cb1d4Srmind } 521afd9e22aSspz | PROTO ICMP6 icmp_type_and_code 522afd9e22aSspz { 523afd9e22aSspz $$.op_proto = IPPROTO_ICMPV6; 524afd9e22aSspz $$.op_opts = $3; 525afd9e22aSspz } 526f75d4435Srmind | PROTO some_name 527f03cb1d4Srmind { 528f75d4435Srmind $$.op_proto = npfctl_protono($2); 529f75d4435Srmind $$.op_opts = NULL; 530f75d4435Srmind } 531f2174d83Schristos | PROTO number 532f75d4435Srmind { 533f75d4435Srmind $$.op_proto = $2; 534f03cb1d4Srmind $$.op_opts = NULL; 535f03cb1d4Srmind } 536f03cb1d4Srmind | 537f03cb1d4Srmind { 538f03cb1d4Srmind $$.op_proto = -1; 539f03cb1d4Srmind $$.op_opts = NULL; 540f03cb1d4Srmind } 541f03cb1d4Srmind ; 542f03cb1d4Srmind 543f03cb1d4Srmind all_or_filt_opts 544f03cb1d4Srmind : ALL 545f03cb1d4Srmind { 546add921fbSrmind $$.fo_from.ap_netaddr = NULL; 547add921fbSrmind $$.fo_from.ap_portrange = NULL; 548add921fbSrmind $$.fo_to.ap_netaddr = NULL; 549add921fbSrmind $$.fo_to.ap_portrange = NULL; 550f03cb1d4Srmind } 551f03cb1d4Srmind | filt_opts { $$ = $1; } 552f03cb1d4Srmind ; 553f03cb1d4Srmind 554ba11b3c0Srmind opt_stateful 555f75d4435Srmind : STATEFUL { $$ = NPF_RULE_STATEFUL; } 556f03cb1d4Srmind | { $$ = 0; } 557f03cb1d4Srmind ; 558f03cb1d4Srmind 559f03cb1d4Srmind opt_apply 560f03cb1d4Srmind : APPLY STRING { $$ = $2; } 561f03cb1d4Srmind | { $$ = NULL; } 562f03cb1d4Srmind ; 563f03cb1d4Srmind 564f03cb1d4Srmind block_opts 565f03cb1d4Srmind : RETURNRST { $$ = NPF_RULE_RETRST; } 566f03cb1d4Srmind | RETURNICMP { $$ = NPF_RULE_RETICMP; } 567f03cb1d4Srmind | RETURN { $$ = NPF_RULE_RETRST | NPF_RULE_RETICMP; } 568f03cb1d4Srmind | { $$ = 0; } 569f03cb1d4Srmind ; 570f03cb1d4Srmind 571f03cb1d4Srmind filt_opts 572f03cb1d4Srmind : FROM filt_addr port_range TO filt_addr port_range 573f03cb1d4Srmind { 574add921fbSrmind $$.fo_from.ap_netaddr = $2; 575add921fbSrmind $$.fo_from.ap_portrange = $3; 576add921fbSrmind $$.fo_to.ap_netaddr = $5; 577add921fbSrmind $$.fo_to.ap_portrange = $6; 578f03cb1d4Srmind } 579f03cb1d4Srmind | FROM filt_addr port_range 580f03cb1d4Srmind { 581add921fbSrmind $$.fo_from.ap_netaddr = $2; 582add921fbSrmind $$.fo_from.ap_portrange = $3; 583add921fbSrmind $$.fo_to.ap_netaddr = NULL; 584add921fbSrmind $$.fo_to.ap_portrange = NULL; 585f03cb1d4Srmind } 586f03cb1d4Srmind | TO filt_addr port_range 587f03cb1d4Srmind { 588add921fbSrmind $$.fo_from.ap_netaddr = NULL; 589add921fbSrmind $$.fo_from.ap_portrange = NULL; 590add921fbSrmind $$.fo_to.ap_netaddr = $2; 591add921fbSrmind $$.fo_to.ap_portrange = $3; 592f03cb1d4Srmind } 593f03cb1d4Srmind ; 594f03cb1d4Srmind 595f03cb1d4Srmind filt_addr 596348a4177Srmind : addr_or_ifaddr { $$ = $1; } 597f03cb1d4Srmind | TABLE_ID { $$ = npfctl_parse_table_id($1); } 598f03cb1d4Srmind | ANY { $$ = NULL; } 599f03cb1d4Srmind ; 600f03cb1d4Srmind 601f03cb1d4Srmind addr_and_mask 602f2174d83Schristos : addr SLASH number 603f03cb1d4Srmind { 604f03cb1d4Srmind $$ = npfctl_parse_fam_addr_mask($1, NULL, &$3); 605f03cb1d4Srmind } 606f03cb1d4Srmind | addr SLASH addr 607f03cb1d4Srmind { 608f03cb1d4Srmind $$ = npfctl_parse_fam_addr_mask($1, $3, NULL); 609f03cb1d4Srmind } 610f03cb1d4Srmind | addr 611f03cb1d4Srmind { 612f03cb1d4Srmind $$ = npfctl_parse_fam_addr_mask($1, NULL, NULL); 613f03cb1d4Srmind } 614f03cb1d4Srmind ; 615f03cb1d4Srmind 616348a4177Srmind addr_or_ifaddr 617f75d4435Srmind : addr_and_mask 618f75d4435Srmind { 619f75d4435Srmind assert($1 != NULL); 620f75d4435Srmind $$ = $1; 621f75d4435Srmind } 622348a4177Srmind | ifaddrs 6238094cc3dSrmind { 624ec3d0e07Srmind ifnet_addr_t *ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0); 625ec3d0e07Srmind $$ = ifna->ifna_addrs; 6268094cc3dSrmind } 6278094cc3dSrmind | VAR_ID 6288094cc3dSrmind { 6298094cc3dSrmind npfvar_t *vp = npfvar_lookup($1); 630f0ae964eSchristos int type = npfvar_get_type(vp, 0); 631ec3d0e07Srmind ifnet_addr_t *ifna; 6328094cc3dSrmind 633f0ae964eSchristos again: 6348094cc3dSrmind switch (type) { 635f0ae964eSchristos case NPFVAR_IDENTIFIER: 636f0ae964eSchristos case NPFVAR_STRING: 637f0ae964eSchristos vp = npfctl_parse_ifnet(npfvar_expand_string(vp), 638f0ae964eSchristos AF_UNSPEC); 639f0ae964eSchristos type = npfvar_get_type(vp, 0); 640f0ae964eSchristos goto again; 6418094cc3dSrmind case NPFVAR_FAM: 6428094cc3dSrmind $$ = vp; 6438094cc3dSrmind break; 644ec3d0e07Srmind case NPFVAR_INTERFACE: 645ec3d0e07Srmind ifna = npfvar_get_data(vp, type, 0); 646ec3d0e07Srmind $$ = ifna->ifna_addrs; 647ec3d0e07Srmind break; 6488094cc3dSrmind case -1: 649ec3d0e07Srmind yyerror("undefined variable '%s'", $1); 6508094cc3dSrmind break; 6518094cc3dSrmind default: 652ec3d0e07Srmind yyerror("wrong variable '%s' type '%s' for address " 653ec3d0e07Srmind "or interface", $1, npfvar_type(type)); 6548094cc3dSrmind break; 6558094cc3dSrmind } 6568094cc3dSrmind } 657f03cb1d4Srmind ; 658f03cb1d4Srmind 659f03cb1d4Srmind addr 660f03cb1d4Srmind : IPV4ADDR { $$ = $1; } 661f03cb1d4Srmind | IPV6ADDR { $$ = $1; } 662f03cb1d4Srmind ; 663f03cb1d4Srmind 664f03cb1d4Srmind port_range 665f03cb1d4Srmind : PORT port /* just port */ 666f03cb1d4Srmind { 667f03cb1d4Srmind $$ = npfctl_parse_port_range($2, $2); 668f03cb1d4Srmind } 669add921fbSrmind | PORT port MINUS port /* port from-to */ 670f03cb1d4Srmind { 671f03cb1d4Srmind $$ = npfctl_parse_port_range($2, $4); 672f03cb1d4Srmind } 673add921fbSrmind | PORT VAR_ID 674add921fbSrmind { 675ff24200fSchristos $$ = npfctl_parse_port_range_variable($2); 676ff24200fSchristos } 677f03cb1d4Srmind | 678f03cb1d4Srmind { 679f03cb1d4Srmind $$ = NULL; 680f03cb1d4Srmind } 681f03cb1d4Srmind ; 682f03cb1d4Srmind 683f03cb1d4Srmind port 684f2174d83Schristos : number { $$ = $1; } 685f03cb1d4Srmind | IDENTIFIER { $$ = npfctl_portno($1); } 686bd928debSchristos | STRING { $$ = npfctl_portno($1); } 687f03cb1d4Srmind ; 688f03cb1d4Srmind 689f03cb1d4Srmind icmp_type_and_code 690f03cb1d4Srmind : ICMPTYPE icmp_type 691f03cb1d4Srmind { 692afd9e22aSspz $$ = npfctl_parse_icmp($<num>0, $2, -1); 693f03cb1d4Srmind } 694f2174d83Schristos | ICMPTYPE icmp_type CODE number 695f03cb1d4Srmind { 696afd9e22aSspz $$ = npfctl_parse_icmp($<num>0, $2, $4); 697f03cb1d4Srmind } 698f03cb1d4Srmind | ICMPTYPE icmp_type CODE IDENTIFIER 699f03cb1d4Srmind { 700ec3d0e07Srmind $$ = npfctl_parse_icmp($<num>0, $2, 701ec3d0e07Srmind npfctl_icmpcode($<num>0, $2, $4)); 702f03cb1d4Srmind } 703f03cb1d4Srmind | ICMPTYPE icmp_type CODE VAR_ID 704f03cb1d4Srmind { 705f03cb1d4Srmind char *s = npfvar_expand_string(npfvar_lookup($4)); 706ec3d0e07Srmind $$ = npfctl_parse_icmp($<num>0, $2, 707ec3d0e07Srmind npfctl_icmpcode($<num>0, $2, s)); 708f03cb1d4Srmind } 70911243735Srmind | { $$ = NULL; } 710f03cb1d4Srmind ; 711f03cb1d4Srmind 712f03cb1d4Srmind tcp_flags_and_mask 713f03cb1d4Srmind : FLAGS tcp_flags SLASH tcp_flags 714f03cb1d4Srmind { 715f03cb1d4Srmind npfvar_add_elements($2, $4); 716f03cb1d4Srmind $$ = $2; 717f03cb1d4Srmind } 718f03cb1d4Srmind | FLAGS tcp_flags 719f03cb1d4Srmind { 720f03cb1d4Srmind char *s = npfvar_get_data($2, NPFVAR_TCPFLAG, 0); 721f03cb1d4Srmind npfvar_add_elements($2, npfctl_parse_tcpflag(s)); 722f03cb1d4Srmind $$ = $2; 723f03cb1d4Srmind } 724f03cb1d4Srmind | { $$ = NULL; } 725f03cb1d4Srmind ; 726f03cb1d4Srmind 727f03cb1d4Srmind tcp_flags 728f03cb1d4Srmind : IDENTIFIER { $$ = npfctl_parse_tcpflag($1); } 729f03cb1d4Srmind ; 730f03cb1d4Srmind 731f03cb1d4Srmind icmp_type 732f2174d83Schristos : number { $$ = $1; } 733afd9e22aSspz | IDENTIFIER { $$ = npfctl_icmptype($<num>-1, $1); } 734f03cb1d4Srmind | VAR_ID 735f03cb1d4Srmind { 736f03cb1d4Srmind char *s = npfvar_expand_string(npfvar_lookup($1)); 737afd9e22aSspz $$ = npfctl_icmptype($<num>-1, s); 738f03cb1d4Srmind } 739f03cb1d4Srmind ; 740f03cb1d4Srmind 741d1d2e2c9Srmind ifname 742f75d4435Srmind : some_name 743f03cb1d4Srmind { 744d1d2e2c9Srmind npfctl_note_interface($1); 745d1d2e2c9Srmind $$ = $1; 746f03cb1d4Srmind } 747f03cb1d4Srmind | VAR_ID 748f03cb1d4Srmind { 749f03cb1d4Srmind npfvar_t *vp = npfvar_lookup($1); 750ff24200fSchristos const int type = npfvar_get_type(vp, 0); 751ec3d0e07Srmind ifnet_addr_t *ifna; 752f03cb1d4Srmind 753f03cb1d4Srmind switch (type) { 754f03cb1d4Srmind case NPFVAR_STRING: 755ec3d0e07Srmind case NPFVAR_IDENTIFIER: 756d1d2e2c9Srmind $$ = npfvar_expand_string(vp); 757f03cb1d4Srmind break; 758ec3d0e07Srmind case NPFVAR_INTERFACE: 759ec3d0e07Srmind ifna = npfvar_get_data(vp, type, 0); 760d1d2e2c9Srmind $$ = ifna->ifna_name; 761ec3d0e07Srmind break; 762f03cb1d4Srmind case -1: 763f03cb1d4Srmind yyerror("undefined variable '%s' for interface", $1); 764f03cb1d4Srmind break; 765f03cb1d4Srmind default: 766f03cb1d4Srmind yyerror("wrong variable '%s' type '%s' for interface", 767f03cb1d4Srmind $1, npfvar_type(type)); 768f03cb1d4Srmind break; 769f03cb1d4Srmind } 770d1d2e2c9Srmind npfctl_note_interface($$); 771f03cb1d4Srmind } 772f03cb1d4Srmind ; 773f03cb1d4Srmind 774348a4177Srmind ifaddrs 775348a4177Srmind : afamily PAR_OPEN ifname PAR_CLOSE 776348a4177Srmind { 777348a4177Srmind $$ = npfctl_parse_ifnet($3, $1); 778348a4177Srmind } 779348a4177Srmind ; 780348a4177Srmind 781348a4177Srmind ifref 782348a4177Srmind : ifname 783348a4177Srmind | ifaddrs 784348a4177Srmind { 785348a4177Srmind ifnet_addr_t *ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0); 786348a4177Srmind npfctl_note_interface(ifna->ifna_name); 787348a4177Srmind $$ = ifna->ifna_name; 788348a4177Srmind } 789348a4177Srmind ; 790348a4177Srmind 791f2174d83Schristos number 792f2174d83Schristos : HEX { $$ = $1; } 793f2174d83Schristos | NUM { $$ = $1; } 794f2174d83Schristos ; 795f2174d83Schristos 796f75d4435Srmind some_name 797f03cb1d4Srmind : IDENTIFIER { $$ = $1; } 798f03cb1d4Srmind | STRING { $$ = $1; } 799f03cb1d4Srmind ; 800f03cb1d4Srmind 801f03cb1d4Srmind %% 802