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 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 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 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 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