Tagging module iproute2 - iproute2-2.6.16-2
[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
29 static int yylex(void);
30
31 static void yyerror(char *s)
32 {
33         fprintf(stderr, "ss: bison bellows (while parsing filter): \"%s!\"", s);
34 }
35
36 %}
37
38 %token HOSTCOND DCOND SCOND DPORT SPORT LEQ GEQ NEQ AUTOBOUND
39 %left '|'
40 %left '&'
41 %nonassoc '!'
42
43 %%
44 applet: null expr
45         {
46                 *yy_ret = $2;
47                 $$ = $2;
48         }
49         | null
50         ;
51 null:   /* NOTHING */ { $$ = NULL; }
52         ;
53 expr:   DCOND HOSTCOND
54         {
55                 $$ = alloc_node(SSF_DCOND, $2);
56         }
57         | SCOND HOSTCOND
58         { 
59                 $$ = alloc_node(SSF_SCOND, $2);
60         }
61         | DPORT GEQ HOSTCOND
62         {
63                 $$ = alloc_node(SSF_D_GE, $3);
64         }
65         | DPORT LEQ HOSTCOND
66         {
67                 $$ = alloc_node(SSF_D_LE, $3);
68         }
69         | DPORT '>' HOSTCOND
70         {
71                 $$ = alloc_node(SSF_NOT, alloc_node(SSF_D_LE, $3));
72         }
73         | DPORT '<' HOSTCOND
74         {
75                 $$ = alloc_node(SSF_NOT, alloc_node(SSF_D_GE, $3));
76         }
77         | DPORT '=' HOSTCOND
78         {
79                 $$ = alloc_node(SSF_DCOND, $3);
80         }
81         | DPORT NEQ HOSTCOND
82         {
83                 $$ = alloc_node(SSF_NOT, alloc_node(SSF_DCOND, $3));
84         }
85
86         | SPORT GEQ HOSTCOND
87         {
88                 $$ = alloc_node(SSF_S_GE, $3);
89         }
90         | SPORT LEQ HOSTCOND
91         {
92                 $$ = alloc_node(SSF_S_LE, $3);
93         }
94         | SPORT '>' HOSTCOND
95         {
96                 $$ = alloc_node(SSF_NOT, alloc_node(SSF_S_LE, $3));
97         }
98         | SPORT '<' HOSTCOND
99         {
100                 $$ = alloc_node(SSF_NOT, alloc_node(SSF_S_GE, $3));
101         }
102         | SPORT '=' HOSTCOND
103         {
104                 $$ = alloc_node(SSF_SCOND, $3);
105         }
106         | SPORT NEQ HOSTCOND
107         {
108                 $$ = alloc_node(SSF_NOT, alloc_node(SSF_SCOND, $3));
109         }
110
111         | AUTOBOUND
112         {
113                 $$ = alloc_node(SSF_S_AUTO, NULL);
114         }
115         | expr '|' expr
116         {
117                 $$ = alloc_node(SSF_OR, $1);
118                 $$->post = $3;
119         }
120         | expr expr
121         {
122                 $$ = alloc_node(SSF_AND, $1);
123                 $$->post = $2;
124         }
125         | expr '&' expr
126
127         {
128                 $$ = alloc_node(SSF_AND, $1);
129                 $$->post = $3;
130         }
131         | '!' expr
132         {
133                 $$ = alloc_node(SSF_NOT, $2);
134         }
135         | '(' expr ')'
136         {
137                 $$ = $2;
138         }
139 ;
140 %%
141
142 static char *get_token_from_line(char **ptr)
143 {
144         char *tok, *cp = *ptr;
145
146         while (*cp == ' ' || *cp == '\t') cp++;
147
148         if (*cp == 0) {
149                 *ptr = cp;
150                 return NULL;
151         }
152
153         tok = cp;
154
155         while (*cp != 0 && *cp != ' ' && *cp != '\t') {
156                 /* Backslash escapes everything. */
157                 if (*cp == '\\') {
158                         char *tp;
159                         for (tp = cp; tp != tok; tp--)
160                                 *tp = *(tp-1);
161                         cp++;
162                         tok++;
163                         if (*cp == 0)
164                                 break;
165                 }
166                 cp++;
167         }
168         if (*cp)
169                 *cp++ = 0;
170         *ptr = cp;
171         return tok;
172 }
173
174 int yylex(void)
175 {
176         static char argbuf[1024];
177         static char *tokptr = argbuf;
178         static int argc;
179         char *curtok;
180
181         do {
182                 while (*tokptr == 0) {
183                         tokptr = NULL;
184                         if (argc < yy_argc) {
185                                 tokptr = yy_argv[argc];
186                                 argc++;
187                         } else if (yy_fp) {
188                                 while (tokptr == NULL) {
189                                         if (fgets(argbuf, sizeof(argbuf)-1, yy_fp) == NULL)
190                                                 return 0;
191                                         argbuf[sizeof(argbuf)-1] = 0;
192                                         if (strlen(argbuf) == sizeof(argbuf) - 1) {
193                                                 fprintf(stderr, "Too long line in filter");
194                                                 exit(-1);
195                                         }
196                                         if (argbuf[strlen(argbuf)-1] == '\n')
197                                                 argbuf[strlen(argbuf)-1] = 0;
198                                         if (argbuf[0] == '#' || argbuf[0] == '0')
199                                                 continue;
200                                         tokptr = argbuf;
201                                 }
202                         } else {
203                                 return 0;
204                         }
205                 }
206         } while ((curtok = get_token_from_line(&tokptr)) == NULL);
207
208         if (strcmp(curtok, "!") == 0 ||
209             strcmp(curtok, "not") == 0)
210                 return '!';
211         if (strcmp(curtok, "&") == 0 ||
212             strcmp(curtok, "&&") == 0 ||
213             strcmp(curtok, "and") == 0)
214                 return '&';
215         if (strcmp(curtok, "|") == 0 ||
216             strcmp(curtok, "||") == 0 ||
217             strcmp(curtok, "or") == 0)
218                 return '|';
219         if (strcmp(curtok, "(") == 0)
220                 return '(';
221         if (strcmp(curtok, ")") == 0)
222                 return ')';
223         if (strcmp(curtok, "dst") == 0)
224                 return DCOND;
225         if (strcmp(curtok, "src") == 0)
226                 return SCOND;
227         if (strcmp(curtok, "dport") == 0)
228                 return DPORT;
229         if (strcmp(curtok, "sport") == 0)
230                 return SPORT;
231         if (strcmp(curtok, ">=") == 0 ||
232             strcmp(curtok, "ge") == 0 ||
233             strcmp(curtok, "geq") == 0)
234                 return GEQ;
235         if (strcmp(curtok, "<=") == 0 ||
236             strcmp(curtok, "le") == 0 ||
237             strcmp(curtok, "leq") == 0)
238                 return LEQ;
239         if (strcmp(curtok, "!=") == 0 ||
240             strcmp(curtok, "ne") == 0 ||
241             strcmp(curtok, "neq") == 0)
242                 return NEQ;
243         if (strcmp(curtok, "=") == 0 ||
244             strcmp(curtok, "==") == 0 ||
245             strcmp(curtok, "eq") == 0)
246                 return '=';
247         if (strcmp(curtok, ">") == 0 ||
248             strcmp(curtok, "gt") == 0)
249                 return '>';
250         if (strcmp(curtok, "<") == 0 ||
251             strcmp(curtok, "lt") == 0)
252                 return '<';
253         if (strcmp(curtok, "autobound") == 0)
254                 return AUTOBOUND;
255         yylval = (void*)parse_hostcond(curtok);
256         if (yylval == NULL) {
257                 fprintf(stderr, "Cannot parse dst/src address.\n");
258                 exit(1);
259         }
260         return HOSTCOND;
261 }
262
263 int ssfilter_parse(struct ssfilter **f, int argc, char **argv, FILE *fp)
264 {
265         yy_argc = argc;
266         yy_argv = argv;
267         yy_fp   = fp;
268         yy_ret  = f;
269
270         if (yyparse()) {
271                 fprintf(stderr, " Sorry.\n");
272                 return -1;
273         }
274         return 0;
275 }