]> git.proxmox.com Git - mirror_iproute2.git/blobdiff - misc/ssfilter.y
rtacct: drop unused header
[mirror_iproute2.git] / misc / ssfilter.y
index a258d04b85d75eb20e83f4d49fe52c3dc6221c6e..8e16b44638f6078e237fb3796d864708046b7072 100644 (file)
@@ -12,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;
@@ -36,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_DCOND, $2);
+                $$ = alloc_node(SSF_AND, $1);
+                $$->post = $3;
         }
-        | SCOND HOSTCOND
+        | exprlist expr
         {
-               $$ = alloc_node(SSF_SCOND, $2);
+                $$ = 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, $3);
+        }
+        | SCOND eq HOSTCOND
+        {
+               $$ = alloc_node(SSF_SCOND, $3);
         }
         | DPORT GEQ HOSTCOND
         {
@@ -75,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);
         }
@@ -100,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);
         }
@@ -108,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));
+        }
+        | CGROUPPATH eq CGROUPCOND
+        {
+                $$ = 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);
         }
 ;
 %%
@@ -187,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 (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;
@@ -237,6 +283,18 @@ int yylex(void)
                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)
@@ -263,6 +321,30 @@ int yylex(void)
                tok_type = AUTOBOUND;
                return AUTOBOUND;
        }
+       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");