Home | History | Annotate | Download | only in misc
      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