]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - misc/ssfilter.y
Merge branch 'iproute2-master' into iproute2-next
[mirror_iproute2.git] / misc / ssfilter.y
index 2e9d9626a30ae70fde510749d03c19fee3cfcedf..0413dddaa7584c5add220e899cbd544869dd3aa8 100644 (file)
@@ -25,6 +25,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);
 
@@ -35,28 +36,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
 %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
+        | '!' expr
         {
-               $$ = alloc_node(SSF_DCOND, $2);
+                $$ = alloc_node(SSF_NOT, $2);
         }
-        | SCOND HOSTCOND
+        | exprlist '|' expr
         {
-               $$ = alloc_node(SSF_SCOND, $2);
+                $$ = 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;
+       }
+       | DCOND eq HOSTCOND
+        {
+               $$ = alloc_node(SSF_DCOND, $3);
+        }
+        | SCOND eq HOSTCOND
+        {
+               $$ = alloc_node(SSF_SCOND, $3);
         }
         | DPORT GEQ HOSTCOND
         {
@@ -74,7 +107,7 @@ expr:        DCOND HOSTCOND
         {
                 $$ = alloc_node(SSF_NOT, alloc_node(SSF_D_GE, $3));
         }
-        | DPORT '=' HOSTCOND
+        | DPORT eq HOSTCOND
         {
                $$ = alloc_node(SSF_DCOND, $3);
         }
@@ -99,7 +132,7 @@ expr:        DCOND HOSTCOND
         {
                 $$ = alloc_node(SSF_NOT, alloc_node(SSF_S_GE, $3));
         }
-        | SPORT '=' HOSTCOND
+        | SPORT eq HOSTCOND
         {
                $$ = alloc_node(SSF_SCOND, $3);
         }
@@ -107,34 +140,25 @@ expr:     DCOND HOSTCOND
         {
                $$ = alloc_node(SSF_NOT, alloc_node(SSF_SCOND, $3));
         }
-
-        | AUTOBOUND
-        {
-                $$ = alloc_node(SSF_S_AUTO, NULL);
-        }
-        | expr '|' expr
+        | DEVNAME eq DEVCOND
         {
-                $$ = alloc_node(SSF_OR, $1);
-               $$->post = $3;
+               $$ = alloc_node(SSF_DEVCOND, $3);
         }
-        | expr expr
+        | DEVNAME NEQ DEVCOND
         {
-                $$ = alloc_node(SSF_AND, $1);
-               $$->post = $2;
+               $$ = alloc_node(SSF_NOT, alloc_node(SSF_DEVCOND, $3));
         }
-        | expr '&' expr
-
+        | FWMARK eq MARKMASK
         {
-                $$ = alloc_node(SSF_AND, $1);
-               $$->post = $3;
+                $$ = alloc_node(SSF_MARKMASK, $3);
         }
-        | '!' expr
+        | FWMARK NEQ MARKMASK
         {
-                $$ = alloc_node(SSF_NOT, $2);
+                $$ = alloc_node(SSF_NOT, alloc_node(SSF_MARKMASK, $3));
         }
-        | '(' expr ')'
+        | AUTOBOUND
         {
-                $$ = $2;
+                $$ = alloc_node(SSF_S_AUTO, NULL);
         }
 ;
 %%
@@ -186,15 +210,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 (argbuf[strlen(argbuf)-1] == '\n')
-                                               argbuf[strlen(argbuf)-1] = 0;
+
+                                       if (len >= sizeof(argbuf) - 1) {
+                                               fprintf(stderr, "Too long line in filter\n");
+                                               exit(-1);
+                                       }
+                                       if (argbuf[len - 1] == '\n')
+                                               argbuf[len-1] = 0;
                                        if (argbuf[0] == '#' || argbuf[0] == '0')
                                                continue;
                                        tokptr = argbuf;
@@ -220,14 +252,30 @@ 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, ">=") == 0 ||
            strcmp(curtok, "ge") == 0 ||
            strcmp(curtok, "geq") == 0)
@@ -250,9 +298,27 @@ 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;
+       }
+       yylval = (void*)parse_hostcond(curtok, tok_type == SPORT || tok_type == DPORT);
        if (yylval == NULL) {
                fprintf(stderr, "Cannot parse dst/src address.\n");
                exit(1);