• 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 #include "ssfilter.h"
8 
9 typedef struct ssfilter * ssfilter_t;
10 
11 #define YYSTYPE ssfilter_t
12 
alloc_node(int type,void * pred)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 
yyerror(char * s)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 
yylex(void)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 
ssfilter_parse(struct ssfilter ** f,int argc,char ** argv,FILE * fp)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 }
276