1 /*- 2 * Copyright (c) 2011-2025 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Martin Husemann. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 %{ 31 #include <stdio.h> 32 #include <stdlib.h> 33 #include <unistd.h> 34 #include <err.h> 35 36 #include "npfctl.h" 37 #include "npf_parse.h" 38 39 int yycolumn; 40 41 #define YY_USER_ACTION yycolumn += yyleng; 42 43 extern int yystarttoken; 44 extern int yylineno; 45 extern const char * yyfilename; 46 extern int yyparse(void); 47 extern void yyrestart(FILE *); 48 49 void 50 npfctl_parse_file(const char *name) 51 { 52 const bool use_stdin = strcmp(name, "-") == 0; 53 FILE *fp; 54 55 fp = use_stdin ? fdopen(STDIN_FILENO, "r") : fopen(name, "r"); 56 if (fp == NULL) { 57 err(EXIT_FAILURE, "open '%s'", name); 58 } 59 yystarttoken = 0; 60 yyrestart(fp); 61 yylineno = 1; 62 yycolumn = 0; 63 yyfilename = use_stdin ? "stdin" : name; 64 yyparse(); 65 fclose(fp); 66 } 67 68 void 69 npfctl_parse_string(const char *str, parse_entry_t entry) 70 { 71 YY_BUFFER_STATE bs; 72 73 switch (entry) { 74 case NPFCTL_PARSE_RULE: 75 yystarttoken = RULE_ENTRY_TOKEN; 76 break; 77 case NPFCTL_PARSE_MAP: 78 yystarttoken = MAP_ENTRY_TOKEN; 79 break; 80 default: 81 abort(); 82 } 83 84 bs = yy_scan_string(str); 85 yyfilename = "stdin"; 86 yyparse(); 87 yy_delete_buffer(bs); 88 } 89 90 %} 91 92 %option noyywrap nounput noinput 93 94 ID [a-zA-Z_][a-zA-Z_0-9]* 95 DID [a-zA-Z_][a-zA-Z_0-9-]* 96 SPID [a-zA-Z][a-zA-Z_0-9.]* 97 NUMBER [0-9]+ 98 HEXDIG [0-9a-fA-F]+ 99 100 %% 101 %{ 102 /* This is prepended to yylex(). */ 103 if (yystarttoken) { 104 int token = yystarttoken; 105 yystarttoken = 0; 106 return token; 107 } 108 %} 109 110 alg return ALG; 111 table return TABLE; 112 type return TYPE; 113 hash return HASH; 114 tree return TREE; 115 lpm return LPM; 116 cdb return CDB; 117 const return CONST; 118 static return TSTATIC; 119 dynamic return TDYNAMIC; 120 file return TFILE; 121 map return MAP; 122 no-ports return NO_PORTS; 123 set return SET; 124 "<->" return ARROWBOTH; 125 "<-" return ARROWLEFT; 126 "->" return ARROWRIGHT; 127 algo return ALGO; 128 netmap return NETMAP; 129 ipset return IPSET; 130 "ip-hash" return IPHASH; 131 "round-robin" return ROUNDROBIN; 132 npt66 return NPT66; 133 "-" return MINUS; 134 procedure return PROCEDURE; 135 \\\n yylineno++; yycolumn = 0; 136 \n yylineno++; yycolumn = 0; return NEWLINE; 137 ; return SEMICOLON; 138 name return NAME; 139 group return GROUP; 140 default return DEFAULT; 141 in return IN; 142 out return OUT; 143 forw return FORW; 144 interface return INTERFACE; 145 all return ALL; 146 block return BLOCK; 147 pass return PASS; 148 pcap-filter return PCAP_FILTER; 149 stateful return STATEFUL; 150 stateful-all return STATEFUL_ALL; 151 apply return APPLY; 152 final return FINAL; 153 quick return FINAL; 154 on return ON; 155 off return OFF; 156 inet6 return INET6; 157 inet4 return INET4; 158 ifaddrs return IFADDRS; 159 proto return PROTO; 160 family return FAMILY; 161 tcp return TCP; 162 icmp { yylval.num = IPPROTO_ICMP; return ICMP; } 163 ipv6-icmp { yylval.num = IPPROTO_ICMPV6; return ICMP6; } 164 \"ipv6-icmp\" { yylval.num = IPPROTO_ICMPV6; return ICMP6; } 165 return-rst return RETURNRST; 166 return-icmp return RETURNICMP; 167 return return RETURN; 168 ruleset return RULESET; 169 from return FROM; 170 to return TO; 171 port return PORT; 172 flags return FLAGS; 173 icmp-type return ICMPTYPE; 174 code return CODE; 175 any return ANY; 176 user return USER; 177 ether return ETHER; 178 layer-2 return L2; 179 180 "/" return SLASH; 181 "{" return CURLY_OPEN; 182 "}" return CURLY_CLOSE; 183 "(" return PAR_OPEN; 184 ")" return PAR_CLOSE; 185 "," return COMMA; 186 "=" return EQ; 187 "!" return EXCL_MARK; 188 "<" return LT; 189 ">" return GT; 190 "<>" return XRG; 191 "><" return IRG; 192 193 "0x"{HEXDIG} { 194 char *endp, *buf = ecalloc(1, yyleng + 1); 195 buf[yyleng] = 0; 196 yylval.num = strtoul(buf+2, &endp, 16); 197 free(buf); 198 return HEX; 199 } 200 201 "Ex"{HEXDIG} { 202 yylval.str = estrndup(yytext, yyleng); 203 return ETHERHEX; 204 } 205 206 {NUMBER}"."{NUMBER} { 207 char *endp, *buf = estrndup(yytext, yyleng); 208 yylval.fpnum = strtod(buf, &endp); 209 free(buf); 210 return FPNUM; 211 } 212 213 {HEXDIG}(":"{HEXDIG}){5} { 214 yylval.str = estrndup(yytext, yyleng); 215 return MACADDR; 216 } 217 218 {HEXDIG}":"[0-9a-fA-F:]* { 219 yylval.str = estrndup(yytext, yyleng); 220 return IPV6ADDR; 221 } 222 223 "::"{HEXDIG}[0-9a-fA-F:.]* { 224 yylval.str = estrndup(yytext, yyleng); 225 return IPV6ADDR; 226 } 227 228 {NUMBER}"."[0-9][0-9.]* { 229 yylval.str = estrndup(yytext, yyleng); 230 return IPV4ADDR; 231 } 232 233 {NUMBER} { 234 char *endp, *buf = estrndup(yytext, yyleng); 235 yylval.num = strtoul(buf, &endp, 10); 236 free(buf); 237 return NUM; 238 } 239 240 "<"{DID}">" { 241 yylval.str = estrndup(yytext + 1, yyleng - 2); 242 return TABLE_ID; 243 } 244 245 "$"{ID} { 246 yylval.str = estrndup(yytext + 1, yyleng - 1); 247 return VAR_ID; 248 } 249 250 {ID}"."{SPID}+ { 251 yylval.str = estrndup(yytext, yyleng); 252 return PARAM; 253 } 254 255 {ID} { 256 yylval.str = estrndup(yytext, yyleng); 257 return IDENTIFIER; 258 } 259 260 \"[^\"]*\" { 261 yylval.str = estrndup(yytext + 1, yyleng - 2); 262 return STRING; 263 } 264 265 #.*$ /* drop comment until end of line */ 266 [ \t] /* eat whitespace */ 267 268 : return COLON; 269 270 . return INVALID; 271