]> git.proxmox.com Git - mirror_iproute2.git/blame - misc/ssfilter.y
ssfilter: Fix for inverted last expression
[mirror_iproute2.git] / misc / ssfilter.y
CommitLineData
aba5acdf
SH
1%{
2
3#include <stdio.h>
43cc93e3 4#include <stdlib.h>
aba5acdf
SH
5#include <malloc.h>
6#include <string.h>
7#include "ssfilter.h"
8
9typedef struct ssfilter * ssfilter_t;
10
11#define YYSTYPE ssfilter_t
12
13static struct ssfilter * alloc_node(int type, void *pred)
14{
15 struct ssfilter *n = malloc(sizeof(*n));
16 if (n == NULL)
17 abort();
18 n->type = type;
19 n->pred = pred;
20 n->post = NULL;
21 return n;
22}
23
24static char **yy_argv;
25static int yy_argc;
26static FILE *yy_fp;
27static ssfilter_t *yy_ret;
7871f7db 28static int tok_type = -1;
aba5acdf
SH
29
30static int yylex(void);
31
32static void yyerror(char *s)
33{
34 fprintf(stderr, "ss: bison bellows (while parsing filter): \"%s!\"", s);
35}
36
37%}
38
ec75249b 39%token HOSTCOND DCOND SCOND DPORT SPORT LEQ GEQ NEQ AUTOBOUND DEVCOND DEVNAME MARKMASK FWMARK
aba5acdf
SH
40%left '|'
41%left '&'
42%nonassoc '!'
43
44%%
38d209ec 45applet: exprlist
aba5acdf 46 {
38d209ec
PS
47 *yy_ret = $1;
48 $$ = $1;
aba5acdf
SH
49 }
50 | null
51 ;
38d209ec 52
aba5acdf
SH
53null: /* NOTHING */ { $$ = NULL; }
54 ;
38d209ec 55
b2038cc0 56exprlist: expr
b2038cc0
PS
57 | exprlist '|' expr
58 {
59 $$ = alloc_node(SSF_OR, $1);
60 $$->post = $3;
61 }
62 | exprlist '&' expr
63 {
64 $$ = alloc_node(SSF_AND, $1);
65 $$->post = $3;
66 }
67 | exprlist expr
68 {
69 $$ = alloc_node(SSF_AND, $1);
70 $$->post = $2;
71 }
72 ;
73
38d209ec
PS
74eq: '='
75 | /* nothing */
76 ;
77
78expr: '(' exprlist ')'
79 {
80 $$ = $2;
81 }
6495bca9
PS
82 | '!' expr
83 {
84 $$ = alloc_node(SSF_NOT, $2);
85 }
38d209ec 86 | DCOND eq HOSTCOND
aba5acdf 87 {
38d209ec 88 $$ = alloc_node(SSF_DCOND, $3);
aba5acdf 89 }
38d209ec 90 | SCOND eq HOSTCOND
ae665a52 91 {
38d209ec 92 $$ = alloc_node(SSF_SCOND, $3);
aba5acdf
SH
93 }
94 | DPORT GEQ HOSTCOND
95 {
96 $$ = alloc_node(SSF_D_GE, $3);
97 }
98 | DPORT LEQ HOSTCOND
99 {
100 $$ = alloc_node(SSF_D_LE, $3);
101 }
102 | DPORT '>' HOSTCOND
103 {
104 $$ = alloc_node(SSF_NOT, alloc_node(SSF_D_LE, $3));
105 }
106 | DPORT '<' HOSTCOND
107 {
108 $$ = alloc_node(SSF_NOT, alloc_node(SSF_D_GE, $3));
109 }
38d209ec 110 | DPORT eq HOSTCOND
aba5acdf
SH
111 {
112 $$ = alloc_node(SSF_DCOND, $3);
113 }
114 | DPORT NEQ HOSTCOND
115 {
116 $$ = alloc_node(SSF_NOT, alloc_node(SSF_DCOND, $3));
117 }
118
119 | SPORT GEQ HOSTCOND
120 {
121 $$ = alloc_node(SSF_S_GE, $3);
122 }
123 | SPORT LEQ HOSTCOND
124 {
125 $$ = alloc_node(SSF_S_LE, $3);
126 }
127 | SPORT '>' HOSTCOND
128 {
129 $$ = alloc_node(SSF_NOT, alloc_node(SSF_S_LE, $3));
130 }
131 | SPORT '<' HOSTCOND
132 {
133 $$ = alloc_node(SSF_NOT, alloc_node(SSF_S_GE, $3));
134 }
38d209ec 135 | SPORT eq HOSTCOND
aba5acdf
SH
136 {
137 $$ = alloc_node(SSF_SCOND, $3);
138 }
139 | SPORT NEQ HOSTCOND
140 {
141 $$ = alloc_node(SSF_NOT, alloc_node(SSF_SCOND, $3));
142 }
38d209ec 143 | DEVNAME eq DEVCOND
2d293212
DA
144 {
145 $$ = alloc_node(SSF_DEVCOND, $3);
146 }
147 | DEVNAME NEQ DEVCOND
148 {
149 $$ = alloc_node(SSF_NOT, alloc_node(SSF_DEVCOND, $3));
150 }
38d209ec 151 | FWMARK eq MARKMASK
ec75249b
LC
152 {
153 $$ = alloc_node(SSF_MARKMASK, $3);
154 }
155 | FWMARK NEQ MARKMASK
156 {
157 $$ = alloc_node(SSF_NOT, alloc_node(SSF_MARKMASK, $3));
158 }
aba5acdf
SH
159 | AUTOBOUND
160 {
161 $$ = alloc_node(SSF_S_AUTO, NULL);
162 }
aba5acdf
SH
163;
164%%
165
166static char *get_token_from_line(char **ptr)
167{
168 char *tok, *cp = *ptr;
169
170 while (*cp == ' ' || *cp == '\t') cp++;
171
172 if (*cp == 0) {
173 *ptr = cp;
174 return NULL;
175 }
176
177 tok = cp;
178
179 while (*cp != 0 && *cp != ' ' && *cp != '\t') {
180 /* Backslash escapes everything. */
181 if (*cp == '\\') {
182 char *tp;
183 for (tp = cp; tp != tok; tp--)
184 *tp = *(tp-1);
185 cp++;
186 tok++;
187 if (*cp == 0)
188 break;
189 }
190 cp++;
191 }
192 if (*cp)
193 *cp++ = 0;
194 *ptr = cp;
195 return tok;
196}
197
198int yylex(void)
199{
200 static char argbuf[1024];
201 static char *tokptr = argbuf;
202 static int argc;
203 char *curtok;
204
205 do {
206 while (*tokptr == 0) {
207 tokptr = NULL;
208 if (argc < yy_argc) {
209 tokptr = yy_argv[argc];
210 argc++;
211 } else if (yy_fp) {
212 while (tokptr == NULL) {
50735818
SH
213 size_t len;
214
215 if (fgets(argbuf, sizeof(argbuf), yy_fp) == NULL)
aba5acdf 216 return 0;
50735818
SH
217
218 len = strnlen(argbuf, sizeof(argbuf));
219 if (len == 0) {
220 fprintf(stderr, "Invalid line\n");
221 exit(-1);
222 }
223
224 if (len >= sizeof(argbuf) - 1) {
225 fprintf(stderr, "Too long line in filter\n");
aba5acdf
SH
226 exit(-1);
227 }
50735818
SH
228 if (argbuf[len - 1] == '\n')
229 argbuf[len-1] = 0;
aba5acdf
SH
230 if (argbuf[0] == '#' || argbuf[0] == '0')
231 continue;
232 tokptr = argbuf;
233 }
234 } else {
235 return 0;
236 }
237 }
238 } while ((curtok = get_token_from_line(&tokptr)) == NULL);
239
240 if (strcmp(curtok, "!") == 0 ||
241 strcmp(curtok, "not") == 0)
242 return '!';
243 if (strcmp(curtok, "&") == 0 ||
244 strcmp(curtok, "&&") == 0 ||
245 strcmp(curtok, "and") == 0)
246 return '&';
247 if (strcmp(curtok, "|") == 0 ||
248 strcmp(curtok, "||") == 0 ||
249 strcmp(curtok, "or") == 0)
250 return '|';
251 if (strcmp(curtok, "(") == 0)
252 return '(';
253 if (strcmp(curtok, ")") == 0)
254 return ')';
7871f7db
VK
255 if (strcmp(curtok, "dst") == 0) {
256 tok_type = DCOND;
aba5acdf 257 return DCOND;
7871f7db
VK
258 }
259 if (strcmp(curtok, "src") == 0) {
260 tok_type = SCOND;
aba5acdf 261 return SCOND;
7871f7db
VK
262 }
263 if (strcmp(curtok, "dport") == 0) {
264 tok_type = DPORT;
aba5acdf 265 return DPORT;
7871f7db
VK
266 }
267 if (strcmp(curtok, "sport") == 0) {
268 tok_type = SPORT;
aba5acdf 269 return SPORT;
7871f7db 270 }
2d293212
DA
271 if (strcmp(curtok, "dev") == 0) {
272 tok_type = DEVNAME;
273 return DEVNAME;
274 }
ec75249b
LC
275 if (strcmp(curtok, "fwmark") == 0) {
276 tok_type = FWMARK;
277 return FWMARK;
278 }
aba5acdf
SH
279 if (strcmp(curtok, ">=") == 0 ||
280 strcmp(curtok, "ge") == 0 ||
281 strcmp(curtok, "geq") == 0)
282 return GEQ;
283 if (strcmp(curtok, "<=") == 0 ||
284 strcmp(curtok, "le") == 0 ||
285 strcmp(curtok, "leq") == 0)
286 return LEQ;
287 if (strcmp(curtok, "!=") == 0 ||
288 strcmp(curtok, "ne") == 0 ||
289 strcmp(curtok, "neq") == 0)
290 return NEQ;
291 if (strcmp(curtok, "=") == 0 ||
292 strcmp(curtok, "==") == 0 ||
293 strcmp(curtok, "eq") == 0)
294 return '=';
295 if (strcmp(curtok, ">") == 0 ||
296 strcmp(curtok, "gt") == 0)
297 return '>';
298 if (strcmp(curtok, "<") == 0 ||
299 strcmp(curtok, "lt") == 0)
300 return '<';
7871f7db
VK
301 if (strcmp(curtok, "autobound") == 0) {
302 tok_type = AUTOBOUND;
aba5acdf 303 return AUTOBOUND;
7871f7db 304 }
2d293212
DA
305 if (tok_type == DEVNAME) {
306 yylval = (void*)parse_devcond(curtok);
307 if (yylval == NULL) {
308 fprintf(stderr, "Cannot parse device.\n");
309 exit(1);
310 }
311 return DEVCOND;
312 }
ec75249b
LC
313 if (tok_type == FWMARK) {
314 yylval = (void*)parse_markmask(curtok);
315 if (yylval == NULL) {
316 fprintf(stderr, "Cannot parse mark %s.\n", curtok);
317 exit(1);
318 }
319 return MARKMASK;
320 }
7871f7db 321 yylval = (void*)parse_hostcond(curtok, tok_type == SPORT || tok_type == DPORT);
aba5acdf
SH
322 if (yylval == NULL) {
323 fprintf(stderr, "Cannot parse dst/src address.\n");
324 exit(1);
325 }
326 return HOSTCOND;
327}
328
329int ssfilter_parse(struct ssfilter **f, int argc, char **argv, FILE *fp)
330{
331 yy_argc = argc;
332 yy_argv = argv;
333 yy_fp = fp;
334 yy_ret = f;
335
336 if (yyparse()) {
337 fprintf(stderr, " Sorry.\n");
338 return -1;
339 }
340 return 0;
341}