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