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