1*bf40bfa8Srmind /* $NetBSD: npf_parse.y,v 1.46 2017/12/10 22:04:41 rmind Exp $ */ 2f03cb1d4Srmind 3f03cb1d4Srmind /*- 4df8b1943Srmind * Copyright (c) 2011-2017 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 <err.h> 35f03cb1d4Srmind #include <netdb.h> 366a296064Sjoerg #include <stdio.h> 376a296064Sjoerg #include <stdlib.h> 386a296064Sjoerg #include <string.h> 396c441296Srmind #ifdef __NetBSD__ 406a296064Sjoerg #include <vis.h> 416c441296Srmind #endif 42f03cb1d4Srmind 43f03cb1d4Srmind #include "npfctl.h" 44f03cb1d4Srmind 458b3f8af5Srmind #define YYSTACKSIZE 4096 468b3f8af5Srmind 4737527ec6Srmind int yyparsetarget; 48f03cb1d4Srmind const char * yyfilename; 49f03cb1d4Srmind 50f03cb1d4Srmind extern int yylineno, yycolumn; 51f03cb1d4Srmind extern int yylex(void); 52f03cb1d4Srmind 53f03cb1d4Srmind void 54f03cb1d4Srmind yyerror(const char *fmt, ...) 55f03cb1d4Srmind { 56f03cb1d4Srmind extern int yyleng; 57f03cb1d4Srmind extern char *yytext; 58f03cb1d4Srmind 597c0a5ca2Srmind char *msg, *context = estrndup(yytext, yyleng); 604e3d5046Srmind bool eol = (*context == '\n'); 61f03cb1d4Srmind va_list ap; 62f03cb1d4Srmind 63f03cb1d4Srmind va_start(ap, fmt); 64f03cb1d4Srmind vasprintf(&msg, fmt, ap); 65f03cb1d4Srmind va_end(ap); 66f03cb1d4Srmind 674e3d5046Srmind fprintf(stderr, "%s:%d:%d: %s", yyfilename, 684e3d5046Srmind yylineno - (int)eol, yycolumn, msg); 694e3d5046Srmind if (!eol) { 706c441296Srmind #ifdef __NetBSD__ 714e3d5046Srmind size_t len = strlen(context); 723c7c5558Srmind char *dst = ecalloc(1, len * 4 + 1); 734e3d5046Srmind 74f03cb1d4Srmind strvisx(dst, context, len, VIS_WHITE|VIS_CSTYLE); 75f0764fe1Skre context = dst; 766c441296Srmind #endif 776c441296Srmind fprintf(stderr, " near '%s'", context); 784e3d5046Srmind } 794e3d5046Srmind fprintf(stderr, "\n"); 80f03cb1d4Srmind exit(EXIT_FAILURE); 81f03cb1d4Srmind } 82f03cb1d4Srmind 8337527ec6Srmind #define CHECK_PARSER_FILE \ 8437527ec6Srmind if (yyparsetarget != NPFCTL_PARSE_FILE) \ 8537527ec6Srmind yyerror("rule must be in the group"); 8637527ec6Srmind 8737527ec6Srmind #define CHECK_PARSER_STRING \ 8837527ec6Srmind if (yyparsetarget != NPFCTL_PARSE_STRING) \ 8937527ec6Srmind yyerror("invalid rule syntax"); 9037527ec6Srmind 91f03cb1d4Srmind %} 92f03cb1d4Srmind 933b895110Schristos %token ALG 94a894e3f7Srmind %token ALGO 95f03cb1d4Srmind %token ALL 96f03cb1d4Srmind %token ANY 97f03cb1d4Srmind %token APPLY 98add921fbSrmind %token ARROWBOTH 99add921fbSrmind %token ARROWLEFT 100add921fbSrmind %token ARROWRIGHT 101f03cb1d4Srmind %token BLOCK 10293bbacf8Schristos %token BPFJIT 103820aad11Srmind %token CDB 104f03cb1d4Srmind %token CURLY_CLOSE 105f03cb1d4Srmind %token CURLY_OPEN 106f03cb1d4Srmind %token CODE 107f03cb1d4Srmind %token COLON 108f03cb1d4Srmind %token COMMA 109f03cb1d4Srmind %token DEFAULT 110f03cb1d4Srmind %token TDYNAMIC 111add921fbSrmind %token TSTATIC 112f03cb1d4Srmind %token EQ 11335bd148cSrmind %token EXCL_MARK 114f03cb1d4Srmind %token TFILE 115f03cb1d4Srmind %token FLAGS 116f03cb1d4Srmind %token FROM 117f03cb1d4Srmind %token GROUP 118f03cb1d4Srmind %token HASH 119f03cb1d4Srmind %token ICMPTYPE 120f03cb1d4Srmind %token ID 121f03cb1d4Srmind %token IN 122348a4177Srmind %token INET4 123f03cb1d4Srmind %token INET6 124df8b1943Srmind %token IFADDRS 125f03cb1d4Srmind %token INTERFACE 126add921fbSrmind %token MAP 127*bf40bfa8Srmind %token NO_PORTS 128f03cb1d4Srmind %token MINUS 129f03cb1d4Srmind %token NAME 130a894e3f7Srmind %token NPT66 131f03cb1d4Srmind %token ON 13293bbacf8Schristos %token OFF 133f03cb1d4Srmind %token OUT 134f03cb1d4Srmind %token PAR_CLOSE 135f03cb1d4Srmind %token PAR_OPEN 136f03cb1d4Srmind %token PASS 137c6e77e2aSrmind %token PCAP_FILTER 138f03cb1d4Srmind %token PORT 139f03cb1d4Srmind %token PROCEDURE 140f03cb1d4Srmind %token PROTO 141f03cb1d4Srmind %token FAMILY 142ba11b3c0Srmind %token FINAL 14337527ec6Srmind %token FORW 144f03cb1d4Srmind %token RETURN 145f03cb1d4Srmind %token RETURNICMP 146f03cb1d4Srmind %token RETURNRST 1477b486642Srmind %token RULESET 148f03cb1d4Srmind %token SEPLINE 14993bbacf8Schristos %token SET 150f03cb1d4Srmind %token SLASH 151ba11b3c0Srmind %token STATEFUL 152196178afSrmind %token STATEFUL_ENDS 153f03cb1d4Srmind %token TABLE 154f03cb1d4Srmind %token TCP 155f03cb1d4Srmind %token TO 156f03cb1d4Srmind %token TREE 157f03cb1d4Srmind %token TYPE 158afd9e22aSspz %token <num> ICMP 159afd9e22aSspz %token <num> ICMP6 160f03cb1d4Srmind 161f03cb1d4Srmind %token <num> HEX 162f03cb1d4Srmind %token <str> IDENTIFIER 163f03cb1d4Srmind %token <str> IPV4ADDR 164f03cb1d4Srmind %token <str> IPV6ADDR 165f03cb1d4Srmind %token <num> NUM 16648a1ec7dSrmind %token <fpnum> FPNUM 167f03cb1d4Srmind %token <str> STRING 168f03cb1d4Srmind %token <str> TABLE_ID 169f03cb1d4Srmind %token <str> VAR_ID 170f03cb1d4Srmind 171df8b1943Srmind %type <str> addr, some_name, table_store, dynamic_ifaddrs 172348a4177Srmind %type <str> proc_param_val, opt_apply, ifname, on_ifname, ifref 173d1d2e2c9Srmind %type <num> port, opt_final, number, afamily, opt_family 174c6e77e2aSrmind %type <num> block_or_pass, rule_dir, group_dir, block_opts 17535bd148cSrmind %type <num> maybe_not, opt_stateful, icmp_type, table_type 176*bf40bfa8Srmind %type <num> map_sd, map_algo, map_flags, map_type 177df8b1943Srmind %type <var> static_ifaddrs, addr_or_ifaddr 178df8b1943Srmind %type <var> port_range, icmp_type_and_code 179f03cb1d4Srmind %type <var> filt_addr, addr_and_mask, tcp_flags, tcp_flags_and_mask 18048a1ec7dSrmind %type <var> procs, proc_call, proc_param_list, proc_param 181348a4177Srmind %type <var> element, list_elems, list, value 182add921fbSrmind %type <addrport> mapseg 183f03cb1d4Srmind %type <filtopts> filt_opts, all_or_filt_opts 184a6f5b6a3Srmind %type <optproto> proto opt_proto 185c6e77e2aSrmind %type <rulegroup> group_opts 18693bbacf8Schristos %type <tf> onoff 187f03cb1d4Srmind 188f03cb1d4Srmind %union { 189f03cb1d4Srmind char * str; 19093bbacf8Schristos bool tf; 191f03cb1d4Srmind unsigned long num; 19248a1ec7dSrmind double fpnum; 193ec3d0e07Srmind npfvar_t * var; 194add921fbSrmind addr_port_t addrport; 195f03cb1d4Srmind filt_opts_t filtopts; 196f03cb1d4Srmind opt_proto_t optproto; 197f03cb1d4Srmind rule_group_t rulegroup; 198f03cb1d4Srmind } 199f03cb1d4Srmind 200f03cb1d4Srmind %% 201f03cb1d4Srmind 202f03cb1d4Srmind input 20337527ec6Srmind : { CHECK_PARSER_FILE } lines 20437527ec6Srmind | { CHECK_PARSER_STRING } rule 205f03cb1d4Srmind ; 206f03cb1d4Srmind 207f03cb1d4Srmind lines 2089ff93001Sriastradh : lines SEPLINE line 209f03cb1d4Srmind | line 210f03cb1d4Srmind ; 211f03cb1d4Srmind 212f03cb1d4Srmind line 2138f6547d8Srmind : vardef 214f03cb1d4Srmind | table 215add921fbSrmind | map 216f03cb1d4Srmind | group 217f03cb1d4Srmind | rproc 2183b895110Schristos | alg 21993bbacf8Schristos | set 220f03cb1d4Srmind | 221f03cb1d4Srmind ; 222f03cb1d4Srmind 2238f6547d8Srmind alg 2248f6547d8Srmind : ALG STRING 2258f6547d8Srmind { 2268f6547d8Srmind npfctl_build_alg($2); 2278f6547d8Srmind } 2288f6547d8Srmind ; 2298f6547d8Srmind 23093bbacf8Schristos onoff 23193bbacf8Schristos : ON { 23293bbacf8Schristos $$ = true; 23393bbacf8Schristos } 23493bbacf8Schristos | OFF { 23593bbacf8Schristos $$ = false; 23693bbacf8Schristos } 23793bbacf8Schristos ; 23893bbacf8Schristos 23993bbacf8Schristos set 24093bbacf8Schristos : SET BPFJIT onoff { 24193bbacf8Schristos npfctl_bpfjit($3); 24293bbacf8Schristos } 24393bbacf8Schristos ; 24493bbacf8Schristos 2458f6547d8Srmind /* 2468f6547d8Srmind * A value - an element or a list of elements. 2478f6547d8Srmind * Can be assigned to a variable or used inline. 2488f6547d8Srmind */ 2498f6547d8Srmind 2508f6547d8Srmind vardef 251348a4177Srmind : VAR_ID EQ value 252f03cb1d4Srmind { 253348a4177Srmind npfvar_add($3, $1); 254f03cb1d4Srmind } 255f03cb1d4Srmind ; 256f03cb1d4Srmind 2578f6547d8Srmind value 2588f6547d8Srmind : element 2598f6547d8Srmind | list 260f03cb1d4Srmind ; 261f03cb1d4Srmind 2628f6547d8Srmind list 263f03cb1d4Srmind : CURLY_OPEN list_elems CURLY_CLOSE 264348a4177Srmind { 265348a4177Srmind $$ = $2; 266348a4177Srmind } 267f03cb1d4Srmind ; 268f03cb1d4Srmind 269f03cb1d4Srmind list_elems 2709ff93001Sriastradh : list_elems COMMA element 271348a4177Srmind { 272348a4177Srmind npfvar_add_elements($1, $3); 273348a4177Srmind } 2748f6547d8Srmind | element 275f03cb1d4Srmind ; 276f03cb1d4Srmind 2778f6547d8Srmind element 278f03cb1d4Srmind : IDENTIFIER 279f03cb1d4Srmind { 280348a4177Srmind $$ = npfvar_create_from_string(NPFVAR_IDENTIFIER, $1); 281f03cb1d4Srmind } 282f03cb1d4Srmind | STRING 283f03cb1d4Srmind { 284348a4177Srmind $$ = npfvar_create_from_string(NPFVAR_STRING, $1); 285f03cb1d4Srmind } 286f2174d83Schristos | number MINUS number 287ff24200fSchristos { 288348a4177Srmind $$ = npfctl_parse_port_range($1, $3); 289ff24200fSchristos } 290f2174d83Schristos | number 291f03cb1d4Srmind { 292348a4177Srmind $$ = npfvar_create_element(NPFVAR_NUM, &$1, sizeof($1)); 293f03cb1d4Srmind } 294f03cb1d4Srmind | VAR_ID 295f03cb1d4Srmind { 296348a4177Srmind $$ = npfvar_create_from_string(NPFVAR_VAR_ID, $1); 297f03cb1d4Srmind } 298348a4177Srmind | TABLE_ID { $$ = npfctl_parse_table_id($1); } 299df8b1943Srmind | dynamic_ifaddrs { $$ = npfctl_ifnet_table($1); } 300df8b1943Srmind | static_ifaddrs { $$ = $1; } 301348a4177Srmind | addr_and_mask { $$ = $1; } 302f03cb1d4Srmind ; 303f03cb1d4Srmind 3048f6547d8Srmind /* 3058f6547d8Srmind * Table definition. 3068f6547d8Srmind */ 3078f6547d8Srmind 308f03cb1d4Srmind table 309f03cb1d4Srmind : TABLE TABLE_ID TYPE table_type table_store 310f03cb1d4Srmind { 311f03cb1d4Srmind npfctl_build_table($2, $4, $5); 312f03cb1d4Srmind } 313f03cb1d4Srmind ; 314f03cb1d4Srmind 315f03cb1d4Srmind table_type 316f03cb1d4Srmind : HASH { $$ = NPF_TABLE_HASH; } 317664900efSrmind | TREE { $$ = NPF_TABLE_TREE; } 318820aad11Srmind | CDB { $$ = NPF_TABLE_CDB; } 319f03cb1d4Srmind ; 320f03cb1d4Srmind 321f03cb1d4Srmind table_store 322f03cb1d4Srmind : TDYNAMIC { $$ = NULL; } 323f03cb1d4Srmind | TFILE STRING { $$ = $2; } 324f03cb1d4Srmind ; 325f03cb1d4Srmind 3268f6547d8Srmind /* 3278f6547d8Srmind * Map definition. 3288f6547d8Srmind */ 3298f6547d8Srmind 330add921fbSrmind map_sd 331add921fbSrmind : TSTATIC { $$ = NPFCTL_NAT_STATIC; } 332add921fbSrmind | TDYNAMIC { $$ = NPFCTL_NAT_DYNAMIC; } 333add921fbSrmind | { $$ = NPFCTL_NAT_DYNAMIC; } 334f03cb1d4Srmind ; 335f03cb1d4Srmind 336a894e3f7Srmind map_algo 337a894e3f7Srmind : ALGO NPT66 { $$ = NPF_ALGO_NPT66; } 338a894e3f7Srmind | { $$ = 0; } 339a894e3f7Srmind ; 340a894e3f7Srmind 341*bf40bfa8Srmind map_flags 342*bf40bfa8Srmind : NO_PORTS { $$ = NPF_NAT_PORTS; } 343*bf40bfa8Srmind | { $$ = 0; } 344*bf40bfa8Srmind ; 345*bf40bfa8Srmind 346add921fbSrmind map_type 347add921fbSrmind : ARROWBOTH { $$ = NPF_NATIN | NPF_NATOUT; } 348add921fbSrmind | ARROWLEFT { $$ = NPF_NATIN; } 349add921fbSrmind | ARROWRIGHT { $$ = NPF_NATOUT; } 350add921fbSrmind ; 351add921fbSrmind 352add921fbSrmind mapseg 353348a4177Srmind : addr_or_ifaddr port_range 354f03cb1d4Srmind { 355add921fbSrmind $$.ap_netaddr = $1; 356add921fbSrmind $$.ap_portrange = $2; 357f03cb1d4Srmind } 358f03cb1d4Srmind ; 359f03cb1d4Srmind 360add921fbSrmind map 361*bf40bfa8Srmind : MAP ifref map_sd map_algo map_flags mapseg map_type mapseg 36275cf8dc1Smlelstv PASS opt_proto all_or_filt_opts 363f03cb1d4Srmind { 364*bf40bfa8Srmind npfctl_build_natseg($3, $7, $5, $2, &$6, &$8, &$10, &$11, $4); 365f03cb1d4Srmind } 366*bf40bfa8Srmind | MAP ifref map_sd map_algo map_flags mapseg map_type mapseg 367a6f5b6a3Srmind { 368*bf40bfa8Srmind npfctl_build_natseg($3, $7, $5, $2, &$6, &$8, NULL, NULL, $4); 369a6f5b6a3Srmind } 370*bf40bfa8Srmind | MAP ifref map_sd map_algo map_flags proto mapseg map_type mapseg 371f03cb1d4Srmind { 372*bf40bfa8Srmind npfctl_build_natseg($3, $8, $5, $2, &$7, &$9, &$6, NULL, $4); 373f03cb1d4Srmind } 374c6e77e2aSrmind | MAP RULESET group_opts 3757b486642Srmind { 376d1d2e2c9Srmind npfctl_build_maprset($3.rg_name, $3.rg_attr, $3.rg_ifname); 3777b486642Srmind } 378f03cb1d4Srmind ; 379f03cb1d4Srmind 3808f6547d8Srmind /* 3818f6547d8Srmind * Rule procedure definition and its parameters. 3828f6547d8Srmind */ 3838f6547d8Srmind 384f03cb1d4Srmind rproc 385f03cb1d4Srmind : PROCEDURE STRING CURLY_OPEN procs CURLY_CLOSE 386f03cb1d4Srmind { 387f03cb1d4Srmind npfctl_build_rproc($2, $4); 388f03cb1d4Srmind } 389f03cb1d4Srmind ; 390f03cb1d4Srmind 391f03cb1d4Srmind procs 3929ff93001Sriastradh : procs SEPLINE proc_call 393f03cb1d4Srmind { 394f03cb1d4Srmind $$ = npfvar_add_elements($1, $3); 395f03cb1d4Srmind } 39648a1ec7dSrmind | proc_call { $$ = $1; } 39748a1ec7dSrmind ; 39848a1ec7dSrmind 39948a1ec7dSrmind proc_call 40048a1ec7dSrmind : IDENTIFIER COLON proc_param_list 40148a1ec7dSrmind { 40248a1ec7dSrmind proc_call_t pc; 40348a1ec7dSrmind 4047c0a5ca2Srmind pc.pc_name = estrdup($1); 40548a1ec7dSrmind pc.pc_opts = $3; 406348a4177Srmind 407348a4177Srmind $$ = npfvar_create_element(NPFVAR_PROC, &pc, sizeof(pc)); 40848a1ec7dSrmind } 409f03cb1d4Srmind | { $$ = NULL; } 410f03cb1d4Srmind ; 411f03cb1d4Srmind 41248a1ec7dSrmind proc_param_list 4139ff93001Sriastradh : proc_param_list COMMA proc_param 414f03cb1d4Srmind { 41548a1ec7dSrmind $$ = npfvar_add_elements($1, $3); 41648a1ec7dSrmind } 41748a1ec7dSrmind | proc_param { $$ = $1; } 41848a1ec7dSrmind | { $$ = NULL; } 41948a1ec7dSrmind ; 420f03cb1d4Srmind 42148a1ec7dSrmind proc_param 42248a1ec7dSrmind : some_name proc_param_val 42348a1ec7dSrmind { 42448a1ec7dSrmind proc_param_t pp; 42548a1ec7dSrmind 4267c0a5ca2Srmind pp.pp_param = estrdup($1); 4277c0a5ca2Srmind pp.pp_value = $2 ? estrdup($2) : NULL; 428348a4177Srmind 429348a4177Srmind $$ = npfvar_create_element(NPFVAR_PROC_PARAM, &pp, sizeof(pp)); 430f03cb1d4Srmind } 431f03cb1d4Srmind ; 432f03cb1d4Srmind 43348a1ec7dSrmind proc_param_val 43448a1ec7dSrmind : some_name { $$ = $1; } 435f2174d83Schristos | number { (void)asprintf(&$$, "%ld", $1); } 43648a1ec7dSrmind | FPNUM { (void)asprintf(&$$, "%lf", $1); } 437f03cb1d4Srmind | { $$ = NULL; } 438f03cb1d4Srmind ; 439f03cb1d4Srmind 4408f6547d8Srmind /* 4418f6547d8Srmind * Group and dynamic ruleset definition. 4428f6547d8Srmind */ 4438f6547d8Srmind 444f03cb1d4Srmind group 445c6e77e2aSrmind : GROUP group_opts 446f03cb1d4Srmind { 447348a4177Srmind /* Build a group. Increase the nesting level. */ 448c6e77e2aSrmind npfctl_build_group($2.rg_name, $2.rg_attr, 449d1d2e2c9Srmind $2.rg_ifname, $2.rg_default); 450f03cb1d4Srmind } 45137527ec6Srmind ruleset_block 45237527ec6Srmind { 45337527ec6Srmind /* Decrease the nesting level. */ 45437527ec6Srmind npfctl_build_group_end(); 45537527ec6Srmind } 456f03cb1d4Srmind ; 457f03cb1d4Srmind 4587b486642Srmind ruleset 459c6e77e2aSrmind : RULESET group_opts 4607b486642Srmind { 4617b486642Srmind /* Ruleset is a dynamic group. */ 462c6e77e2aSrmind npfctl_build_group($2.rg_name, $2.rg_attr | NPF_RULE_DYNAMIC, 463d1d2e2c9Srmind $2.rg_ifname, $2.rg_default); 4647b486642Srmind npfctl_build_group_end(); 4657b486642Srmind } 466f03cb1d4Srmind ; 467f03cb1d4Srmind 468c6e77e2aSrmind group_dir 469c6e77e2aSrmind : FORW { $$ = NPF_RULE_FORW; } 470c6e77e2aSrmind | rule_dir 471c6e77e2aSrmind ; 472c6e77e2aSrmind 473c6e77e2aSrmind group_opts 474f03cb1d4Srmind : DEFAULT 475f03cb1d4Srmind { 47637527ec6Srmind memset(&$$, 0, sizeof(rule_group_t)); 47737527ec6Srmind $$.rg_default = true; 478f03cb1d4Srmind } 479d1d2e2c9Srmind | STRING group_dir on_ifname 480f03cb1d4Srmind { 48137527ec6Srmind memset(&$$, 0, sizeof(rule_group_t)); 482c6e77e2aSrmind $$.rg_name = $1; 483c6e77e2aSrmind $$.rg_attr = $2; 484d1d2e2c9Srmind $$.rg_ifname = $3; 485f03cb1d4Srmind } 486f03cb1d4Srmind ; 487f03cb1d4Srmind 48837527ec6Srmind ruleset_block 4897b486642Srmind : CURLY_OPEN ruleset_def CURLY_CLOSE 490f03cb1d4Srmind ; 491f03cb1d4Srmind 4927b486642Srmind ruleset_def 4939ff93001Sriastradh : ruleset_def SEPLINE rule_group 49437527ec6Srmind | rule_group 495f03cb1d4Srmind ; 496f03cb1d4Srmind 49737527ec6Srmind rule_group 49837527ec6Srmind : rule 49937527ec6Srmind | group 5007b486642Srmind | ruleset 50137527ec6Srmind | 50285aa89dfSrmind ; 50337527ec6Srmind 5048f6547d8Srmind /* 5058f6547d8Srmind * Rule and misc. 5068f6547d8Srmind */ 5078f6547d8Srmind 508f03cb1d4Srmind rule 509d1d2e2c9Srmind : block_or_pass opt_stateful rule_dir opt_final on_ifname 510ec3d0e07Srmind opt_family opt_proto all_or_filt_opts opt_apply 511f03cb1d4Srmind { 512ba11b3c0Srmind npfctl_build_rule($1 | $2 | $3 | $4, $5, 513c6e77e2aSrmind $6, &$7, &$8, NULL, $9); 514c6e77e2aSrmind } 515d1d2e2c9Srmind | block_or_pass opt_stateful rule_dir opt_final on_ifname 516c6e77e2aSrmind PCAP_FILTER STRING opt_apply 517c6e77e2aSrmind { 518c6e77e2aSrmind npfctl_build_rule($1 | $2 | $3 | $4, $5, 519c6e77e2aSrmind AF_UNSPEC, NULL, NULL, $7, $8); 520f03cb1d4Srmind } 521f03cb1d4Srmind ; 522f03cb1d4Srmind 523f03cb1d4Srmind block_or_pass 524f03cb1d4Srmind : BLOCK block_opts { $$ = $2; } 525f03cb1d4Srmind | PASS { $$ = NPF_RULE_PASS; } 526f03cb1d4Srmind ; 527f03cb1d4Srmind 528f03cb1d4Srmind rule_dir 529f03cb1d4Srmind : IN { $$ = NPF_RULE_IN; } 530f03cb1d4Srmind | OUT { $$ = NPF_RULE_OUT; } 531f03cb1d4Srmind | { $$ = NPF_RULE_IN | NPF_RULE_OUT; } 532f03cb1d4Srmind ; 533f03cb1d4Srmind 534ba11b3c0Srmind opt_final 535ba11b3c0Srmind : FINAL { $$ = NPF_RULE_FINAL; } 536f03cb1d4Srmind | { $$ = 0; } 537f03cb1d4Srmind ; 538f03cb1d4Srmind 539d1d2e2c9Srmind on_ifname 540348a4177Srmind : ON ifref { $$ = $2; } 541d1d2e2c9Srmind | { $$ = NULL; } 542f03cb1d4Srmind ; 543f03cb1d4Srmind 544ec3d0e07Srmind afamily 545348a4177Srmind : INET4 { $$ = AF_INET; } 546ec3d0e07Srmind | INET6 { $$ = AF_INET6; } 547ec3d0e07Srmind ; 548ec3d0e07Srmind 54935bd148cSrmind maybe_not 55035bd148cSrmind : EXCL_MARK { $$ = true; } 55135bd148cSrmind | { $$ = false; } 55235bd148cSrmind ; 55335bd148cSrmind 554f75d4435Srmind opt_family 555ec3d0e07Srmind : FAMILY afamily { $$ = $2; } 556f75d4435Srmind | { $$ = AF_UNSPEC; } 557f03cb1d4Srmind ; 558f03cb1d4Srmind 559a6f5b6a3Srmind proto 560f03cb1d4Srmind : PROTO TCP tcp_flags_and_mask 561f03cb1d4Srmind { 562f03cb1d4Srmind $$.op_proto = IPPROTO_TCP; 563f03cb1d4Srmind $$.op_opts = $3; 564f03cb1d4Srmind } 565f03cb1d4Srmind | PROTO ICMP icmp_type_and_code 566f03cb1d4Srmind { 567f03cb1d4Srmind $$.op_proto = IPPROTO_ICMP; 568f03cb1d4Srmind $$.op_opts = $3; 569f03cb1d4Srmind } 570afd9e22aSspz | PROTO ICMP6 icmp_type_and_code 571afd9e22aSspz { 572afd9e22aSspz $$.op_proto = IPPROTO_ICMPV6; 573afd9e22aSspz $$.op_opts = $3; 574afd9e22aSspz } 575f75d4435Srmind | PROTO some_name 576f03cb1d4Srmind { 577f75d4435Srmind $$.op_proto = npfctl_protono($2); 578f75d4435Srmind $$.op_opts = NULL; 579f75d4435Srmind } 580f2174d83Schristos | PROTO number 581f75d4435Srmind { 582f75d4435Srmind $$.op_proto = $2; 583f03cb1d4Srmind $$.op_opts = NULL; 584f03cb1d4Srmind } 585a6f5b6a3Srmind ; 586a6f5b6a3Srmind 587a6f5b6a3Srmind opt_proto 588a6f5b6a3Srmind : proto { $$ = $1; } 589f03cb1d4Srmind | 590f03cb1d4Srmind { 591f03cb1d4Srmind $$.op_proto = -1; 592f03cb1d4Srmind $$.op_opts = NULL; 593f03cb1d4Srmind } 594f03cb1d4Srmind ; 595f03cb1d4Srmind 596f03cb1d4Srmind all_or_filt_opts 597f03cb1d4Srmind : ALL 598f03cb1d4Srmind { 59935bd148cSrmind $$.fo_finvert = false; 600add921fbSrmind $$.fo_from.ap_netaddr = NULL; 601add921fbSrmind $$.fo_from.ap_portrange = NULL; 60235bd148cSrmind $$.fo_tinvert = false; 603add921fbSrmind $$.fo_to.ap_netaddr = NULL; 604add921fbSrmind $$.fo_to.ap_portrange = NULL; 605f03cb1d4Srmind } 606f03cb1d4Srmind | filt_opts { $$ = $1; } 607f03cb1d4Srmind ; 608f03cb1d4Srmind 609ba11b3c0Srmind opt_stateful 610f75d4435Srmind : STATEFUL { $$ = NPF_RULE_STATEFUL; } 611196178afSrmind | STATEFUL_ENDS { $$ = NPF_RULE_STATEFUL | NPF_RULE_MULTIENDS; } 612f03cb1d4Srmind | { $$ = 0; } 613f03cb1d4Srmind ; 614f03cb1d4Srmind 615f03cb1d4Srmind opt_apply 616f03cb1d4Srmind : APPLY STRING { $$ = $2; } 617f03cb1d4Srmind | { $$ = NULL; } 618f03cb1d4Srmind ; 619f03cb1d4Srmind 620f03cb1d4Srmind block_opts 621f03cb1d4Srmind : RETURNRST { $$ = NPF_RULE_RETRST; } 622f03cb1d4Srmind | RETURNICMP { $$ = NPF_RULE_RETICMP; } 623f03cb1d4Srmind | RETURN { $$ = NPF_RULE_RETRST | NPF_RULE_RETICMP; } 624f03cb1d4Srmind | { $$ = 0; } 625f03cb1d4Srmind ; 626f03cb1d4Srmind 627f03cb1d4Srmind filt_opts 62835bd148cSrmind : FROM maybe_not filt_addr port_range TO maybe_not filt_addr port_range 629f03cb1d4Srmind { 63035bd148cSrmind $$.fo_finvert = $2; 63135bd148cSrmind $$.fo_from.ap_netaddr = $3; 63235bd148cSrmind $$.fo_from.ap_portrange = $4; 63335bd148cSrmind $$.fo_tinvert = $6; 63435bd148cSrmind $$.fo_to.ap_netaddr = $7; 63535bd148cSrmind $$.fo_to.ap_portrange = $8; 636f03cb1d4Srmind } 63735bd148cSrmind | FROM maybe_not filt_addr port_range 638f03cb1d4Srmind { 63935bd148cSrmind $$.fo_finvert = $2; 64035bd148cSrmind $$.fo_from.ap_netaddr = $3; 64135bd148cSrmind $$.fo_from.ap_portrange = $4; 64235bd148cSrmind $$.fo_tinvert = false; 643add921fbSrmind $$.fo_to.ap_netaddr = NULL; 644add921fbSrmind $$.fo_to.ap_portrange = NULL; 645f03cb1d4Srmind } 64635bd148cSrmind | TO maybe_not filt_addr port_range 647f03cb1d4Srmind { 64835bd148cSrmind $$.fo_finvert = false; 649add921fbSrmind $$.fo_from.ap_netaddr = NULL; 650add921fbSrmind $$.fo_from.ap_portrange = NULL; 65135bd148cSrmind $$.fo_tinvert = $2; 65235bd148cSrmind $$.fo_to.ap_netaddr = $3; 65335bd148cSrmind $$.fo_to.ap_portrange = $4; 654f03cb1d4Srmind } 655f03cb1d4Srmind ; 656f03cb1d4Srmind 657f03cb1d4Srmind filt_addr 658dceaabc9Schristos : list { $$ = $1; } 659dceaabc9Schristos | addr_or_ifaddr { $$ = $1; } 660df8b1943Srmind | dynamic_ifaddrs { $$ = npfctl_ifnet_table($1); } 661f03cb1d4Srmind | TABLE_ID { $$ = npfctl_parse_table_id($1); } 662f03cb1d4Srmind | ANY { $$ = NULL; } 663f03cb1d4Srmind ; 664f03cb1d4Srmind 665f03cb1d4Srmind addr_and_mask 666f2174d83Schristos : addr SLASH number 667f03cb1d4Srmind { 668f03cb1d4Srmind $$ = npfctl_parse_fam_addr_mask($1, NULL, &$3); 669f03cb1d4Srmind } 670f03cb1d4Srmind | addr SLASH addr 671f03cb1d4Srmind { 672f03cb1d4Srmind $$ = npfctl_parse_fam_addr_mask($1, $3, NULL); 673f03cb1d4Srmind } 674f03cb1d4Srmind | addr 675f03cb1d4Srmind { 676f03cb1d4Srmind $$ = npfctl_parse_fam_addr_mask($1, NULL, NULL); 677f03cb1d4Srmind } 678f03cb1d4Srmind ; 679f03cb1d4Srmind 680348a4177Srmind addr_or_ifaddr 681f75d4435Srmind : addr_and_mask 682f75d4435Srmind { 683f75d4435Srmind assert($1 != NULL); 684f75d4435Srmind $$ = $1; 685f75d4435Srmind } 686df8b1943Srmind | static_ifaddrs 6878094cc3dSrmind { 6885a32644fSchristos if (npfvar_get_count($1) != 1) 6895a32644fSchristos yyerror("multiple interfaces are not supported"); 690ec3d0e07Srmind ifnet_addr_t *ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0); 691ec3d0e07Srmind $$ = ifna->ifna_addrs; 6928094cc3dSrmind } 6938094cc3dSrmind | VAR_ID 6948094cc3dSrmind { 6958094cc3dSrmind npfvar_t *vp = npfvar_lookup($1); 696f0ae964eSchristos int type = npfvar_get_type(vp, 0); 697ec3d0e07Srmind ifnet_addr_t *ifna; 6988094cc3dSrmind 699f0ae964eSchristos again: 7008094cc3dSrmind switch (type) { 701f0ae964eSchristos case NPFVAR_IDENTIFIER: 702f0ae964eSchristos case NPFVAR_STRING: 703f0ae964eSchristos vp = npfctl_parse_ifnet(npfvar_expand_string(vp), 704f0ae964eSchristos AF_UNSPEC); 705f0ae964eSchristos type = npfvar_get_type(vp, 0); 706f0ae964eSchristos goto again; 7078094cc3dSrmind case NPFVAR_FAM: 708df8b1943Srmind case NPFVAR_TABLE: 7098094cc3dSrmind $$ = vp; 7108094cc3dSrmind break; 711ec3d0e07Srmind case NPFVAR_INTERFACE: 71215718026Srmind $$ = NULL; 71315718026Srmind for (u_int i = 0; i < npfvar_get_count(vp); i++) { 71415718026Srmind ifna = npfvar_get_data(vp, type, i); 71515718026Srmind $$ = npfvar_add_elements($$, ifna->ifna_addrs); 71615718026Srmind } 717ec3d0e07Srmind break; 7188094cc3dSrmind case -1: 719ec3d0e07Srmind yyerror("undefined variable '%s'", $1); 7208094cc3dSrmind break; 7218094cc3dSrmind default: 722ec3d0e07Srmind yyerror("wrong variable '%s' type '%s' for address " 723ec3d0e07Srmind "or interface", $1, npfvar_type(type)); 7248094cc3dSrmind break; 7258094cc3dSrmind } 7268094cc3dSrmind } 727f03cb1d4Srmind ; 728f03cb1d4Srmind 729f03cb1d4Srmind addr 730f03cb1d4Srmind : IPV4ADDR { $$ = $1; } 731f03cb1d4Srmind | IPV6ADDR { $$ = $1; } 732f03cb1d4Srmind ; 733f03cb1d4Srmind 734f03cb1d4Srmind port_range 735f03cb1d4Srmind : PORT port /* just port */ 736f03cb1d4Srmind { 737f03cb1d4Srmind $$ = npfctl_parse_port_range($2, $2); 738f03cb1d4Srmind } 739add921fbSrmind | PORT port MINUS port /* port from-to */ 740f03cb1d4Srmind { 741f03cb1d4Srmind $$ = npfctl_parse_port_range($2, $4); 742f03cb1d4Srmind } 743add921fbSrmind | PORT VAR_ID 744add921fbSrmind { 7456c441296Srmind npfvar_t *vp = npfvar_lookup($2); 7466c441296Srmind $$ = npfctl_parse_port_range_variable($2, vp); 747ff24200fSchristos } 7486c441296Srmind | PORT list 749f03cb1d4Srmind { 7506c441296Srmind $$ = npfctl_parse_port_range_variable(NULL, $2); 751f03cb1d4Srmind } 7526c441296Srmind | { $$ = NULL; } 753f03cb1d4Srmind ; 754f03cb1d4Srmind 755f03cb1d4Srmind port 756f2174d83Schristos : number { $$ = $1; } 757f03cb1d4Srmind | IDENTIFIER { $$ = npfctl_portno($1); } 758bd928debSchristos | STRING { $$ = npfctl_portno($1); } 759f03cb1d4Srmind ; 760f03cb1d4Srmind 761f03cb1d4Srmind icmp_type_and_code 762f03cb1d4Srmind : ICMPTYPE icmp_type 763f03cb1d4Srmind { 764afd9e22aSspz $$ = npfctl_parse_icmp($<num>0, $2, -1); 765f03cb1d4Srmind } 766f2174d83Schristos | ICMPTYPE icmp_type CODE number 767f03cb1d4Srmind { 768afd9e22aSspz $$ = npfctl_parse_icmp($<num>0, $2, $4); 769f03cb1d4Srmind } 770f03cb1d4Srmind | ICMPTYPE icmp_type CODE IDENTIFIER 771f03cb1d4Srmind { 772ec3d0e07Srmind $$ = npfctl_parse_icmp($<num>0, $2, 773ec3d0e07Srmind npfctl_icmpcode($<num>0, $2, $4)); 774f03cb1d4Srmind } 775f03cb1d4Srmind | ICMPTYPE icmp_type CODE VAR_ID 776f03cb1d4Srmind { 777f03cb1d4Srmind char *s = npfvar_expand_string(npfvar_lookup($4)); 778ec3d0e07Srmind $$ = npfctl_parse_icmp($<num>0, $2, 779ec3d0e07Srmind npfctl_icmpcode($<num>0, $2, s)); 780f03cb1d4Srmind } 78111243735Srmind | { $$ = NULL; } 782f03cb1d4Srmind ; 783f03cb1d4Srmind 784f03cb1d4Srmind tcp_flags_and_mask 785f03cb1d4Srmind : FLAGS tcp_flags SLASH tcp_flags 786f03cb1d4Srmind { 787f03cb1d4Srmind npfvar_add_elements($2, $4); 788f03cb1d4Srmind $$ = $2; 789f03cb1d4Srmind } 790f03cb1d4Srmind | FLAGS tcp_flags 791f03cb1d4Srmind { 7925a32644fSchristos if (npfvar_get_count($2) != 1) 7935a32644fSchristos yyerror("multiple tcpflags are not supported"); 794f03cb1d4Srmind char *s = npfvar_get_data($2, NPFVAR_TCPFLAG, 0); 795f03cb1d4Srmind npfvar_add_elements($2, npfctl_parse_tcpflag(s)); 796f03cb1d4Srmind $$ = $2; 797f03cb1d4Srmind } 798f03cb1d4Srmind | { $$ = NULL; } 799f03cb1d4Srmind ; 800f03cb1d4Srmind 801f03cb1d4Srmind tcp_flags 802f03cb1d4Srmind : IDENTIFIER { $$ = npfctl_parse_tcpflag($1); } 803f03cb1d4Srmind ; 804f03cb1d4Srmind 805f03cb1d4Srmind icmp_type 806f2174d83Schristos : number { $$ = $1; } 807afd9e22aSspz | IDENTIFIER { $$ = npfctl_icmptype($<num>-1, $1); } 808f03cb1d4Srmind | VAR_ID 809f03cb1d4Srmind { 810f03cb1d4Srmind char *s = npfvar_expand_string(npfvar_lookup($1)); 811afd9e22aSspz $$ = npfctl_icmptype($<num>-1, s); 812f03cb1d4Srmind } 813f03cb1d4Srmind ; 814f03cb1d4Srmind 815d1d2e2c9Srmind ifname 816f75d4435Srmind : some_name 817f03cb1d4Srmind { 818d1d2e2c9Srmind npfctl_note_interface($1); 819d1d2e2c9Srmind $$ = $1; 820f03cb1d4Srmind } 821f03cb1d4Srmind | VAR_ID 822f03cb1d4Srmind { 823f03cb1d4Srmind npfvar_t *vp = npfvar_lookup($1); 824ff24200fSchristos const int type = npfvar_get_type(vp, 0); 825ec3d0e07Srmind ifnet_addr_t *ifna; 826f03cb1d4Srmind 827f03cb1d4Srmind switch (type) { 828f03cb1d4Srmind case NPFVAR_STRING: 829ec3d0e07Srmind case NPFVAR_IDENTIFIER: 830d1d2e2c9Srmind $$ = npfvar_expand_string(vp); 831f03cb1d4Srmind break; 832ec3d0e07Srmind case NPFVAR_INTERFACE: 8335a32644fSchristos if (npfvar_get_count(vp) != 1) 8345a32644fSchristos yyerror( 8355a32644fSchristos "multiple interfaces are not supported"); 836ec3d0e07Srmind ifna = npfvar_get_data(vp, type, 0); 837d1d2e2c9Srmind $$ = ifna->ifna_name; 838ec3d0e07Srmind break; 839f03cb1d4Srmind case -1: 840f03cb1d4Srmind yyerror("undefined variable '%s' for interface", $1); 841f03cb1d4Srmind break; 842f03cb1d4Srmind default: 843f03cb1d4Srmind yyerror("wrong variable '%s' type '%s' for interface", 844f03cb1d4Srmind $1, npfvar_type(type)); 845f03cb1d4Srmind break; 846f03cb1d4Srmind } 847d1d2e2c9Srmind npfctl_note_interface($$); 848f03cb1d4Srmind } 849f03cb1d4Srmind ; 850f03cb1d4Srmind 851df8b1943Srmind static_ifaddrs 852348a4177Srmind : afamily PAR_OPEN ifname PAR_CLOSE 853348a4177Srmind { 854348a4177Srmind $$ = npfctl_parse_ifnet($3, $1); 855348a4177Srmind } 856348a4177Srmind ; 857348a4177Srmind 858df8b1943Srmind dynamic_ifaddrs 859df8b1943Srmind : IFADDRS PAR_OPEN ifname PAR_CLOSE 860df8b1943Srmind { 861df8b1943Srmind $$ = $3; 862df8b1943Srmind } 863df8b1943Srmind ; 864df8b1943Srmind 865348a4177Srmind ifref 866348a4177Srmind : ifname 867df8b1943Srmind | dynamic_ifaddrs 868df8b1943Srmind | static_ifaddrs 869348a4177Srmind { 8705a32644fSchristos if (npfvar_get_count($1) != 1) 8715a32644fSchristos yyerror("multiple interfaces are not supported"); 872348a4177Srmind ifnet_addr_t *ifna = npfvar_get_data($1, NPFVAR_INTERFACE, 0); 873348a4177Srmind npfctl_note_interface(ifna->ifna_name); 874348a4177Srmind $$ = ifna->ifna_name; 875348a4177Srmind } 876348a4177Srmind ; 877348a4177Srmind 878f2174d83Schristos number 879f2174d83Schristos : HEX { $$ = $1; } 880f2174d83Schristos | NUM { $$ = $1; } 881f2174d83Schristos ; 882f2174d83Schristos 883f75d4435Srmind some_name 884f03cb1d4Srmind : IDENTIFIER { $$ = $1; } 885f03cb1d4Srmind | STRING { $$ = $1; } 886f03cb1d4Srmind ; 887f03cb1d4Srmind 888f03cb1d4Srmind %% 889