diff options
Diffstat (limited to 'filter')
-rw-r--r-- | filter/config.Y | 83 | ||||
-rw-r--r-- | filter/filter.c | 28 | ||||
-rw-r--r-- | filter/filter.h | 18 |
3 files changed, 93 insertions, 36 deletions
diff --git a/filter/config.Y b/filter/config.Y index 9d0cc747..93854836 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -5,16 +5,13 @@ * * Can be freely distributed and used under the terms of the GNU GPL. * - FIXME: prefix variables, make prefix.ip and prefix.length work FIXME: define keyword - FIXME: case without { }'s - FIXME: allow px+, px- px^pair in prefix sets + FIXME: make px+, px- px^pair work in prefix sets FIXME: create ip.mask(x) function FIXME: whole system of paths, path ~ string, path.prepend(), path.originate FIXME: create community lists FIXME: access to dynamic attributes - FIXME: do not allow function call by callme(1,2,) - FIXME: pairs of integers: define compare + FIXME: make case faster */ CF_HDR @@ -29,12 +26,12 @@ CF_HDR CF_DECLS -CF_KEYWORDS(FUNCTION, PRINT, CONST, +CF_KEYWORDS(FUNCTION, PRINT, PRINTN, CONST, ACCEPT, REJECT, ERROR, QUITBIRD, INT, BOOL, IP, PREFIX, PAIR, SET, STRING, IF, THEN, ELSE, CASE, TRUE, FALSE, - RTA, FROM, GW, NET, + RTA, FROM, GW, NET, MASK, LEN, IMPOSSIBLE, FILTER @@ -42,9 +39,9 @@ CF_KEYWORDS(FUNCTION, PRINT, CONST, %type <x> term block cmds cmd function_body ifthen constant print_one print_list var_list switch_body %type <f> filter filter_body -%type <i> type break_command +%type <i> type break_command pair %type <e> set_item set_items -%type <v> set_atom +%type <v> set_atom prefix prefix_s ipa %type <s> decls function_params CF_GRAMMAR @@ -80,6 +77,12 @@ decls: /* EMPTY */ { $$ = NULL; } cf_define_symbol($2, SYM_VARIABLE | $1, NULL); printf( "New variable %s type %x\n", $2->name, $1 ); $2->aux = $4; + { + struct f_val * val; + val = cfg_alloc(sizeof(struct f_val)); + val->type = $1; + $2->aux2 = val; + } $$=$2; } ; @@ -146,10 +149,36 @@ block: } ; +/* + * Simple types, their bison value is int + */ +pair: + '(' NUM ',' NUM ')' { $$ = $2 << 16 | $4; } + ; + +/* + * Complex types, their bison value is struct f_val + */ +prefix_s: + IPA '/' NUM { $$.type = T_PREFIX; $$.val.px.ip = $1; $$.val.px.len = $3; printf( "ook, we have prefix here\n" ); } + ; + +prefix: + prefix_s { $$ = $1; } + | prefix_s '+' { $$ = $1; $$.val.px.len |= LEN_PLUS; } + | prefix_s '-' { $$ = $1; $$.val.px.len |= LEN_MINUS; } +/* | prefix_s '{' NUM ',' NUM '}' How should this be done? */ + ; + +ipa: + IPA { $$.type = T_IP; $$.val.ip = $1; } + ; + set_atom: - NUM { $$.type = T_INT; $$.val.i = $1; } - | IPA { $$.type = T_IP; $$.val.ip = $1; } - + NUM { $$.type = T_INT; $$.val.i = $1; } + | pair { $$.type = T_PAIR; $$.val.i = $1; } + | ipa { $$ = $1; } + | prefix { $$ = $1; } ; set_item: @@ -162,15 +191,16 @@ set_items: | set_items ',' set_item { $$ = $3; $$->left = $1; } ; + constant: CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_INT; $$->a2.i = $3; } | NUM { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_INT; $$->a2.i = $1; } | TRUE { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_BOOL; $$->a2.i = 1; } | FALSE { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_BOOL; $$->a2.i = 0; } | TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_STRING; $$->a2.p = $1; } - | '(' NUM ',' NUM ')' { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_PAIR; $$->a2.i = $2 << 16 | $4; } - | IPA { struct f_val * val; val = cfg_alloc(sizeof(struct f_val)); $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; val->type = T_IP; val->val.ip = $1; } - | IPA '/' NUM { struct f_val * val; val = cfg_alloc(sizeof(struct f_val)); $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; val->type = T_PREFIX; val->val.px.ip = $1; val->val.px.len = $3; printf( "ook, we have prefix here\n" ); } + | pair { $$ = f_new_inst(); $$->code = 'c'; $$->a1.i = T_PAIR; $$->a2.i = $1; } + | ipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; } + | prefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; } | '[' 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" ); } ; @@ -188,9 +218,11 @@ term: $$ = f_new_inst(); switch ($1->class) { case SYM_VARIABLE | T_INT: - $$->code = 'i'; - $$->a1.i = T_INT; - $$->a2.p = &($1->aux); + case SYM_VARIABLE | T_PAIR: + case SYM_VARIABLE | T_PREFIX: + case SYM_VARIABLE | T_IP: + $$->code = 'C'; + $$->a1.p = $1->aux2; break; default: cf_error("Can not use this class of symbol as variable." ); @@ -204,6 +236,7 @@ term: | 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; } + | term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = 'iM'; $$->a1.p = $1; $$->a2.p = $5; } ; break_command: @@ -212,6 +245,7 @@ break_command: | REJECT { $$ = F_REJECT } | ERROR { $$ = F_ERROR } | PRINT { $$ = F_NOP } + | PRINTN { $$ = F_NONL } ; ifthen: @@ -236,7 +270,13 @@ print_list: /* EMPTY */ { $$ = NULL; } } ; -var_list: /* EMPTY */ { $$ = NULL; } +var_list: term { + $$ = f_new_inst(); + $$->code = 's'; + $$->a1.p = NULL; + $$->a2.p = $1; + $$->next = NULL; + } | term ',' var_list { $$ = f_new_inst(); $$->code = 's'; @@ -246,15 +286,16 @@ var_list: /* EMPTY */ { $$ = NULL; } } ; +/* 2 shift/reduce conflicts here. Curable by replacing cmds with block which breaks syntax */ switch_body: /* EMPTY */ { $$ = NULL; } - | term ':' block switch_body { + | term ':' cmds switch_body { $$ = f_new_inst(); $$->code = 'of'; $$->a1.p = $1; $$->a2.p = $3; $$->next = $4; } - | ELSE ':' block { + | ELSE ':' cmds { $$ = f_new_inst(); $$->code = 'el'; $$->a1.p = NULL; diff --git a/filter/filter.c b/filter/filter.c index d317fcc0..f6b2d4be 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -58,6 +58,7 @@ val_compare(struct f_val v1, struct f_val v2) return CMP_ERROR; switch (v1.type) { case T_INT: + case T_PAIR: if (v1.val.i == v2.val.i) return 0; if (v1.val.i < v2.val.i) return -1; return 1; @@ -209,31 +210,32 @@ interpret(struct f_inst *what) runtime( "~ applied on unknown type pair" ); break; - /* Set to consant, a1 = type, a2 = value */ + /* Set to indirect value, a1 = variable, a2 = value */ case 's': ARG(v2, a2.p); sym = what->a1.p; switch (res.type = v2.type) { case T_VOID: runtime( "Can not assign void values" ); case T_INT: - if (sym->class != (SYM_VARIABLE | T_INT)) + case T_IP: + case T_PREFIX: + case T_PAIR: + if (sym->class != (SYM_VARIABLE | v2.type)) runtime( "Variable of bad type" ); - sym->aux = v2.val.i; + * (struct f_val *) sym->aux2 = v2; break; + default: + bug( "Set to invalid type\n" ); } break; - case 'c': + case 'c': /* integer (or simple type) constant */ res.type = what->a1.i; - res.val.i = (int) what->a2.p; + res.val.i = what->a2.i; break; case 'C': res = * ((struct f_val *) what->a1.p); break; - case 'i': - res.type = what->a1.i; - res.val.i = * ((int *) what->a2.p); - break; case 'p': ONEARG; val_print(v1); @@ -253,7 +255,8 @@ interpret(struct f_inst *what) break; case 'p,': ONEARG; - printf( "\n" ); + if (what->a2.i != F_NONL) + printf( "\n" ); switch (what->a2.i) { case F_QUITBIRD: @@ -265,6 +268,7 @@ interpret(struct f_inst *what) res.type = T_RETURN; res.val.i = what->a1.i; break; + case F_NONL: case F_NOP: break; default: @@ -309,6 +313,10 @@ interpret(struct f_inst *what) ONEARG; interpret_switch(what->a2.p, v1); break; + case 'iM': /* IP.MASK(val) */ + TWOARGS_C; + bug( "Should implement ip.mask\n" ); + break; default: bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff); } diff --git a/filter/filter.h b/filter/filter.h index f32a98eb..ac7162ec 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -31,6 +31,11 @@ struct f_inst { /* Instruction */ struct prefix { ip_addr ip; int len; +#define LEN_MASK 0xff +#define LEN_PLUS 0x10000 +#define LEN_MINUS 0x20000 +#define LEN_RANGE 0x40000 + /* If range then prefix must be in range (len >> 8 & 0xff, len & 0xff) */ }; struct f_val { @@ -66,11 +71,12 @@ int val_compare(struct f_val v1, struct f_val v2); void val_print(struct f_val v); #define F_NOP 0 -#define F_ACCEPT 1 /* Need to preserve ordering: accepts < rejects! */ -#define F_MODIFY 2 /* FIXME: Introduce modification flags instead? */ -#define F_REJECT 3 -#define F_ERROR 4 -#define F_QUITBIRD 5 +#define F_NONL 1 +#define F_ACCEPT 2 /* Need to preserve ordering: accepts < rejects! */ +#define F_MODIFY 3 /* FIXME: Introduce modification flags instead? */ +#define F_REJECT 4 +#define F_ERROR 5 +#define F_QUITBIRD 6 #define FILTER_ACCEPT NULL #define FILTER_REJECT ((void *) 1) @@ -101,4 +107,6 @@ struct f_tree { void *data; }; +#define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val)); + #endif |