diff options
Diffstat (limited to 'filter')
-rw-r--r-- | filter/config.Y | 23 | ||||
-rw-r--r-- | filter/filter.c | 19 | ||||
-rw-r--r-- | filter/filter.h | 7 |
3 files changed, 40 insertions, 9 deletions
diff --git a/filter/config.Y b/filter/config.Y index 1e4bafe..a12766e 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -5,12 +5,11 @@ * * Can be freely distributed and used under the terms of the GNU GPL. * - FIXME: define keyword - FIXME: create ip.mask(x) function + FIXME (nonurgent): define keyword FIXME: whole system of paths, path ~ string, path.prepend(), path.originate FIXME: create community lists FIXME: enumerational types - FIXME: defined() keyword + FIXME: write access to dynamic attributes. */ CF_HDR @@ -32,11 +31,15 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, CONST, TRUE, FALSE, RTA, FROM, GW, NET, MASK, RIP_METRIC, RIP_TAG, LEN, + DEFINED, IMPOSSIBLE, FILTER ) -%type <x> term block cmds cmd function_body ifthen constant print_one print_list var_list var_listn +%nonassoc THEN +%nonassoc ELSE ';' + +%type <x> term block cmds cmd function_body ifthen constant print_one print_list var_list var_listn any_dynamic %type <f> filter filter_body %type <i> type break_command pair %type <e> set_item set_items switch_body @@ -237,8 +240,15 @@ constant: | '[' set_items ']' { printf( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_SET; $$->a2.p = build_tree($2); printf( "ook\n" ); } ; +any_dynamic: + RIP_METRIC { $$ = f_new_inst(); $$->a1.i = T_INT; $$->a2.i = EA_RIP_METRIC;} + | RIP_TAG { $$ = f_new_inst(); $$->a1.i = T_INT; $$->a2.i = EA_RIP_TAG; } + ; + + term: - term '+' term { $$ = f_new_inst(); $$->code = '+'; $$->a1.p = $1; $$->a2.p = $3; } + '(' term ')' { $$ = $2; } + | term '+' term { $$ = f_new_inst(); $$->code = '+'; $$->a1.p = $1; $$->a2.p = $3; } | term '=' term { $$ = f_new_inst(); $$->code = '=='; $$->a1.p = $1; $$->a2.p = $3; } | term '!' '=' term { $$ = f_new_inst(); $$->code = '!='; $$->a1.p = $1; $$->a2.p = $4; } | term '<' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $1; $$->a2.p = $3; } @@ -246,6 +256,7 @@ term: | term '>' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $3; $$->a2.p = $1; } | term '>' '=' term { $$ = f_new_inst(); $$->code = '<='; $$->a1.p = $4; $$->a2.p = $1; } | term '~' term { $$ = f_new_inst(); $$->code = '~'; $$->a1.p = $1; $$->a2.p = $3; } + | DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = 'de'; $$->a1.p = $3; } | SYM { $$ = f_new_inst(); @@ -267,7 +278,7 @@ term: | RTA '.' GW { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_IP; $$->a2.i = OFFSETOF(struct rta, gw); } | RTA '.' NET { $$ = f_new_inst(); $$->code = 'a'; $$->a1.i = T_PREFIX; $$->a2.i = 0x12345678; } - | RTA '.' RIP_METRIC { $$ = f_new_inst(); $$->code = 'ea'; $$->a1.i = T_INT; $$->a2.i = EA_RIP_METRIC; } + | RTA '.' any_dynamic { $$ = $3; $$->code = 'ea'; } | term '.' IP { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->a2.i = T_IP; } | term '.' LEN { $$ = f_new_inst(); $$->code = 'cp'; $$->a1.p = $1; $$->a2.i = T_INT; } diff --git a/filter/filter.c b/filter/filter.c index 99d47bc..a6030ae 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -62,6 +62,7 @@ val_compare(struct f_val v1, struct f_val v2) if (v1.type != v2.type) return CMP_ERROR; switch (v1.type) { + case T_ENUM: case T_INT: case T_PAIR: if (v1.val.i == v2.val.i) return 0; @@ -219,6 +220,11 @@ interpret(struct f_inst *what) if (res.val.i == CMP_ERROR) runtime( "~ applied on unknown type pair" ); break; + case 'de': + ONEARG; + res.type = T_BOOL; + res.val.i = (v1.type != T_VOID); + break; /* Set to indirect value, a1 = variable, a2 = value */ case 's': @@ -226,6 +232,7 @@ interpret(struct f_inst *what) sym = what->a1.p; switch (res.type = v2.type) { case T_VOID: runtime( "Can not assign void values" ); + case T_ENUM: case T_INT: case T_IP: case T_PREFIX: @@ -352,8 +359,16 @@ interpret(struct f_inst *what) } break; case 'iM': /* IP.MASK(val) */ - TWOARGS_C; - bug( "Should implement ip.mask\n" ); + TWOARGS; + if (v2.type != T_INT) + runtime( "Can not use this type for mask."); + if (v1.type != T_IP) + runtime( "You can mask only IP addresses." ); + { + ip_addr mask = ipa_mkmask(v2.val.i); + res.type = T_IP; + res.val.px.ip = ipa_and(mask, v1.val.px.ip); + } break; default: bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff); diff --git a/filter/filter.h b/filter/filter.h index 4cdf8f6..ebb0925 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -92,7 +92,12 @@ void val_print(struct f_val v); #define T_INT 0x10 #define T_BOOL 0x11 #define T_PAIR 0x12 -#define T_ENUM 0x13 + +/* Put enumerational types in 0x30..0x7f range */ +#define T_ENUM_LO 0x30 +#define T_ENUM_HI 0x7f + +#define T_ENUM T_ENUM_LO ... T_ENUM_HI /* Bigger ones */ #define T_IP 0x20 |