static struct ssfilter * alloc_node(int type, void *pred)
{
- struct ssfilter *n = malloc(sizeof(*n));
+ struct ssfilter *n;
+
+ if (!ssfilter_is_supported(type)) {
+ fprintf(stderr, "It looks like such filter is not supported! Too old kernel?\n");
+ exit(-1);
+ }
+
+ n = malloc(sizeof(*n));
if (n == NULL)
abort();
n->type = type;
%}
-%token HOSTCOND DCOND SCOND DPORT SPORT LEQ GEQ NEQ AUTOBOUND DEVCOND DEVNAME MARKMASK FWMARK
+%token HOSTCOND DCOND SCOND DPORT SPORT LEQ GEQ NEQ AUTOBOUND DEVCOND DEVNAME MARKMASK FWMARK CGROUPCOND CGROUPPATH
%left '|'
%left '&'
%nonassoc '!'
%%
-applet: null expr
+applet: exprlist
{
- *yy_ret = $2;
- $$ = $2;
+ *yy_ret = $1;
+ $$ = $1;
}
| null
;
+
null: /* NOTHING */ { $$ = NULL; }
;
-expr: DCOND HOSTCOND
+
+exprlist: expr
+ | exprlist '|' expr
+ {
+ $$ = alloc_node(SSF_OR, $1);
+ $$->post = $3;
+ }
+ | exprlist '&' expr
+ {
+ $$ = alloc_node(SSF_AND, $1);
+ $$->post = $3;
+ }
+ | exprlist expr
+ {
+ $$ = alloc_node(SSF_AND, $1);
+ $$->post = $2;
+ }
+ ;
+
+eq: '='
+ | /* nothing */
+ ;
+
+expr: '(' exprlist ')'
+ {
+ $$ = $2;
+ }
+ | '!' expr
+ {
+ $$ = alloc_node(SSF_NOT, $2);
+ }
+ | DCOND eq HOSTCOND
{
- $$ = alloc_node(SSF_DCOND, $2);
+ $$ = alloc_node(SSF_DCOND, $3);
}
- | SCOND HOSTCOND
+ | SCOND eq HOSTCOND
{
- $$ = alloc_node(SSF_SCOND, $2);
+ $$ = alloc_node(SSF_SCOND, $3);
}
| DPORT GEQ HOSTCOND
{
{
$$ = alloc_node(SSF_NOT, alloc_node(SSF_D_GE, $3));
}
- | DPORT '=' HOSTCOND
+ | DPORT eq HOSTCOND
{
$$ = alloc_node(SSF_DCOND, $3);
}
{
$$ = alloc_node(SSF_NOT, alloc_node(SSF_S_GE, $3));
}
- | SPORT '=' HOSTCOND
+ | SPORT eq HOSTCOND
{
$$ = alloc_node(SSF_SCOND, $3);
}
{
$$ = alloc_node(SSF_NOT, alloc_node(SSF_SCOND, $3));
}
- | DEVNAME '=' DEVCOND
+ | DEVNAME eq DEVCOND
{
$$ = alloc_node(SSF_DEVCOND, $3);
}
{
$$ = alloc_node(SSF_NOT, alloc_node(SSF_DEVCOND, $3));
}
- | FWMARK '=' MARKMASK
+ | FWMARK eq MARKMASK
{
$$ = alloc_node(SSF_MARKMASK, $3);
}
{
$$ = alloc_node(SSF_NOT, alloc_node(SSF_MARKMASK, $3));
}
- | AUTOBOUND
- {
- $$ = alloc_node(SSF_S_AUTO, NULL);
- }
- | expr '|' expr
- {
- $$ = alloc_node(SSF_OR, $1);
- $$->post = $3;
- }
- | expr expr
- {
- $$ = alloc_node(SSF_AND, $1);
- $$->post = $2;
- }
- | expr '&' expr
-
+ | CGROUPPATH eq CGROUPCOND
{
- $$ = alloc_node(SSF_AND, $1);
- $$->post = $3;
+ $$ = alloc_node(SSF_CGROUPCOND, $3);
}
- | '!' expr
+ | CGROUPPATH NEQ CGROUPCOND
{
- $$ = alloc_node(SSF_NOT, $2);
+ $$ = alloc_node(SSF_NOT, alloc_node(SSF_CGROUPCOND, $3));
}
- | '(' expr ')'
+ | AUTOBOUND
{
- $$ = $2;
+ $$ = alloc_node(SSF_S_AUTO, NULL);
}
;
%%
tok_type = FWMARK;
return FWMARK;
}
+ if (strcmp(curtok, "cgroup") == 0) {
+ tok_type = CGROUPPATH;
+ return CGROUPPATH;
+ }
if (strcmp(curtok, ">=") == 0 ||
strcmp(curtok, "ge") == 0 ||
strcmp(curtok, "geq") == 0)
}
return MARKMASK;
}
+ if (tok_type == CGROUPPATH) {
+ yylval = (void*)parse_cgroupcond(curtok);
+ if (yylval == NULL) {
+ fprintf(stderr, "Cannot parse cgroup %s.\n", curtok);
+ exit(1);
+ }
+ return CGROUPCOND;
+ }
yylval = (void*)parse_hostcond(curtok, tok_type == SPORT || tok_type == DPORT);
if (yylval == NULL) {
fprintf(stderr, "Cannot parse dst/src address.\n");