1%{
2
3#include <stdio.h>
4#include <stdlib.h>
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;
28
29static int yylex(void);
30
31static 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%%
44applet: null expr
45        {
46                *yy_ret = $2;
47                $$ = $2;
48        }
49        | null
50        ;
51null:   /* NOTHING */ { $$ = NULL; }
52        ;
53expr:	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
142static 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
174int 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
263int 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