Blame misc/ssfilter.y

Packit Service 3880ab
%{
Packit Service 3880ab
Packit Service 3880ab
#include <stdio.h>
Packit Service 3880ab
#include <stdlib.h>
Packit Service 3880ab
#include <malloc.h>
Packit Service 3880ab
#include <string.h>
Packit Service 3880ab
#include "ssfilter.h"
Packit Service 3880ab
Packit Service 3880ab
typedef struct ssfilter * ssfilter_t;
Packit Service 3880ab
Packit Service 3880ab
#define YYSTYPE ssfilter_t
Packit Service 3880ab
Packit Service 3880ab
static struct ssfilter * alloc_node(int type, void *pred)
Packit Service 3880ab
{
Packit Service 3880ab
	struct ssfilter *n;
Packit Service 3880ab
Packit Service 3880ab
	if (!ssfilter_is_supported(type)) {
Packit Service 3880ab
		fprintf(stderr, "It looks like such filter is not supported! Too old kernel?\n");
Packit Service 3880ab
		exit(-1);
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	n = malloc(sizeof(*n));
Packit Service 3880ab
	if (n == NULL)
Packit Service 3880ab
		abort();
Packit Service 3880ab
	n->type = type;
Packit Service 3880ab
	n->pred = pred;
Packit Service 3880ab
	n->post = NULL;
Packit Service 3880ab
	return n;
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
static char		**yy_argv;
Packit Service 3880ab
static int		yy_argc;
Packit Service 3880ab
static FILE		*yy_fp;
Packit Service 3880ab
static ssfilter_t	*yy_ret;
Packit Service 3880ab
static int tok_type = -1;
Packit Service 3880ab
Packit Service 3880ab
static int yylex(void);
Packit Service 3880ab
Packit Service 3880ab
static void yyerror(char *s)
Packit Service 3880ab
{
Packit Service 3880ab
	fprintf(stderr, "ss: bison bellows (while parsing filter): \"%s!\"", s);
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
%}
Packit Service 3880ab
Packit Service 3880ab
%token HOSTCOND DCOND SCOND DPORT SPORT LEQ GEQ NEQ AUTOBOUND DEVCOND DEVNAME MARKMASK FWMARK CGROUPCOND CGROUPPATH
Packit Service 3880ab
%left '|'
Packit Service 3880ab
%left '&'
Packit Service 3880ab
%nonassoc '!'
Packit Service 3880ab
Packit Service 3880ab
%%
Packit Service 3880ab
applet: exprlist
Packit Service 3880ab
        {
Packit Service 3880ab
                *yy_ret = $1;
Packit Service 3880ab
                $$ = $1;
Packit Service 3880ab
        }
Packit Service 3880ab
        | null
Packit Service 3880ab
        ;
Packit Service 3880ab
Packit Service 3880ab
null:   /* NOTHING */ { $$ = NULL; }
Packit Service 3880ab
        ;
Packit Service 3880ab
Packit Service 3880ab
exprlist: expr
Packit Service 3880ab
        | exprlist '|' expr
Packit Service 3880ab
        {
Packit Service 3880ab
                $$ = alloc_node(SSF_OR, $1);
Packit Service 3880ab
                $$->post = $3;
Packit Service 3880ab
        }
Packit Service 3880ab
        | exprlist '&' expr
Packit Service 3880ab
        {
Packit Service 3880ab
                $$ = alloc_node(SSF_AND, $1);
Packit Service 3880ab
                $$->post = $3;
Packit Service 3880ab
        }
Packit Service 3880ab
        | exprlist expr
Packit Service 3880ab
        {
Packit Service 3880ab
                $$ = alloc_node(SSF_AND, $1);
Packit Service 3880ab
                $$->post = $2;
Packit Service 3880ab
        }
Packit Service 3880ab
        ;
Packit Service 3880ab
Packit Service 3880ab
eq:	'='
Packit Service 3880ab
	| /* nothing */
Packit Service 3880ab
	;
Packit Service 3880ab
Packit Service 3880ab
expr:	'(' exprlist ')'
Packit Service 3880ab
	{
Packit Service 3880ab
		$$ = $2;
Packit Service 3880ab
	}
Packit Service 3880ab
	| '!' expr
Packit Service 3880ab
	{
Packit Service 3880ab
		$$ = alloc_node(SSF_NOT, $2);
Packit Service 3880ab
	}
Packit Service 3880ab
	| DCOND eq HOSTCOND
Packit Service 3880ab
        {
Packit Service 3880ab
		$$ = alloc_node(SSF_DCOND, $3);
Packit Service 3880ab
        }
Packit Service 3880ab
        | SCOND eq HOSTCOND
Packit Service 3880ab
        {
Packit Service 3880ab
		$$ = alloc_node(SSF_SCOND, $3);
Packit Service 3880ab
        }
Packit Service 3880ab
        | DPORT GEQ HOSTCOND
Packit Service 3880ab
        {
Packit Service 3880ab
                $$ = alloc_node(SSF_D_GE, $3);
Packit Service 3880ab
        }
Packit Service 3880ab
        | DPORT LEQ HOSTCOND
Packit Service 3880ab
        {
Packit Service 3880ab
                $$ = alloc_node(SSF_D_LE, $3);
Packit Service 3880ab
        }
Packit Service 3880ab
        | DPORT '>' HOSTCOND
Packit Service 3880ab
        {
Packit Service 3880ab
                $$ = alloc_node(SSF_NOT, alloc_node(SSF_D_LE, $3));
Packit Service 3880ab
        }
Packit Service 3880ab
        | DPORT '<' HOSTCOND
Packit Service 3880ab
        {
Packit Service 3880ab
                $$ = alloc_node(SSF_NOT, alloc_node(SSF_D_GE, $3));
Packit Service 3880ab
        }
Packit Service 3880ab
        | DPORT eq HOSTCOND
Packit Service 3880ab
        {
Packit Service 3880ab
		$$ = alloc_node(SSF_DCOND, $3);
Packit Service 3880ab
        }
Packit Service 3880ab
        | DPORT NEQ HOSTCOND
Packit Service 3880ab
        {
Packit Service 3880ab
		$$ = alloc_node(SSF_NOT, alloc_node(SSF_DCOND, $3));
Packit Service 3880ab
        }
Packit Service 3880ab
Packit Service 3880ab
        | SPORT GEQ HOSTCOND
Packit Service 3880ab
        {
Packit Service 3880ab
                $$ = alloc_node(SSF_S_GE, $3);
Packit Service 3880ab
        }
Packit Service 3880ab
        | SPORT LEQ HOSTCOND
Packit Service 3880ab
        {
Packit Service 3880ab
                $$ = alloc_node(SSF_S_LE, $3);
Packit Service 3880ab
        }
Packit Service 3880ab
        | SPORT '>' HOSTCOND
Packit Service 3880ab
        {
Packit Service 3880ab
                $$ = alloc_node(SSF_NOT, alloc_node(SSF_S_LE, $3));
Packit Service 3880ab
        }
Packit Service 3880ab
        | SPORT '<' HOSTCOND
Packit Service 3880ab
        {
Packit Service 3880ab
                $$ = alloc_node(SSF_NOT, alloc_node(SSF_S_GE, $3));
Packit Service 3880ab
        }
Packit Service 3880ab
        | SPORT eq HOSTCOND
Packit Service 3880ab
        {
Packit Service 3880ab
		$$ = alloc_node(SSF_SCOND, $3);
Packit Service 3880ab
        }
Packit Service 3880ab
        | SPORT NEQ HOSTCOND
Packit Service 3880ab
        {
Packit Service 3880ab
		$$ = alloc_node(SSF_NOT, alloc_node(SSF_SCOND, $3));
Packit Service 3880ab
        }
Packit Service 3880ab
        | DEVNAME eq DEVCOND
Packit Service 3880ab
        {
Packit Service 3880ab
		$$ = alloc_node(SSF_DEVCOND, $3);
Packit Service 3880ab
        }
Packit Service 3880ab
        | DEVNAME NEQ DEVCOND
Packit Service 3880ab
        {
Packit Service 3880ab
		$$ = alloc_node(SSF_NOT, alloc_node(SSF_DEVCOND, $3));
Packit Service 3880ab
        }
Packit Service 3880ab
        | FWMARK eq MARKMASK
Packit Service 3880ab
        {
Packit Service 3880ab
                $$ = alloc_node(SSF_MARKMASK, $3);
Packit Service 3880ab
        }
Packit Service 3880ab
        | FWMARK NEQ MARKMASK
Packit Service 3880ab
        {
Packit Service 3880ab
                $$ = alloc_node(SSF_NOT, alloc_node(SSF_MARKMASK, $3));
Packit Service 3880ab
        }
Packit Service 3880ab
        | CGROUPPATH eq CGROUPCOND
Packit Service 3880ab
        {
Packit Service 3880ab
                $$ = alloc_node(SSF_CGROUPCOND, $3);
Packit Service 3880ab
        }
Packit Service 3880ab
        | CGROUPPATH NEQ CGROUPCOND
Packit Service 3880ab
        {
Packit Service 3880ab
                $$ = alloc_node(SSF_NOT, alloc_node(SSF_CGROUPCOND, $3));
Packit Service 3880ab
        }
Packit Service 3880ab
        | AUTOBOUND
Packit Service 3880ab
        {
Packit Service 3880ab
                $$ = alloc_node(SSF_S_AUTO, NULL);
Packit Service 3880ab
        }
Packit Service 3880ab
;
Packit Service 3880ab
%%
Packit Service 3880ab
Packit Service 3880ab
static char *get_token_from_line(char **ptr)
Packit Service 3880ab
{
Packit Service 3880ab
	char *tok, *cp = *ptr;
Packit Service 3880ab
Packit Service 3880ab
	while (*cp == ' ' || *cp == '\t') cp++;
Packit Service 3880ab
Packit Service 3880ab
	if (*cp == 0) {
Packit Service 3880ab
		*ptr = cp;
Packit Service 3880ab
		return NULL;
Packit Service 3880ab
	}
Packit Service 3880ab
Packit Service 3880ab
	tok = cp;
Packit Service 3880ab
Packit Service 3880ab
	while (*cp != 0 && *cp != ' ' && *cp != '\t') {
Packit Service 3880ab
		/* Backslash escapes everything. */
Packit Service 3880ab
		if (*cp == '\\') {
Packit Service 3880ab
			char *tp;
Packit Service 3880ab
			for (tp = cp; tp != tok; tp--)
Packit Service 3880ab
				*tp = *(tp-1);
Packit Service 3880ab
			cp++;
Packit Service 3880ab
			tok++;
Packit Service 3880ab
			if (*cp == 0)
Packit Service 3880ab
				break;
Packit Service 3880ab
		}
Packit Service 3880ab
		cp++;
Packit Service 3880ab
	}
Packit Service 3880ab
	if (*cp)
Packit Service 3880ab
		*cp++ = 0;
Packit Service 3880ab
	*ptr = cp;
Packit Service 3880ab
	return tok;
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
int yylex(void)
Packit Service 3880ab
{
Packit Service 3880ab
	static char argbuf[1024];
Packit Service 3880ab
	static char *tokptr = argbuf;
Packit Service 3880ab
	static int argc;
Packit Service 3880ab
	char *curtok;
Packit Service 3880ab
Packit Service 3880ab
	do {
Packit Service 3880ab
		while (*tokptr == 0) {
Packit Service 3880ab
			tokptr = NULL;
Packit Service 3880ab
			if (argc < yy_argc) {
Packit Service 3880ab
				tokptr = yy_argv[argc];
Packit Service 3880ab
				argc++;
Packit Service 3880ab
			} else if (yy_fp) {
Packit Service 3880ab
				while (tokptr == NULL) {
Packit Service 3880ab
					size_t len;
Packit Service 3880ab
Packit Service 3880ab
					if (fgets(argbuf, sizeof(argbuf), yy_fp) == NULL)
Packit Service 3880ab
						return 0;
Packit Service 3880ab
Packit Service 3880ab
					len = strnlen(argbuf, sizeof(argbuf));
Packit Service 3880ab
					if (len == 0) {
Packit Service 3880ab
						fprintf(stderr, "Invalid line\n");
Packit Service 3880ab
						exit(-1);
Packit Service 3880ab
					}
Packit Service 3880ab
Packit Service 3880ab
					if (len >= sizeof(argbuf) - 1) {
Packit Service 3880ab
						fprintf(stderr, "Too long line in filter\n");
Packit Service 3880ab
						exit(-1);
Packit Service 3880ab
					}
Packit Service 3880ab
					if (argbuf[len - 1] == '\n')
Packit Service 3880ab
						argbuf[len-1] = 0;
Packit Service 3880ab
					if (argbuf[0] == '#' || argbuf[0] == '0')
Packit Service 3880ab
						continue;
Packit Service 3880ab
					tokptr = argbuf;
Packit Service 3880ab
				}
Packit Service 3880ab
			} else {
Packit Service 3880ab
				return 0;
Packit Service 3880ab
			}
Packit Service 3880ab
		}
Packit Service 3880ab
	} while ((curtok = get_token_from_line(&tokptr)) == NULL);
Packit Service 3880ab
Packit Service 3880ab
	if (strcmp(curtok, "!") == 0 ||
Packit Service 3880ab
	    strcmp(curtok, "not") == 0)
Packit Service 3880ab
		return '!';
Packit Service 3880ab
	if (strcmp(curtok, "&") == 0 ||
Packit Service 3880ab
	    strcmp(curtok, "&&") == 0 ||
Packit Service 3880ab
	    strcmp(curtok, "and") == 0)
Packit Service 3880ab
		return '&';
Packit Service 3880ab
	if (strcmp(curtok, "|") == 0 ||
Packit Service 3880ab
	    strcmp(curtok, "||") == 0 ||
Packit Service 3880ab
	    strcmp(curtok, "or") == 0)
Packit Service 3880ab
		return '|';
Packit Service 3880ab
	if (strcmp(curtok, "(") == 0)
Packit Service 3880ab
		return '(';
Packit Service 3880ab
	if (strcmp(curtok, ")") == 0)
Packit Service 3880ab
		return ')';
Packit Service 3880ab
	if (strcmp(curtok, "dst") == 0) {
Packit Service 3880ab
		tok_type = DCOND;
Packit Service 3880ab
		return DCOND;
Packit Service 3880ab
	}
Packit Service 3880ab
	if (strcmp(curtok, "src") == 0) {
Packit Service 3880ab
                tok_type = SCOND;
Packit Service 3880ab
		return SCOND;
Packit Service 3880ab
        }
Packit Service 3880ab
	if (strcmp(curtok, "dport") == 0) {
Packit Service 3880ab
		tok_type = DPORT;
Packit Service 3880ab
		return DPORT;
Packit Service 3880ab
	}
Packit Service 3880ab
	if (strcmp(curtok, "sport") == 0) {
Packit Service 3880ab
		tok_type = SPORT;
Packit Service 3880ab
		return SPORT;
Packit Service 3880ab
	}
Packit Service 3880ab
	if (strcmp(curtok, "dev") == 0) {
Packit Service 3880ab
		tok_type = DEVNAME;
Packit Service 3880ab
		return DEVNAME;
Packit Service 3880ab
	}
Packit Service 3880ab
	if (strcmp(curtok, "fwmark") == 0) {
Packit Service 3880ab
		tok_type = FWMARK;
Packit Service 3880ab
		return FWMARK;
Packit Service 3880ab
	}
Packit Service 3880ab
	if (strcmp(curtok, "cgroup") == 0) {
Packit Service 3880ab
		tok_type = CGROUPPATH;
Packit Service 3880ab
		return CGROUPPATH;
Packit Service 3880ab
	}
Packit Service 3880ab
	if (strcmp(curtok, ">=") == 0 ||
Packit Service 3880ab
	    strcmp(curtok, "ge") == 0 ||
Packit Service 3880ab
	    strcmp(curtok, "geq") == 0)
Packit Service 3880ab
		return GEQ;
Packit Service 3880ab
	if (strcmp(curtok, "<=") == 0 ||
Packit Service 3880ab
	    strcmp(curtok, "le") == 0 ||
Packit Service 3880ab
	    strcmp(curtok, "leq") == 0)
Packit Service 3880ab
		return LEQ;
Packit Service 3880ab
	if (strcmp(curtok, "!=") == 0 ||
Packit Service 3880ab
	    strcmp(curtok, "ne") == 0 ||
Packit Service 3880ab
	    strcmp(curtok, "neq") == 0)
Packit Service 3880ab
		return NEQ;
Packit Service 3880ab
	if (strcmp(curtok, "=") == 0 ||
Packit Service 3880ab
	    strcmp(curtok, "==") == 0 ||
Packit Service 3880ab
	    strcmp(curtok, "eq") == 0)
Packit Service 3880ab
		return '=';
Packit Service 3880ab
	if (strcmp(curtok, ">") == 0 ||
Packit Service 3880ab
	    strcmp(curtok, "gt") == 0)
Packit Service 3880ab
		return '>';
Packit Service 3880ab
	if (strcmp(curtok, "<") == 0 ||
Packit Service 3880ab
	    strcmp(curtok, "lt") == 0)
Packit Service 3880ab
		return '<';
Packit Service 3880ab
	if (strcmp(curtok, "autobound") == 0) {
Packit Service 3880ab
		tok_type = AUTOBOUND;
Packit Service 3880ab
		return AUTOBOUND;
Packit Service 3880ab
	}
Packit Service 3880ab
	if (tok_type == DEVNAME) {
Packit Service 3880ab
		yylval = (void*)parse_devcond(curtok);
Packit Service 3880ab
		if (yylval == NULL) {
Packit Service 3880ab
			fprintf(stderr, "Cannot parse device.\n");
Packit Service 3880ab
			exit(1);
Packit Service 3880ab
		}
Packit Service 3880ab
		return DEVCOND;
Packit Service 3880ab
	}
Packit Service 3880ab
	if (tok_type == FWMARK) {
Packit Service 3880ab
		yylval = (void*)parse_markmask(curtok);
Packit Service 3880ab
		if (yylval == NULL) {
Packit Service 3880ab
			fprintf(stderr, "Cannot parse mark %s.\n", curtok);
Packit Service 3880ab
			exit(1);
Packit Service 3880ab
		}
Packit Service 3880ab
		return MARKMASK;
Packit Service 3880ab
	}
Packit Service 3880ab
	if (tok_type == CGROUPPATH) {
Packit Service 3880ab
		yylval = (void*)parse_cgroupcond(curtok);
Packit Service 3880ab
		if (yylval == NULL) {
Packit Service 3880ab
			fprintf(stderr, "Cannot parse cgroup %s.\n", curtok);
Packit Service 3880ab
			exit(1);
Packit Service 3880ab
		}
Packit Service 3880ab
		return CGROUPCOND;
Packit Service 3880ab
	}
Packit Service 3880ab
	yylval = (void*)parse_hostcond(curtok, tok_type == SPORT || tok_type == DPORT);
Packit Service 3880ab
	if (yylval == NULL) {
Packit Service 3880ab
		fprintf(stderr, "Cannot parse dst/src address.\n");
Packit Service 3880ab
		exit(1);
Packit Service 3880ab
	}
Packit Service 3880ab
	return HOSTCOND;
Packit Service 3880ab
}
Packit Service 3880ab
Packit Service 3880ab
int ssfilter_parse(struct ssfilter **f, int argc, char **argv, FILE *fp)
Packit Service 3880ab
{
Packit Service 3880ab
	yy_argc = argc;
Packit Service 3880ab
	yy_argv = argv;
Packit Service 3880ab
	yy_fp   = fp;
Packit Service 3880ab
	yy_ret  = f;
Packit Service 3880ab
Packit Service 3880ab
	if (yyparse()) {
Packit Service 3880ab
		fprintf(stderr, " Sorry.\n");
Packit Service 3880ab
		return -1;
Packit Service 3880ab
	}
Packit Service 3880ab
	return 0;
Packit Service 3880ab
}