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