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