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