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 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 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 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 | FWMARK '=' MARKMASK 115 { 116 $$ = alloc_node(SSF_MARKMASK, $3); 117 } 118 | FWMARK NEQ MARKMASK 119 { 120 $$ = alloc_node(SSF_NOT, alloc_node(SSF_MARKMASK, $3)); 121 } 122 | AUTOBOUND 123 { 124 $$ = alloc_node(SSF_S_AUTO, NULL); 125 } 126 | expr '|' expr 127 { 128 $$ = alloc_node(SSF_OR, $1); 129 $$->post = $3; 130 } 131 | expr expr 132 { 133 $$ = alloc_node(SSF_AND, $1); 134 $$->post = $2; 135 } 136 | expr '&' expr 137 138 { 139 $$ = alloc_node(SSF_AND, $1); 140 $$->post = $3; 141 } 142 | '!' expr 143 { 144 $$ = alloc_node(SSF_NOT, $2); 145 } 146 | '(' expr ')' 147 { 148 $$ = $2; 149 } 150 ; 151 %% 152 153 static char *get_token_from_line(char **ptr) 154 { 155 char *tok, *cp = *ptr; 156 157 while (*cp == ' ' || *cp == '\t') cp++; 158 159 if (*cp == 0) { 160 *ptr = cp; 161 return NULL; 162 } 163 164 tok = cp; 165 166 while (*cp != 0 && *cp != ' ' && *cp != '\t') { 167 /* Backslash escapes everything. */ 168 if (*cp == '\\') { 169 char *tp; 170 for (tp = cp; tp != tok; tp--) 171 *tp = *(tp-1); 172 cp++; 173 tok++; 174 if (*cp == 0) 175 break; 176 } 177 cp++; 178 } 179 if (*cp) 180 *cp++ = 0; 181 *ptr = cp; 182 return tok; 183 } 184 185 int yylex(void) 186 { 187 static char argbuf[1024]; 188 static char *tokptr = argbuf; 189 static int argc; 190 char *curtok; 191 192 do { 193 while (*tokptr == 0) { 194 tokptr = NULL; 195 if (argc < yy_argc) { 196 tokptr = yy_argv[argc]; 197 argc++; 198 } else if (yy_fp) { 199 while (tokptr == NULL) { 200 if (fgets(argbuf, sizeof(argbuf)-1, yy_fp) == NULL) 201 return 0; 202 argbuf[sizeof(argbuf)-1] = 0; 203 if (strlen(argbuf) == sizeof(argbuf) - 1) { 204 fprintf(stderr, "Too long line in filter"); 205 exit(-1); 206 } 207 if (argbuf[strlen(argbuf)-1] == '\n') 208 argbuf[strlen(argbuf)-1] = 0; 209 if (argbuf[0] == '#' || argbuf[0] == '0') 210 continue; 211 tokptr = argbuf; 212 } 213 } else { 214 return 0; 215 } 216 } 217 } while ((curtok = get_token_from_line(&tokptr)) == NULL); 218 219 if (strcmp(curtok, "!") == 0 || 220 strcmp(curtok, "not") == 0) 221 return '!'; 222 if (strcmp(curtok, "&") == 0 || 223 strcmp(curtok, "&&") == 0 || 224 strcmp(curtok, "and") == 0) 225 return '&'; 226 if (strcmp(curtok, "|") == 0 || 227 strcmp(curtok, "||") == 0 || 228 strcmp(curtok, "or") == 0) 229 return '|'; 230 if (strcmp(curtok, "(") == 0) 231 return '('; 232 if (strcmp(curtok, ")") == 0) 233 return ')'; 234 if (strcmp(curtok, "dst") == 0) { 235 tok_type = DCOND; 236 return DCOND; 237 } 238 if (strcmp(curtok, "src") == 0) { 239 tok_type = SCOND; 240 return SCOND; 241 } 242 if (strcmp(curtok, "dport") == 0) { 243 tok_type = DPORT; 244 return DPORT; 245 } 246 if (strcmp(curtok, "sport") == 0) { 247 tok_type = SPORT; 248 return SPORT; 249 } 250 if (strcmp(curtok, "fwmark") == 0) { 251 tok_type = FWMARK; 252 return FWMARK; 253 } 254 if (strcmp(curtok, ">=") == 0 || 255 strcmp(curtok, "ge") == 0 || 256 strcmp(curtok, "geq") == 0) 257 return GEQ; 258 if (strcmp(curtok, "<=") == 0 || 259 strcmp(curtok, "le") == 0 || 260 strcmp(curtok, "leq") == 0) 261 return LEQ; 262 if (strcmp(curtok, "!=") == 0 || 263 strcmp(curtok, "ne") == 0 || 264 strcmp(curtok, "neq") == 0) 265 return NEQ; 266 if (strcmp(curtok, "=") == 0 || 267 strcmp(curtok, "==") == 0 || 268 strcmp(curtok, "eq") == 0) 269 return '='; 270 if (strcmp(curtok, ">") == 0 || 271 strcmp(curtok, "gt") == 0) 272 return '>'; 273 if (strcmp(curtok, "<") == 0 || 274 strcmp(curtok, "lt") == 0) 275 return '<'; 276 if (strcmp(curtok, "autobound") == 0) { 277 tok_type = AUTOBOUND; 278 return AUTOBOUND; 279 } 280 if (tok_type == FWMARK) { 281 yylval = (void*)parse_markmask(curtok); 282 if (yylval == NULL) { 283 fprintf(stderr, "Cannot parse mark %s.\n", curtok); 284 exit(1); 285 } 286 return MARKMASK; 287 } 288 yylval = (void*)parse_hostcond(curtok, tok_type == SPORT || tok_type == DPORT); 289 if (yylval == NULL) { 290 fprintf(stderr, "Cannot parse dst/src address.\n"); 291 exit(1); 292 } 293 return HOSTCOND; 294 } 295 296 int ssfilter_parse(struct ssfilter **f, int argc, char **argv, FILE *fp) 297 { 298 yy_argc = argc; 299 yy_argv = argv; 300 yy_fp = fp; 301 yy_ret = f; 302 303 if (yyparse()) { 304 fprintf(stderr, " Sorry.\n"); 305 return -1; 306 } 307 return 0; 308 } 309