]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - misc/ssfilter.y
Merge branch 'main' into next
[mirror_iproute2.git] / misc / ssfilter.y
index f47ab2fdcacd01cfd84d146887c41498832fb842..8e16b44638f6078e237fb3796d864708046b7072 100644 (file)
@@ -1,6 +1,7 @@
 %{
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <malloc.h>
 #include <string.h>
 #include "ssfilter.h"
@@ -11,7 +12,14 @@ typedef struct ssfilter * ssfilter_t;
 
 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;
@@ -24,6 +32,7 @@ static char           **yy_argv;
 static int             yy_argc;
 static FILE            *yy_fp;
 static ssfilter_t      *yy_ret;
+static int tok_type = -1;
 
 static int yylex(void);
 
@@ -34,28 +43,60 @@ static void yyerror(char *s)
 
 %}
 
-%token HOSTCOND DCOND SCOND DPORT SPORT LEQ GEQ NEQ AUTOBOUND
+%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
-        { 
-               $$ = alloc_node(SSF_SCOND, $2);
+        | SCOND eq HOSTCOND
+        {
+               $$ = alloc_node(SSF_SCOND, $3);
         }
         | DPORT GEQ HOSTCOND
         {
@@ -73,7 +114,7 @@ expr:        DCOND HOSTCOND
         {
                 $$ = alloc_node(SSF_NOT, alloc_node(SSF_D_GE, $3));
         }
-        | DPORT '=' HOSTCOND
+        | DPORT eq HOSTCOND
         {
                $$ = alloc_node(SSF_DCOND, $3);
         }
@@ -98,7 +139,7 @@ expr:        DCOND HOSTCOND
         {
                 $$ = alloc_node(SSF_NOT, alloc_node(SSF_S_GE, $3));
         }
-        | SPORT '=' HOSTCOND
+        | SPORT eq HOSTCOND
         {
                $$ = alloc_node(SSF_SCOND, $3);
         }
@@ -106,34 +147,33 @@ expr:     DCOND HOSTCOND
         {
                $$ = alloc_node(SSF_NOT, alloc_node(SSF_SCOND, $3));
         }
-
-        | AUTOBOUND
+        | DEVNAME eq DEVCOND
         {
-                $$ = alloc_node(SSF_S_AUTO, NULL);
+               $$ = alloc_node(SSF_DEVCOND, $3);
         }
-        | expr '|' expr
+        | DEVNAME NEQ DEVCOND
         {
-                $$ = alloc_node(SSF_OR, $1);
-               $$->post = $3;
+               $$ = alloc_node(SSF_NOT, alloc_node(SSF_DEVCOND, $3));
         }
-        | expr expr
+        | FWMARK eq MARKMASK
         {
-                $$ = alloc_node(SSF_AND, $1);
-               $$->post = $2;
+                $$ = alloc_node(SSF_MARKMASK, $3);
         }
-        | expr '&' expr
-
+        | FWMARK NEQ MARKMASK
         {
-                $$ = alloc_node(SSF_AND, $1);
-               $$->post = $3;
+                $$ = alloc_node(SSF_NOT, alloc_node(SSF_MARKMASK, $3));
         }
-        | '!' expr
+        | CGROUPPATH eq CGROUPCOND
         {
-                $$ = alloc_node(SSF_NOT, $2);
+                $$ = alloc_node(SSF_CGROUPCOND, $3);
         }
-        | '(' expr ')'
+        | CGROUPPATH NEQ CGROUPCOND
         {
-                $$ = $2;
+                $$ = alloc_node(SSF_NOT, alloc_node(SSF_CGROUPCOND, $3));
+        }
+        | AUTOBOUND
+        {
+                $$ = alloc_node(SSF_S_AUTO, NULL);
         }
 ;
 %%
@@ -185,15 +225,23 @@ int yylex(void)
                                argc++;
                        } else if (yy_fp) {
                                while (tokptr == NULL) {
-                                       if (fgets(argbuf, sizeof(argbuf)-1, yy_fp) == NULL)
+                                       size_t len;
+
+                                       if (fgets(argbuf, sizeof(argbuf), yy_fp) == NULL)
                                                return 0;
-                                       argbuf[sizeof(argbuf)-1] = 0;
-                                       if (strlen(argbuf) == sizeof(argbuf) - 1) {
-                                               fprintf(stderr, "Too long line in filter");
+
+                                       len = strnlen(argbuf, sizeof(argbuf));
+                                       if (len == 0) {
+                                               fprintf(stderr, "Invalid line\n");
+                                               exit(-1);
+                                       }
+
+                                       if (len >= sizeof(argbuf) - 1) {
+                                               fprintf(stderr, "Too long line in filter\n");
                                                exit(-1);
                                        }
-                                       if (argbuf[strlen(argbuf)-1] == '\n')
-                                               argbuf[strlen(argbuf)-1] = 0;
+                                       if (argbuf[len - 1] == '\n')
+                                               argbuf[len-1] = 0;
                                        if (argbuf[0] == '#' || argbuf[0] == '0')
                                                continue;
                                        tokptr = argbuf;
@@ -219,14 +267,34 @@ int yylex(void)
                return '(';
        if (strcmp(curtok, ")") == 0)
                return ')';
-       if (strcmp(curtok, "dst") == 0)
+       if (strcmp(curtok, "dst") == 0) {
+               tok_type = DCOND;
                return DCOND;
-       if (strcmp(curtok, "src") == 0)
+       }
+       if (strcmp(curtok, "src") == 0) {
+                tok_type = SCOND;
                return SCOND;
-       if (strcmp(curtok, "dport") == 0)
+        }
+       if (strcmp(curtok, "dport") == 0) {
+               tok_type = DPORT;
                return DPORT;
-       if (strcmp(curtok, "sport") == 0)
+       }
+       if (strcmp(curtok, "sport") == 0) {
+               tok_type = SPORT;
                return SPORT;
+       }
+       if (strcmp(curtok, "dev") == 0) {
+               tok_type = DEVNAME;
+               return DEVNAME;
+       }
+       if (strcmp(curtok, "fwmark") == 0) {
+               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)
@@ -249,9 +317,35 @@ int yylex(void)
        if (strcmp(curtok, "<") == 0 ||
            strcmp(curtok, "lt") == 0)
                return '<';
-       if (strcmp(curtok, "autobound") == 0)
+       if (strcmp(curtok, "autobound") == 0) {
+               tok_type = AUTOBOUND;
                return AUTOBOUND;
-       yylval = (void*)parse_hostcond(curtok);
+       }
+       if (tok_type == DEVNAME) {
+               yylval = (void*)parse_devcond(curtok);
+               if (yylval == NULL) {
+                       fprintf(stderr, "Cannot parse device.\n");
+                       exit(1);
+               }
+               return DEVCOND;
+       }
+       if (tok_type == FWMARK) {
+               yylval = (void*)parse_markmask(curtok);
+               if (yylval == NULL) {
+                       fprintf(stderr, "Cannot parse mark %s.\n", curtok);
+                       exit(1);
+               }
+               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");
                exit(1);