iproute2/misc/ssfilter.y
<<
>>
Prefs
   1%{
   2
   3#include <stdio.h>
   4#include <stdlib.h>
   5#include <malloc.h>
   6#include <string.h>
   7#include "ssfilter.h"
   8
   9typedef struct ssfilter * ssfilter_t;
  10
  11#define YYSTYPE ssfilter_t
  12
  13static struct ssfilter * alloc_node(int type, void *pred)
  14{
  15        struct ssfilter *n;
  16
  17        if (!ssfilter_is_supported(type)) {
  18                fprintf(stderr, "It looks like such filter is not supported! Too old kernel?\n");
  19                exit(-1);
  20        }
  21
  22        n = malloc(sizeof(*n));
  23        if (n == NULL)
  24                abort();
  25        n->type = type;
  26        n->pred = pred;
  27        n->post = NULL;
  28        return n;
  29}
  30
  31static char             **yy_argv;
  32static int              yy_argc;
  33static FILE             *yy_fp;
  34static ssfilter_t       *yy_ret;
  35static int tok_type = -1;
  36
  37static int yylex(void);
  38
  39static void yyerror(char *s)
  40{
  41        fprintf(stderr, "ss: bison bellows (while parsing filter): \"%s!\"", s);
  42}
  43
  44%}
  45
  46%token HOSTCOND DCOND SCOND DPORT SPORT LEQ GEQ NEQ AUTOBOUND DEVCOND DEVNAME MARKMASK FWMARK CGROUPCOND CGROUPPATH
  47%left '|'
  48%left '&'
  49%nonassoc '!'
  50
  51%%
  52applet: exprlist
  53        {
  54                *yy_ret = $1;
  55                $$ = $1;
  56        }
  57        | null
  58        ;
  59
  60null:   /* NOTHING */ { $$ = NULL; }
  61        ;
  62
  63exprlist: expr
  64        | exprlist '|' expr
  65        {
  66                $$ = alloc_node(SSF_OR, $1);
  67                $$->post = $3;
  68        }
  69        | exprlist '&' expr
  70        {
  71                $$ = alloc_node(SSF_AND, $1);
  72                $$->post = $3;
  73        }
  74        | exprlist expr
  75        {
  76                $$ = alloc_node(SSF_AND, $1);
  77                $$->post = $2;
  78        }
  79        ;
  80
  81eq:     '='
  82        | /* nothing */
  83        ;
  84
  85expr:   '(' exprlist ')'
  86        {
  87                $$ = $2;
  88        }
  89        | '!' expr
  90        {
  91                $$ = alloc_node(SSF_NOT, $2);
  92        }
  93        | DCOND eq HOSTCOND
  94        {
  95                $$ = alloc_node(SSF_DCOND, $3);
  96        }
  97        | SCOND eq HOSTCOND
  98        {
  99                $$ = alloc_node(SSF_SCOND, $3);
 100        }
 101        | DPORT GEQ HOSTCOND
 102        {
 103                $$ = alloc_node(SSF_D_GE, $3);
 104        }
 105        | DPORT LEQ HOSTCOND
 106        {
 107                $$ = alloc_node(SSF_D_LE, $3);
 108        }
 109        | DPORT '>' HOSTCOND
 110        {
 111                $$ = alloc_node(SSF_NOT, alloc_node(SSF_D_LE, $3));
 112        }
 113        | DPORT '<' HOSTCOND
 114        {
 115                $$ = alloc_node(SSF_NOT, alloc_node(SSF_D_GE, $3));
 116        }
 117        | DPORT eq HOSTCOND
 118        {
 119                $$ = alloc_node(SSF_DCOND, $3);
 120        }
 121        | DPORT NEQ HOSTCOND
 122        {
 123                $$ = alloc_node(SSF_NOT, alloc_node(SSF_DCOND, $3));
 124        }
 125
 126        | SPORT GEQ HOSTCOND
 127        {
 128                $$ = alloc_node(SSF_S_GE, $3);
 129        }
 130        | SPORT LEQ HOSTCOND
 131        {
 132                $$ = alloc_node(SSF_S_LE, $3);
 133        }
 134        | SPORT '>' HOSTCOND
 135        {
 136                $$ = alloc_node(SSF_NOT, alloc_node(SSF_S_LE, $3));
 137        }
 138        | SPORT '<' HOSTCOND
 139        {
 140                $$ = alloc_node(SSF_NOT, alloc_node(SSF_S_GE, $3));
 141        }
 142        | SPORT eq HOSTCOND
 143        {
 144                $$ = alloc_node(SSF_SCOND, $3);
 145        }
 146        | SPORT NEQ HOSTCOND
 147        {
 148                $$ = alloc_node(SSF_NOT, alloc_node(SSF_SCOND, $3));
 149        }
 150        | DEVNAME eq DEVCOND
 151        {
 152                $$ = alloc_node(SSF_DEVCOND, $3);
 153        }
 154        | DEVNAME NEQ DEVCOND
 155        {
 156                $$ = alloc_node(SSF_NOT, alloc_node(SSF_DEVCOND, $3));
 157        }
 158        | FWMARK eq MARKMASK
 159        {
 160                $$ = alloc_node(SSF_MARKMASK, $3);
 161        }
 162        | FWMARK NEQ MARKMASK
 163        {
 164                $$ = alloc_node(SSF_NOT, alloc_node(SSF_MARKMASK, $3));
 165        }
 166        | CGROUPPATH eq CGROUPCOND
 167        {
 168                $$ = alloc_node(SSF_CGROUPCOND, $3);
 169        }
 170        | CGROUPPATH NEQ CGROUPCOND
 171        {
 172                $$ = alloc_node(SSF_NOT, alloc_node(SSF_CGROUPCOND, $3));
 173        }
 174        | AUTOBOUND
 175        {
 176                $$ = alloc_node(SSF_S_AUTO, NULL);
 177        }
 178;
 179%%
 180
 181static char *get_token_from_line(char **ptr)
 182{
 183        char *tok, *cp = *ptr;
 184
 185        while (*cp == ' ' || *cp == '\t') cp++;
 186
 187        if (*cp == 0) {
 188                *ptr = cp;
 189                return NULL;
 190        }
 191
 192        tok = cp;
 193
 194        while (*cp != 0 && *cp != ' ' && *cp != '\t') {
 195                /* Backslash escapes everything. */
 196                if (*cp == '\\') {
 197                        char *tp;
 198                        for (tp = cp; tp != tok; tp--)
 199                                *tp = *(tp-1);
 200                        cp++;
 201                        tok++;
 202                        if (*cp == 0)
 203                                break;
 204                }
 205                cp++;
 206        }
 207        if (*cp)
 208                *cp++ = 0;
 209        *ptr = cp;
 210        return tok;
 211}
 212
 213int yylex(void)
 214{
 215        static char argbuf[1024];
 216        static char *tokptr = argbuf;
 217        static int argc;
 218        char *curtok;
 219
 220        do {
 221                while (*tokptr == 0) {
 222                        tokptr = NULL;
 223                        if (argc < yy_argc) {
 224                                tokptr = yy_argv[argc];
 225                                argc++;
 226                        } else if (yy_fp) {
 227                                while (tokptr == NULL) {
 228                                        size_t len;
 229
 230                                        if (fgets(argbuf, sizeof(argbuf), yy_fp) == NULL)
 231                                                return 0;
 232
 233                                        len = strnlen(argbuf, sizeof(argbuf));
 234                                        if (len == 0) {
 235                                                fprintf(stderr, "Invalid line\n");
 236                                                exit(-1);
 237                                        }
 238
 239                                        if (len >= sizeof(argbuf) - 1) {
 240                                                fprintf(stderr, "Too long line in filter\n");
 241                                                exit(-1);
 242                                        }
 243                                        if (argbuf[len - 1] == '\n')
 244                                                argbuf[len-1] = 0;
 245                                        if (argbuf[0] == '#' || argbuf[0] == '0')
 246                                                continue;
 247                                        tokptr = argbuf;
 248                                }
 249                        } else {
 250                                return 0;
 251                        }
 252                }
 253        } while ((curtok = get_token_from_line(&tokptr)) == NULL);
 254
 255        if (strcmp(curtok, "!") == 0 ||
 256            strcmp(curtok, "not") == 0)
 257                return '!';
 258        if (strcmp(curtok, "&") == 0 ||
 259            strcmp(curtok, "&&") == 0 ||
 260            strcmp(curtok, "and") == 0)
 261                return '&';
 262        if (strcmp(curtok, "|") == 0 ||
 263            strcmp(curtok, "||") == 0 ||
 264            strcmp(curtok, "or") == 0)
 265                return '|';
 266        if (strcmp(curtok, "(") == 0)
 267                return '(';
 268        if (strcmp(curtok, ")") == 0)
 269                return ')';
 270        if (strcmp(curtok, "dst") == 0) {
 271                tok_type = DCOND;
 272                return DCOND;
 273        }
 274        if (strcmp(curtok, "src") == 0) {
 275                tok_type = SCOND;
 276                return SCOND;
 277        }
 278        if (strcmp(curtok, "dport") == 0) {
 279                tok_type = DPORT;
 280                return DPORT;
 281        }
 282        if (strcmp(curtok, "sport") == 0) {
 283                tok_type = SPORT;
 284                return SPORT;
 285        }
 286        if (strcmp(curtok, "dev") == 0) {
 287                tok_type = DEVNAME;
 288                return DEVNAME;
 289        }
 290        if (strcmp(curtok, "fwmark") == 0) {
 291                tok_type = FWMARK;
 292                return FWMARK;
 293        }
 294        if (strcmp(curtok, "cgroup") == 0) {
 295                tok_type = CGROUPPATH;
 296                return CGROUPPATH;
 297        }
 298        if (strcmp(curtok, ">=") == 0 ||
 299            strcmp(curtok, "ge") == 0 ||
 300            strcmp(curtok, "geq") == 0)
 301                return GEQ;
 302        if (strcmp(curtok, "<=") == 0 ||
 303            strcmp(curtok, "le") == 0 ||
 304            strcmp(curtok, "leq") == 0)
 305                return LEQ;
 306        if (strcmp(curtok, "!=") == 0 ||
 307            strcmp(curtok, "ne") == 0 ||
 308            strcmp(curtok, "neq") == 0)
 309                return NEQ;
 310        if (strcmp(curtok, "=") == 0 ||
 311            strcmp(curtok, "==") == 0 ||
 312            strcmp(curtok, "eq") == 0)
 313                return '=';
 314        if (strcmp(curtok, ">") == 0 ||
 315            strcmp(curtok, "gt") == 0)
 316                return '>';
 317        if (strcmp(curtok, "<") == 0 ||
 318            strcmp(curtok, "lt") == 0)
 319                return '<';
 320        if (strcmp(curtok, "autobound") == 0) {
 321                tok_type = AUTOBOUND;
 322                return AUTOBOUND;
 323        }
 324        if (tok_type == DEVNAME) {
 325                yylval = (void*)parse_devcond(curtok);
 326                if (yylval == NULL) {
 327                        fprintf(stderr, "Cannot parse device.\n");
 328                        exit(1);
 329                }
 330                return DEVCOND;
 331        }
 332        if (tok_type == FWMARK) {
 333                yylval = (void*)parse_markmask(curtok);
 334                if (yylval == NULL) {
 335                        fprintf(stderr, "Cannot parse mark %s.\n", curtok);
 336                        exit(1);
 337                }
 338                return MARKMASK;
 339        }
 340        if (tok_type == CGROUPPATH) {
 341                yylval = (void*)parse_cgroupcond(curtok);
 342                if (yylval == NULL) {
 343                        fprintf(stderr, "Cannot parse cgroup %s.\n", curtok);
 344                        exit(1);
 345                }
 346                return CGROUPCOND;
 347        }
 348        yylval = (void*)parse_hostcond(curtok, tok_type == SPORT || tok_type == DPORT);
 349        if (yylval == NULL) {
 350                fprintf(stderr, "Cannot parse dst/src address.\n");
 351                exit(1);
 352        }
 353        return HOSTCOND;
 354}
 355
 356int ssfilter_parse(struct ssfilter **f, int argc, char **argv, FILE *fp)
 357{
 358        yy_argc = argc;
 359        yy_argv = argv;
 360        yy_fp   = fp;
 361        yy_ret  = f;
 362
 363        if (yyparse()) {
 364                fprintf(stderr, " Sorry.\n");
 365                return -1;
 366        }
 367        return 0;
 368}
 369