1 /*-
2  * Copyright (c) 2011-2012 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
npfctl_parse_file(const char * name)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
npfctl_parse_string(const char * str,parse_entry_t entry)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 
177 "/"                           return SLASH;
178 "{"                           return CURLY_OPEN;
179 "}"                           return CURLY_CLOSE;
180 "("                           return PAR_OPEN;
181 ")"                           return PAR_CLOSE;
182 ","                           return COMMA;
183 "="                           return EQ;
184 "!"                           return EXCL_MARK;
185 
186 "0x"{HEXDIG} {
187                               char *endp, *buf = ecalloc(1, yyleng + 1);
188                               buf[yyleng] = 0;
189                               yylval.num = strtoul(buf+2, &endp, 16);
190                               free(buf);
191                               return HEX;
192                     }
193 
194 {NUMBER}"."{NUMBER} {
195                               char *endp, *buf = estrndup(yytext, yyleng);
196                               yylval.fpnum = strtod(buf, &endp);
197                               free(buf);
198                               return FPNUM;
199                     }
200 
201 {HEXDIG}":"[0-9a-fA-F:]* {
202                               yylval.str = estrndup(yytext, yyleng);
203                               return IPV6ADDR;
204                     }
205 
206 "::"{HEXDIG}[0-9a-fA-F:.]* {
207                               yylval.str = estrndup(yytext, yyleng);
208                               return IPV6ADDR;
209                     }
210 
211 {NUMBER}"."[0-9][0-9.]* {
212                               yylval.str = estrndup(yytext, yyleng);
213                               return IPV4ADDR;
214                     }
215 
216 {NUMBER}  {
217                               char *endp, *buf = estrndup(yytext, yyleng);
218                               yylval.num = strtoul(buf, &endp, 10);
219                               free(buf);
220                               return NUM;
221                     }
222 
223 "<"{DID}">"         {
224                               yylval.str = estrndup(yytext + 1, yyleng - 2);
225                               return TABLE_ID;
226                     }
227 
228 "$"{ID}             {
229                               yylval.str = estrndup(yytext + 1, yyleng - 1);
230                               return VAR_ID;
231                     }
232 
233 {ID}"."{SPID}+      {
234                               yylval.str = estrndup(yytext, yyleng);
235                               return PARAM;
236                     }
237 
238 {ID}                {
239                               yylval.str = estrndup(yytext, yyleng);
240                               return IDENTIFIER;
241                     }
242 
243 \"[^\"]*\"          {
244                               yylval.str = estrndup(yytext + 1, yyleng - 2);
245                               return STRING;
246                     }
247 
248 #.*$                /* drop comment until end of line */
249 [ \t]               /* eat whitespace */
250 
251 :                   return COLON;
252 
253 .                   return INVALID;
254