diff options
author | Jan Maria Matejka <mq@ucw.cz> | 2018-03-13 16:51:04 +0100 |
---|---|---|
committer | Jan Maria Matejka <mq@ucw.cz> | 2018-03-13 16:51:04 +0100 |
commit | d1ba927b369c91ddb2143b686ca4c1be53e46e64 (patch) | |
tree | e8d0fadcf418ff24e58aaa3957577d0dde943d5c | |
parent | f2f5a7d9455f938fb14e31315a879c3be2c5d28a (diff) | |
parent | 7c601e6b7b7696b24ce5f5715fa14dbb91c71d6e (diff) |
Merge branch 'master' into int-new
-rw-r--r-- | conf/confbase.Y | 2 | ||||
-rw-r--r-- | filter/config.Y | 245 | ||||
-rw-r--r-- | filter/f-util.c | 44 | ||||
-rw-r--r-- | filter/filter.c | 231 | ||||
-rw-r--r-- | filter/filter.h | 90 |
5 files changed, 333 insertions, 279 deletions
diff --git a/conf/confbase.Y b/conf/confbase.Y index 55615528..72f56f1e 100644 --- a/conf/confbase.Y +++ b/conf/confbase.Y @@ -49,6 +49,8 @@ CF_DECLS struct rtable_config *r; struct channel_config *cc; struct f_inst *x; + struct f_dynamic_attr fda; + struct f_static_attr fsa; struct filter *f; struct f_tree *e; struct f_trie *trie; diff --git a/filter/config.Y b/filter/config.Y index cd5a5b33..6b7bedaf 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -12,8 +12,6 @@ CF_HDR CF_DEFINES -#define P(a,b) ((a << 8) | b) - static inline u32 pair(u32 a, u32 b) { return (a << 16) | b; } static inline u32 pair_a(u32 p) { return p >> 16; } static inline u32 pair_b(u32 p) { return p & 0xFFFF; } @@ -157,12 +155,11 @@ f_new_lc_item(u32 f1, u32 t1, u32 f2, u32 t2, u32 f3, u32 t3) } static inline struct f_inst * -f_generate_empty(struct f_inst *dyn) +f_generate_empty(struct f_dynamic_attr dyn) { - struct f_inst *e = f_new_inst(); - e->code = 'E'; + struct f_inst *e = f_new_inst(FI_EMPTY); - switch (dyn->aux & EAF_TYPE_MASK) { + switch (dyn.type & EAF_TYPE_MASK) { case EAF_TYPE_AS_PATH: e->aux = T_PATH; break; @@ -179,9 +176,9 @@ f_generate_empty(struct f_inst *dyn) cf_error("Can't empty that attribute"); } - dyn->code = P('e','S'); - dyn->a1.p = e; - return dyn; + struct f_inst *s = f_new_inst_da(FI_EA_SET, dyn); + s->a1.p = e; + return s; } @@ -190,21 +187,19 @@ f_generate_dpair(struct f_inst *t1, struct f_inst *t2) { struct f_inst *rv; - if ((t1->code == 'c') && (t2->code == 'c')) { + if ((t1->fi_code == FI_CONSTANT) && (t2->fi_code == FI_CONSTANT)) { if ((t1->aux != T_INT) || (t2->aux != T_INT)) cf_error( "Can't operate with value of non-integer type in pair constructor"); check_u16(t1->a2.i); check_u16(t2->a2.i); - rv = f_new_inst(); - rv->code = 'c'; + rv = f_new_inst(FI_CONSTANT); rv->aux = T_PAIR; rv->a2.i = pair(t1->a2.i, t2->a2.i); } else { - rv = f_new_inst(); - rv->code = P('m', 'p'); + rv = f_new_inst(FI_PAIR_CONSTRUCT); rv->a1.p = t1; rv->a2.p = t2; } @@ -219,7 +214,7 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv) int c1 = 0, c2 = 0, ipv4_used = 0; u32 key = 0, val2 = 0; - if (tk->code == 'c') { + if (tk->fi_code == FI_CONSTANT) { c1 = 1; if (tk->aux == T_INT) { @@ -233,7 +228,7 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv) } /* IP->Quad implicit conversion */ - else if (tk->code == 'C') { + else if (tk->fi_code == FI_CONSTANT_INDIRECT) { c1 = 1; struct f_val *val = tk->a1.p; @@ -250,7 +245,7 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv) cf_error("Can't operate with key of non-integer/IPv4 type in EC constructor"); } - if (tv->code == 'c') { + if (tv->fi_code == FI_CONSTANT) { if (tv->aux != T_INT) cf_error("Can't operate with value of non-integer type in EC constructor"); c2 = 1; @@ -276,15 +271,13 @@ f_generate_ec(u16 kind, struct f_inst *tk, struct f_inst *tv) } NEW_F_VAL; - rv = f_new_inst(); - rv->code = 'C'; + rv = f_new_inst(FI_CONSTANT_INDIRECT); rv->a1.p = val; val->type = T_EC; val->val.ec = ec; } else { - rv = f_new_inst(); - rv->code = P('m','c'); + rv = f_new_inst(FI_EC_CONSTRUCT); rv->aux = kind; rv->a1.p = tk; rv->a2.p = tv; @@ -298,12 +291,11 @@ f_generate_lc(struct f_inst *t1, struct f_inst *t2, struct f_inst *t3) { struct f_inst *rv; - if ((t1->code == 'c') && (t2->code == 'c') && (t3->code == 'c')) { + if ((t1->fi_code == FI_CONSTANT) && (t2->fi_code == FI_CONSTANT) && (t3->fi_code == FI_CONSTANT)) { if ((t1->aux != T_INT) || (t2->aux != T_INT) || (t3->aux != T_INT)) cf_error( "LC - Can't operate with value of non-integer type in tuple constructor"); - rv = f_new_inst(); - rv->code = 'C'; + rv = f_new_inst(FI_CONSTANT_INDIRECT); NEW_F_VAL; rv->a1.p = val; @@ -314,7 +306,7 @@ f_generate_lc(struct f_inst *t1, struct f_inst *t2, struct f_inst *t3) { rv = cfg_allocz(sizeof(struct f_inst3)); rv->lineno = ifs->lino; - rv->code = P('m','l'); + rv->fi_code = FI_LC_CONSTRUCT; rv->a1.p = t1; rv->a2.p = t2; INST3(rv).p = t3; @@ -372,8 +364,7 @@ static struct f_inst * assert_done(struct f_inst *expr, const char *start, const char *end) { struct f_inst *i; - i = f_new_inst(); - i->code = P('a','s'); + i = f_new_inst(FI_ASSERT); i->a1.p = expr; if (end >= start) @@ -412,7 +403,9 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, %nonassoc THEN %nonassoc ELSE -%type <x> term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn dynamic_attr static_attr function_call symbol bgp_path_expr +%type <x> term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn function_call symbol bgp_path_expr +%type <fda> dynamic_attr +%type <fsa> static_attr %type <f> filter filter_body where_filter %type <i> type break_command ec_kind %type <i32> cnum @@ -543,16 +536,13 @@ where_filter: /* Construct 'IF term THEN ACCEPT; REJECT;' */ struct filter *f = cfg_alloc(sizeof(struct filter)); struct f_inst *i, *acc, *rej; - acc = f_new_inst(); /* ACCEPT */ - acc->code = P('p',','); + acc = f_new_inst(FI_PRINT_AND_DIE); /* ACCEPT */ acc->a1.p = NULL; acc->a2.i = F_ACCEPT; - rej = f_new_inst(); /* REJECT */ - rej->code = P('p',','); + rej = f_new_inst(FI_PRINT_AND_DIE); /* REJECT */ rej->a1.p = NULL; rej->a2.i = F_REJECT; - i = f_new_inst(); /* IF */ - i->code = '?'; + i = f_new_inst(FI_CONDITION); /* IF */ i->a1.p = $2; i->a2.p = acc; i->next = rej; @@ -571,8 +561,7 @@ function_body: decls '{' cmds '}' { if ($1) { /* Prepend instruction to clear local variables */ - $$ = f_new_inst(); - $$->code = P('c','v'); + $$ = f_new_inst(FI_CLEAR_LOCAL_VARS); $$->a1.p = $1; $$->next = $3; } else @@ -755,7 +744,7 @@ switch_body: /* EMPTY */ { $$ = NULL; } } ; -/* CONST '(' expr ')' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $3; } */ +/* CONST '(' expr ')' { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_INT; $$->a2.i = $3; } */ bgp_path_expr: symbol { $$ = $1; } @@ -776,17 +765,17 @@ bgp_path_tail: ; constant: - NUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_INT; $$->a2.i = $1; } - | TRUE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 1; } - | FALSE { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_BOOL; $$->a2.i = 0; } - | TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; } - | fipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; } - | VPN_RD { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_RD; val->val.ec = $1; $$->a1.p = val; } - | net_ { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_NET; val->val.net = $1; $$->a1.p = val; } - | '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); } - | '[' fprefix_set ']' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PREFIX_SET; $$->a2.p = $2; } - | ENUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; } - | bgp_path { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; val->type = T_PATH_MASK; val->val.path_mask = $1; $$->a1.p = val; } + NUM { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_INT; $$->a2.i = $1; } + | TRUE { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_BOOL; $$->a2.i = 1; } + | FALSE { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_BOOL; $$->a2.i = 0; } + | TEXT { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_STRING; $$->a2.p = $1; } + | fipa { NEW_F_VAL; $$ = f_new_inst(FI_CONSTANT_INDIRECT); $$->a1.p = val; *val = $1; } + | VPN_RD { NEW_F_VAL; $$ = f_new_inst(FI_CONSTANT_INDIRECT); val->type = T_RD; val->val.ec = $1; $$->a1.p = val; } + | net_ { NEW_F_VAL; $$ = f_new_inst(FI_CONSTANT_INDIRECT); val->type = T_NET; val->val.net = $1; $$->a1.p = val; } + | '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(FI_CONSTANT); $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); } + | '[' fprefix_set ']' { $$ = f_new_inst(FI_CONSTANT); $$->aux = T_PREFIX_SET; $$->a2.p = $2; } + | ENUM { $$ = f_new_inst(FI_CONSTANT); $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; } + | bgp_path { NEW_F_VAL; $$ = f_new_inst(FI_CONSTANT_INDIRECT); val->type = T_PATH_MASK; val->val.path_mask = $1; $$->a1.p = val; } ; constructor: @@ -801,7 +790,7 @@ constructor: * For such cases, we force the dynamic_attr list to contain * at least an invalid token, so it is syntantically correct. */ -CF_ADDTO(dynamic_attr, INVALID_TOKEN { $$ = NULL; }) +CF_ADDTO(dynamic_attr, INVALID_TOKEN { $$ = (struct f_dynamic_attr) {}; }) rtadot: /* EMPTY, we are not permitted RTA. prefix */ ; @@ -813,8 +802,7 @@ function_call: if ($1->class != SYM_FUNCTION) cf_error("You can't call something which is not a function. Really."); DBG("You are calling function %s\n", $1->name); - $$ = f_new_inst(); - $$->code = P('c','a'); + $$ = f_new_inst(FI_CALL); $$->a1.p = inst; $$->a2.p = $1->def; sym = $1->aux2; @@ -831,11 +819,9 @@ function_call: symbol: SYM { - $$ = f_new_inst(); - switch ($1->class & 0xff00) { - case SYM_CONSTANT: $$->code = 'C'; break; - case SYM_VARIABLE: $$->code = 'V'; break; + case SYM_CONSTANT: $$ = f_new_inst(FI_CONSTANT_INDIRECT); break; + case SYM_VARIABLE: $$ = f_new_inst(FI_VARIABLE); break; default: cf_error("%s: variable expected.", $1->name); } @@ -844,57 +830,57 @@ symbol: } static_attr: - FROM { $$ = f_new_inst(); $$->aux = T_IP; $$->a2.i = SA_FROM; $$->a1.i = 1; } - | GW { $$ = f_new_inst(); $$->aux = T_IP; $$->a2.i = SA_GW; $$->a1.i = 1; } - | NET { $$ = f_new_inst(); $$->aux = T_NET; $$->a2.i = SA_NET; } - | PROTO { $$ = f_new_inst(); $$->aux = T_STRING; $$->a2.i = SA_PROTO; } - | SOURCE { $$ = f_new_inst(); $$->aux = T_ENUM_RTS; $$->a2.i = SA_SOURCE; } - | SCOPE { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = SA_SCOPE; $$->a1.i = 1; } - | DEST { $$ = f_new_inst(); $$->aux = T_ENUM_RTD; $$->a2.i = SA_DEST; $$->a1.i = 1; } - | IFNAME { $$ = f_new_inst(); $$->aux = T_STRING; $$->a2.i = SA_IFNAME; } - | IFINDEX { $$ = f_new_inst(); $$->aux = T_INT; $$->a2.i = SA_IFINDEX; } + FROM { $$ = f_new_static_attr(T_IP, SA_FROM, 1); } + | GW { $$ = f_new_static_attr(T_IP, SA_GW, 1); } + | NET { $$ = f_new_static_attr(T_NET, SA_NET, 0); } + | PROTO { $$ = f_new_static_attr(T_STRING, SA_PROTO, 0); } + | SOURCE { $$ = f_new_static_attr(T_ENUM_RTS, SA_SOURCE, 0); } + | SCOPE { $$ = f_new_static_attr(T_ENUM_SCOPE, SA_SCOPE, 1); } + | DEST { $$ = f_new_static_attr(T_ENUM_RTD, SA_DEST, 1); } + | IFNAME { $$ = f_new_static_attr(T_STRING, SA_IFNAME, 0); } + | IFINDEX { $$ = f_new_static_attr(T_INT, SA_IFINDEX, 0); } ; term: - '(' 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 = $3; } - | term '/' term { $$ = f_new_inst(); $$->code = '/'; $$->a1.p = $1; $$->a2.p = $3; } - | term AND term { $$ = f_new_inst(); $$->code = '&'; $$->a1.p = $1; $$->a2.p = $3; } - | term OR term { $$ = f_new_inst(); $$->code = '|'; $$->a1.p = $1; $$->a2.p = $3; } - | term '=' term { $$ = f_new_inst(); $$->code = P('=','='); $$->a1.p = $1; $$->a2.p = $3; } - | term NEQ term { $$ = f_new_inst(); $$->code = P('!','='); $$->a1.p = $1; $$->a2.p = $3; } - | term '<' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $1; $$->a2.p = $3; } - | term LEQ term { $$ = f_new_inst(); $$->code = P('<','='); $$->a1.p = $1; $$->a2.p = $3; } - | term '>' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $3; $$->a2.p = $1; } - | term GEQ term { $$ = f_new_inst(); $$->code = P('<','='); $$->a1.p = $3; $$->a2.p = $1; } - | term '~' term { $$ = f_new_inst(); $$->code = '~'; $$->a1.p = $1; $$->a2.p = $3; } - | term NMA term { $$ = f_new_inst(); $$->code = P('!','~'); $$->a1.p = $1; $$->a2.p = $3; } - | '!' term { $$ = f_new_inst(); $$->code = '!'; $$->a1.p = $2; } - | DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e'); $$->a1.p = $3; } + '(' term ')' { $$ = $2; } + | term '+' term { $$ = f_new_inst(FI_ADD); $$->a1.p = $1; $$->a2.p = $3; } + | term '-' term { $$ = f_new_inst(FI_SUBTRACT); $$->a1.p = $1; $$->a2.p = $3; } + | term '*' term { $$ = f_new_inst(FI_MULTIPLY); $$->a1.p = $1; $$->a2.p = $3; } + | term '/' term { $$ = f_new_inst(FI_DIVIDE); $$->a1.p = $1; $$->a2.p = $3; } + | term AND term { $$ = f_new_inst(FI_AND); $$->a1.p = $1; $$->a2.p = $3; } + | term OR term { $$ = f_new_inst(FI_OR); $$->a1.p = $1; $$->a2.p = $3; } + | term '=' term { $$ = f_new_inst(FI_EQ); $$->a1.p = $1; $$->a2.p = $3; } + | term NEQ term { $$ = f_new_inst(FI_NEQ); $$->a1.p = $1; $$->a2.p = $3; } + | term '<' term { $$ = f_new_inst(FI_LT); $$->a1.p = $1; $$->a2.p = $3; } + | term LEQ term { $$ = f_new_inst(FI_LTE); $$->a1.p = $1; $$->a2.p = $3; } + | term '>' term { $$ = f_new_inst(FI_LT); $$->a1.p = $3; $$->a2.p = $1; } + | term GEQ term { $$ = f_new_inst(FI_LTE); $$->a1.p = $3; $$->a2.p = $1; } + | term '~' term { $$ = f_new_inst(FI_MATCH); $$->a1.p = $1; $$->a2.p = $3; } + | term NMA term { $$ = f_new_inst(FI_NOT_MATCH);$$->a1.p = $1; $$->a2.p = $3; } + | '!' term { $$ = f_new_inst(FI_NOT); $$->a1.p = $2; } + | DEFINED '(' term ')' { $$ = f_new_inst(FI_DEFINED); $$->a1.p = $3; } | symbol { $$ = $1; } | constant { $$ = $1; } | constructor { $$ = $1; } - | PREFERENCE { $$ = f_new_inst(); $$->code = 'P'; } + | PREFERENCE { $$ = f_new_inst(FI_PREF_GET); } - | rtadot static_attr { $$ = $2; $$->code = 'a'; } + | rtadot static_attr { $$ = f_new_inst_sa(FI_RTA_GET, $2); } - | rtadot dynamic_attr { $$ = $2; $$->code = P('e','a'); } + | rtadot dynamic_attr { $$ = f_new_inst_da(FI_EA_GET, $2); } - | term '.' IS_V4 { $$ = f_new_inst(); $$->code = P('I','i'); $$->a1.p = $1; } - | term '.' TYPE { $$ = f_new_inst(); $$->code = 'T'; $$->a1.p = $1; } - | term '.' IP { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_IP; } - | term '.' RD { $$ = f_new_inst(); $$->code = P('R','D'); $$->a1.p = $1; $$->aux = T_RD; } - | term '.' LEN { $$ = f_new_inst(); $$->code = 'L'; $$->a1.p = $1; } - | term '.' MAXLEN { $$ = f_new_inst(); $$->code = P('R','m'); $$->a1.p = $1; } - | term '.' ASN { $$ = f_new_inst(); $$->code = P('R','a'); $$->a1.p = $1; } - | term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = P('i','M'); $$->a1.p = $1; $$->a2.p = $5; } - | term '.' FIRST { $$ = f_new_inst(); $$->code = P('a','f'); $$->a1.p = $1; } - | term '.' LAST { $$ = f_new_inst(); $$->code = P('a','l'); $$->a1.p = $1; } - | term '.' LAST_NONAGGREGATED { $$ = f_new_inst(); $$->code = P('a','L'); $$->a1.p = $1; } + | term '.' IS_V4 { $$ = f_new_inst(FI_IS_V4); $$->a1.p = $1; } + | term '.' TYPE { $$ = f_new_inst(FI_TYPE); $$->a1.p = $1; } + | term '.' IP { $$ = f_new_inst(FI_IP); $$->a1.p = $1; $$->aux = T_IP; } + | term '.' RD { $$ = f_new_inst(FI_ROUTE_DISTINGUISHER); $$->a1.p = $1; $$->aux = T_RD; } + | term '.' LEN { $$ = f_new_inst(FI_LENGTH); $$->a1.p = $1; } + | term '.' MAXLEN { $$ = f_new_inst(FI_ROA_MAXLEN); $$->a1.p = $1; } + | term '.' ASN { $$ = f_new_inst(FI_ROA_ASN); $$->a1.p = $1; } + | term '.' MASK '(' term ')' { $$ = f_new_inst(FI_IP_MASK); $$->a1.p = $1; $$->a2.p = $5; } + | term '.' FIRST { $$ = f_new_inst(FI_AS_PATH_FIRST); $$->a1.p = $1; } + | term '.' LAST { $$ = f_new_inst(FI_AS_PATH_LAST); $$->a1.p = $1; } + | term '.' LAST_NONAGGREGATED { $$ = f_new_inst(FI_AS_PATH_LAST_NAG); $$->a1.p = $1; } /* Communities */ /* This causes one shift/reduce conflict @@ -904,19 +890,19 @@ term: | rtadot dynamic_attr '.' RESET{ } */ - | '+' EMPTY '+' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_PATH; } - | '-' EMPTY '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_CLIST; } - | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_ECLIST; } - | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(); $$->code = 'E'; $$->aux = T_LCLIST; } - | PREPEND '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('A','p'); $$->a1.p = $3; $$->a2.p = $5; } - | ADD '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; } - | DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; } - | FILTER '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'f'; } + | '+' EMPTY '+' { $$ = f_new_inst(FI_EMPTY); $$->aux = T_PATH; } + | '-' EMPTY '-' { $$ = f_new_inst(FI_EMPTY); $$->aux = T_CLIST; } + | '-' '-' EMPTY '-' '-' { $$ = f_new_inst(FI_EMPTY); $$->aux = T_ECLIST; } + | '-' '-' '-' EMPTY '-' '-' '-' { $$ = f_new_inst(FI_EMPTY); $$->aux = T_LCLIST; } + | PREPEND '(' term ',' term ')' { $$ = f_new_inst(FI_PATH_PREPEND); $$->a1.p = $3; $$->a2.p = $5; } + | ADD '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_ADD_DEL); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'a'; } + | DELETE '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_ADD_DEL); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; } + | FILTER '(' term ',' term ')' { $$ = f_new_inst(FI_CLIST_ADD_DEL); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'f'; } | ROA_CHECK '(' rtable ')' { $$ = f_generate_roa_check($3, NULL, NULL); } | ROA_CHECK '(' rtable ',' term ',' term ')' { $$ = f_generate_roa_check($3, $5, $7); } - | FORMAT '(' term ')' { $$ = f_new_inst(); $$->code = P('f','m'); $$->a1.p = $3; } + | FORMAT '(' term ')' { $$ = f_new_inst(FI_FORMAT); $$->a1.p = $3; } /* | term '.' LEN { $$->code = P('P','l'); } */ @@ -927,8 +913,7 @@ term: if ($1->class != SYM_FUNCTION) cf_error("You can't call something which is not a function. Really."); DBG("You are calling function %s\n", $1->name); - $$ = f_new_inst(); - $$->code = P('c','a'); + $$ = f_new_inst(FI_CALL); $$->a1.p = inst; $$->a2.p = $1->def; sym = $1->aux2; @@ -953,7 +938,7 @@ break_command: ; print_one: - term { $$ = f_new_inst(); $$->code = 'p'; $$->a1.p = $1; $$->a2.p = NULL; } + term { $$ = f_new_inst(FI_PRINT); $$->a1.p = $1; $$->a2.p = NULL; } ; print_list: /* EMPTY */ { $$ = NULL; } @@ -967,15 +952,13 @@ print_list: /* EMPTY */ { $$ = NULL; } ; var_listn: term { - $$ = f_new_inst(); - $$->code = 's'; + $$ = f_new_inst(FI_SET); $$->a1.p = NULL; $$->a2.p = $1; $$->next = NULL; } | term ',' var_listn { - $$ = f_new_inst(); - $$->code = 's'; + $$ = f_new_inst(FI_SET); $$->a1.p = NULL; $$->a2.p = $1; $$->next = $3; @@ -988,73 +971,63 @@ var_list: /* EMPTY */ { $$ = NULL; } cmd: IF term THEN block { - $$ = f_new_inst(); - $$->code = '?'; + $$ = f_new_inst(FI_CONDITION); $$->a1.p = $2; $$->a2.p = $4; } | IF term THEN block ELSE block { - struct f_inst *i = f_new_inst(); - i->code = '?'; + struct f_inst *i = f_new_inst(FI_CONDITION); i->a1.p = $2; i->a2.p = $4; - $$ = f_new_inst(); - $$->code = '?'; + $$ = f_new_inst(FI_CONDITION); $$->a1.p = i; $$->a2.p = $6; } | SYM '=' term ';' { - $$ = f_new_inst(); DBG( "Ook, we'll set value\n" ); if (($1->class & ~T_MASK) != SYM_VARIABLE) cf_error( "You may set only variables." ); - $$->code = 's'; + $$ = f_new_inst(FI_SET); $$->a1.p = $1; $$->a2.p = $3; } | RETURN term ';' { - $$ = f_new_inst(); DBG( "Ook, we'll return the value\n" ); - $$->code = 'r'; + $$ = f_new_inst(FI_RETURN); $$->a1.p = $2; } | rtadot dynamic_attr '=' term ';' { - $$ = $2; - $$->code = P('e','S'); + $$ = f_new_inst_da(FI_EA_SET, $2); $$->a1.p = $4; } | rtadot static_attr '=' term ';' { - $$ = $2; + $$ = f_new_inst_sa(FI_RTA_SET, $2); if (!$$->a1.i) cf_error( "This static attribute is read-only."); - $$->code = P('a','S'); $$->a1.p = $4; } | PREFERENCE '=' term ';' { - $$ = f_new_inst(); - $$->code = P('P','S'); + $$ = f_new_inst(FI_PREF_SET); $$->a1.p = $3; } | UNSET '(' rtadot dynamic_attr ')' ';' { - $$ = $4; + $$ = f_new_inst_da(FI_EA_SET, $4); $$->aux = EAF_TYPE_UNDEF | EAF_TEMP; - $$->code = P('e','S'); $$->a1.p = NULL; } - | break_command print_list ';' { $$ = f_new_inst(); $$->code = P('p',','); $$->a1.p = $2; $$->a2.i = $1; } + | break_command print_list ';' { $$ = f_new_inst(FI_PRINT_AND_DIE); $$->a1.p = $2; $$->a2.i = $1; } | function_call ';' { $$ = $1; } | CASE term '{' switch_body '}' { - $$ = f_new_inst(); - $$->code = P('S','W'); + $$ = f_new_inst(FI_SWITCH); $$->a1.p = $2; $$->a2.p = build_tree( $4 ); } | rtadot dynamic_attr '.' EMPTY ';' { $$ = f_generate_empty($2); } - | rtadot dynamic_attr '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex( P('A','p'), 'x', $2, $6 ); } - | rtadot dynamic_attr '.' ADD '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'a', $2, $6 ); } - | rtadot dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'd', $2, $6 ); } - | rtadot dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( P('C','a'), 'f', $2, $6 ); } + | rtadot dynamic_attr '.' PREPEND '(' term ')' ';' { $$ = f_generate_complex( FI_PATH_PREPEND, 'x', $2, $6 ); } + | rtadot dynamic_attr '.' ADD '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_ADD_DEL, 'a', $2, $6 ); } + | rtadot dynamic_attr '.' DELETE '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_ADD_DEL, 'd', $2, $6 ); } + | rtadot dynamic_attr '.' FILTER '(' term ')' ';' { $$ = f_generate_complex( FI_CLIST_ADD_DEL, 'f', $2, $6 ); } | BT_ASSERT '(' get_cf_position term get_cf_position ')' ';' { $$ = assert_done($4, $3 + 1, $5 - 1); } ; diff --git a/filter/f-util.c b/filter/f-util.c index 52c13223..68aecd73 100644 --- a/filter/f-util.c +++ b/filter/f-util.c @@ -2,6 +2,7 @@ * Filters: utility functions * * Copyright 1998 Pavel Machek <pavel@ucw.cz> + * 2017 Jan Maria Matejka <mq@ucw.cz> * * Can be freely distributed and used under the terms of the GNU GPL. */ @@ -13,43 +14,48 @@ #define P(a,b) ((a<<8) | b) struct f_inst * -f_new_inst(void) +f_new_inst(enum f_instruction_code fi_code) { struct f_inst * ret; - ret = cfg_alloc(sizeof(struct f_inst)); - ret->code = ret->aux = 0; - ret->arg1 = ret->arg2 = ret->next = NULL; + ret = cfg_allocz(sizeof(struct f_inst)); + ret->fi_code = fi_code; ret->lineno = ifs->lino; return ret; } struct f_inst * -f_new_dynamic_attr(int type, int f_type, int code) +f_new_inst_da(enum f_instruction_code fi_code, struct f_dynamic_attr da) { - /* FIXME: Remove the f_type parameter? */ - struct f_inst *f = f_new_inst(); - f->aux = (f_type << 8) | type; - f->a2.i = code; - return f; + struct f_inst *ret = f_new_inst(fi_code); + ret->aux = (da.f_type << 8) | da.type; + ret->a2.i = da.ea_code; + return ret; +} + +struct f_inst * +f_new_inst_sa(enum f_instruction_code fi_code, struct f_static_attr sa) +{ + struct f_inst *ret = f_new_inst(fi_code); + ret->aux = sa.f_type; + ret->a2.i = sa.sa_code; + ret->a1.i = sa.readonly; + return ret; } /* * Generate set_dynamic( operation( get_dynamic(), argument ) ) */ struct f_inst * -f_generate_complex(int operation, int operation_aux, struct f_inst *dyn, struct f_inst *argument) +f_generate_complex(int operation, int operation_aux, struct f_dynamic_attr da, struct f_inst *argument) { - struct f_inst *set_dyn = f_new_inst(), - *oper = f_new_inst(), - *get_dyn = dyn; + struct f_inst *set_dyn = f_new_inst_da(FI_EA_SET, da), + *oper = f_new_inst(operation), + *get_dyn = f_new_inst_da(FI_EA_GET, da); - *set_dyn = *get_dyn; - get_dyn->code = P('e','a'); - oper->code = operation; oper->aux = operation_aux; oper->a1.p = get_dyn; oper->a2.p = argument; - set_dyn->code = P('e','S'); + set_dyn->a1.p = oper; return set_dyn; } @@ -58,7 +64,7 @@ struct f_inst * f_generate_roa_check(struct rtable_config *table, struct f_inst *prefix, struct f_inst *asn) { struct f_inst_roa_check *ret = cfg_allocz(sizeof(struct f_inst_roa_check)); - ret->i.code = P('R','C'); + ret->i.fi_code = FI_ROA_CHECK; ret->i.lineno = ifs->lino; ret->i.arg1 = prefix; ret->i.arg2 = asn; diff --git a/filter/filter.c b/filter/filter.c index 8cf90b53..f81f5cfe 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -48,8 +48,6 @@ #include "conf/conf.h" #include "filter/filter.h" -#define P(a,b) ((a<<8) | b) - #define CMP_ERROR 999 void (*bt_assert_hook)(int result, struct f_inst *assert); @@ -462,7 +460,6 @@ val_in_range(struct f_val v1, struct f_val v2) if (((v1.type == T_PAIR) || (v1.type == T_QUAD)) && (v2.type == T_CLIST)) return int_set_contains(v2.val.ad, v1.val.i); - /* IP->Quad implicit conversion */ if (val_is_ip4(v1) && (v2.type == T_CLIST)) return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.ip)); @@ -632,22 +629,20 @@ static struct f_val interpret(struct f_inst *what) { struct symbol *sym; - struct f_val v1, v2, res, *vp; + struct f_val v1, v2, res = { .type = T_VOID }, *vp; unsigned u1, u2; int i; u32 as; + for ( ; what; what = what->next) { res.type = T_VOID; - if (!what) - return res; - - switch(what->code) { - case ',': + switch(what->fi_code) { + case FI_COMMA: TWOARGS; break; /* Binary operators */ - case '+': + case FI_ADD: TWOARGS_C; switch (res.type = v1.type) { case T_VOID: runtime( "Can't operate with values of type void" ); @@ -655,7 +650,7 @@ interpret(struct f_inst *what) default: runtime( "Usage of unknown type" ); } break; - case '-': + case FI_SUBTRACT: TWOARGS_C; switch (res.type = v1.type) { case T_VOID: runtime( "Can't operate with values of type void" ); @@ -663,7 +658,7 @@ interpret(struct f_inst *what) default: runtime( "Usage of unknown type" ); } break; - case '*': + case FI_MULTIPLY: TWOARGS_C; switch (res.type = v1.type) { case T_VOID: runtime( "Can't operate with values of type void" ); @@ -671,7 +666,7 @@ interpret(struct f_inst *what) default: runtime( "Usage of unknown type" ); } break; - case '/': + case FI_DIVIDE: TWOARGS_C; switch (res.type = v1.type) { case T_VOID: runtime( "Can't operate with values of type void" ); @@ -681,12 +676,12 @@ interpret(struct f_inst *what) } break; - case '&': - case '|': + case FI_AND: + case FI_OR: ARG(v1, a1.p); if (v1.type != T_BOOL) runtime( "Can't do boolean operation on non-booleans" ); - if (v1.val.i == (what->code == '|')) { + if (v1.val.i == (what->fi_code == FI_OR)) { res.type = T_BOOL; res.val.i = v1.val.i; break; @@ -699,7 +694,7 @@ interpret(struct f_inst *what) res.val.i = v2.val.i; break; - case P('m','p'): + case FI_PAIR_CONSTRUCT: TWOARGS; if ((v1.type != T_INT) || (v2.type != T_INT)) runtime( "Can't operate with value of non-integer type in pair constructor" ); @@ -711,7 +706,7 @@ interpret(struct f_inst *what) res.type = T_PAIR; break; - case P('m','c'): + case FI_EC_CONSTRUCT: { TWOARGS; @@ -757,7 +752,7 @@ interpret(struct f_inst *what) break; } - case P('m','l'): + case FI_LC_CONSTRUCT: { TWOARGS; @@ -793,12 +788,12 @@ interpret(struct f_inst *what) res.val.i = (x); \ break; - case P('!','='): SAME(!i); - case P('=','='): SAME(i); - case '<': COMPARE(i==-1); - case P('<','='): COMPARE(i!=1); + case FI_NEQ: SAME(!i); + case FI_EQ: SAME(i); + case FI_LT: COMPARE(i==-1); + case FI_LTE: COMPARE(i!=1); - case '!': + case FI_NOT: ONEARG; if (v1.type != T_BOOL) runtime( "Not applied to non-boolean" ); @@ -806,7 +801,7 @@ interpret(struct f_inst *what) res.val.i = !res.val.i; break; - case '~': + case FI_MATCH: TWOARGS; res.type = T_BOOL; res.val.i = val_in_range(v1, v2); @@ -815,7 +810,7 @@ interpret(struct f_inst *what) res.val.i = !!res.val.i; break; - case P('!','~'): + case FI_NOT_MATCH: TWOARGS; res.type = T_BOOL; res.val.i = val_in_range(v1, v2); @@ -824,12 +819,12 @@ interpret(struct f_inst *what) res.val.i = !res.val.i; break; - case P('d','e'): + case FI_DEFINED: ONEARG; res.type = T_BOOL; res.val.i = (v1.type != T_VOID) && !undef_value(v1); break; - case 'T': + case FI_TYPE: ONEARG; switch (v1.type) { @@ -841,7 +836,7 @@ interpret(struct f_inst *what) runtime( "Can't determine type of this item" ); } break; - case P('I','i'): + case FI_IS_V4: ONEARG; if (v1.type != T_IP) runtime( "IP version check needs an IP address" ); @@ -850,7 +845,7 @@ interpret(struct f_inst *what) break; /* Set to indirect value, a1 = variable, a2 = value */ - case 's': + case FI_SET: ARG(v2, a2.p); sym = what->a1.p; vp = sym->def; @@ -869,7 +864,7 @@ interpret(struct f_inst *what) break; /* some constants have value in a2, some in *a1.p, strange. */ - case 'c': /* integer (or simple type) constant, string, set, or prefix_set */ + case FI_CONSTANT: /* integer (or simple type) constant, string, set, or prefix_set */ res.type = what->aux; if (res.type == T_PREFIX_SET) @@ -881,15 +876,15 @@ interpret(struct f_inst *what) else res.val.i = what->a2.i; break; - case 'V': - case 'C': + case FI_VARIABLE: + case FI_CONSTANT_INDIRECT: res = * ((struct f_val *) what->a1.p); break; - case 'p': + case FI_PRINT: ONEARG; val_format(v1, &f_buf); break; - case '?': /* ? has really strange error value, so we can implement if ... else nicely :-) */ + case FI_CONDITION: /* ? has really strange error value, so we can implement if ... else nicely :-) */ ONEARG; if (v1.type != T_BOOL) runtime( "If requires boolean expression" ); @@ -899,10 +894,10 @@ interpret(struct f_inst *what) } else res.val.i = 1; res.type = T_BOOL; break; - case '0': + case FI_NOP: debug( "No operation\n" ); break; - case P('p',','): + case FI_PRINT_AND_DIE: ONEARG; if ((what->a2.i == F_NOP || (what->a2.i != F_NONL && what->a1.p)) && !(f_flags & FF_SILENT)) @@ -925,7 +920,7 @@ interpret(struct f_inst *what) bug( "unknown return type: Can't happen"); } break; - case 'a': /* rta access */ + case FI_RTA_GET: /* rta access */ { ACCESS_RTE; struct rta *rta = (*f_rte)->attrs; @@ -948,7 +943,7 @@ interpret(struct f_inst *what) } } break; - case P('a','S'): + case FI_RTA_SET: ACCESS_RTE; ONEARG; if (what->aux != v1.type) @@ -1000,7 +995,7 @@ interpret(struct f_inst *what) } } break; - case P('e','a'): /* Access to extended attributes */ + case FI_EA_GET: /* Access to extended attributes */ ACCESS_RTE; { eattr *e = NULL; @@ -1094,7 +1089,7 @@ interpret(struct f_inst *what) } } break; - case P('e','S'): + case FI_EA_SET: ACCESS_RTE; ONEARG; { @@ -1198,12 +1193,12 @@ interpret(struct f_inst *what) } } break; - case 'P': + case FI_PREF_GET: ACCESS_RTE; res.type = T_INT; res.val.i = (*f_rte)->pref; break; - case P('P','S'): + case FI_PREF_SET: ACCESS_RTE; ONEARG; if (v1.type != T_INT) @@ -1213,7 +1208,7 @@ interpret(struct f_inst *what) f_rte_cow(); (*f_rte)->pref = v1.val.i; break; - case 'L': /* Get length of */ + case FI_LENGTH: /* Get length of */ ONEARG; res.type = T_INT; switch(v1.type) { @@ -1225,7 +1220,7 @@ interpret(struct f_inst *what) default: runtime( "Prefix, path, clist or eclist expected" ); } break; - case P('R','m'): /* Get ROA max prefix length */ + case FI_ROA_MAXLEN: /* Get ROA max prefix length */ ONEARG; if (v1.type != T_NET || !net_is_roa(v1.val.net)) runtime( "ROA expected" ); @@ -1235,7 +1230,7 @@ interpret(struct f_inst *what) ((net_addr_roa4 *) v1.val.net)->max_pxlen : ((net_addr_roa6 *) v1.val.net)->max_pxlen; break; - case P('R','a'): /* Get ROA ASN */ + case FI_ROA_ASN: /* Get ROA ASN */ ONEARG; if (v1.type != T_NET || !net_is_roa(v1.val.net)) runtime( "ROA expected" ); @@ -1245,14 +1240,14 @@ interpret(struct f_inst *what) ((net_addr_roa4 *) v1.val.net)->asn : ((net_addr_roa6 *) v1.val.net)->asn; break; - case P('c','p'): /* Convert prefix to ... */ + case FI_IP: /* Convert prefix to ... */ ONEARG; if (v1.type != T_NET) runtime( "Prefix expected" ); res.type = T_IP; res.val.ip = net_prefix(v1.val.net); break; - case P('R','D'): + case FI_ROUTE_DISTINGUISHER: ONEARG; if (v1.type != T_NET) runtime( "Prefix expected" ); @@ -1261,7 +1256,7 @@ interpret(struct f_inst *what) res.type = T_RD; res.val.ec = net_rd(v1.val.net); break; - case P('a','f'): /* Get first ASN from AS PATH */ + case FI_AS_PATH_FIRST: /* Get first ASN from AS PATH */ ONEARG; if (v1.type != T_PATH) runtime( "AS path expected" ); @@ -1271,7 +1266,7 @@ interpret(struct f_inst *what) res.type = T_INT; res.val.i = as; break; - case P('a','l'): /* Get last ASN from AS PATH */ + case FI_AS_PATH_LAST: /* Get last ASN from AS PATH */ ONEARG; if (v1.type != T_PATH) runtime( "AS path expected" ); @@ -1281,7 +1276,7 @@ interpret(struct f_inst *what) res.type = T_INT; res.val.i = as; break; - case P('a','L'): /* Get last ASN from non-aggregated part of AS PATH */ + case FI_AS_PATH_LAST_NAG: /* Get last ASN from non-aggregated part of AS PATH */ ONEARG; if (v1.type != T_PATH) runtime( "AS path expected" ); @@ -1289,23 +1284,23 @@ interpret(struct f_inst *what) res.type = T_INT; res.val.i = as_path_get_last_nonaggregated(v1.val.ad); break; - case 'r': + case FI_RETURN: ONEARG; res = v1; res.type |= T_RETURN; return res; - case P('c','a'): /* CALL: this is special: if T_RETURN and returning some value, mask it out */ + case FI_CALL: /* CALL: this is special: if T_RETURN and returning some value, mask it out */ ONEARG; res = interpret(what->a2.p); if (res.type == T_RETURN) return res; res.type &= ~T_RETURN; break; - case P('c','v'): /* Clear local variables */ + case FI_CLEAR_LOCAL_VARS: /* Clear local variables */ for (sym = what->a1.p; sym != NULL; sym = sym->aux2) ((struct f_val *) sym->def)->type = T_VOID; break; - case P('S','W'): + case FI_SWITCH: ONEARG; { struct f_tree *t = find_tree(what->a2.p, v1); @@ -1324,7 +1319,7 @@ interpret(struct f_inst *what) return res; } break; - case P('i','M'): /* IP.MASK(val) */ + case FI_IP_MASK: /* IP.MASK(val) */ TWOARGS; if (v2.type != T_INT) runtime( "Integer expected"); @@ -1337,11 +1332,11 @@ interpret(struct f_inst *what) ipa_from_ip6(ip6_and(ipa_to_ip6(v1.val.ip), ip6_mkmask(v2.val.i))); break; - case 'E': /* Create empty attribute */ + case FI_EMPTY: /* Create empty attribute */ res.type = what->aux; res.val.ad = adata_empty(f_pool, 0); break; - case P('A','p'): /* Path prepend */ + case FI_PATH_PREPEND: /* Path prepend */ TWOARGS; if (v1.type != T_PATH) runtime("Can't prepend to non-path"); @@ -1352,7 +1347,7 @@ interpret(struct f_inst *what) res.val.ad = as_path_prepend(f_pool, v1.val.ad, v2.val.i); break; - case P('C','a'): /* (Extended) Community list add or delete */ + case FI_CLIST_ADD_DEL: /* (Extended) Community list add or delete */ TWOARGS; if (v1.type == T_PATH) { @@ -1518,8 +1513,7 @@ interpret(struct f_inst *what) break; - - case P('R','C'): /* ROA Check */ + case FI_ROA_CHECK: /* ROA Check */ if (what->arg1) { TWOARGS; @@ -1559,14 +1553,14 @@ interpret(struct f_inst *what) break; - case P('f','m'): /* Format */ + case FI_FORMAT: /* Format */ ONEARG; res.type = T_STRING; res.val.s = val_format_str(v1); break; - case P('a','s'): /* Birdtest Assert */ + case FI_ASSERT: /* Birdtest Assert */ ONEARG; if (v1.type != T_BOOL) @@ -1579,10 +1573,8 @@ interpret(struct f_inst *what) break; default: - bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff); - } - if (what->next) - return interpret(what->next); + bug( "Unknown instruction %d (%c)", what->fi_code, what->fi_code & 0xff); + }} return res; } @@ -1609,40 +1601,39 @@ i_same(struct f_inst *f1, struct f_inst *f2) return 1; if (f1->aux != f2->aux) return 0; - if (f1->code != f2->code) + if (f1->fi_code != f2->fi_code) return 0; if (f1 == f2) /* It looks strange, but it is possible with call rewriting trickery */ return 1; - switch(f1->code) { - case ',': /* fall through */ - case '+': - case '-': - case '*': - case '/': - case '|': - case '&': - case P('m','p'): - case P('m','c'): - case P('!','='): - case P('=','='): - case '<': - case P('<','='): TWOARGS; break; - - case '!': ONEARG; break; - case P('!', '~'): - case '~': TWOARGS; break; - case P('d','e'): ONEARG; break; - case 'T': ONEARG; break; - case P('n','T'): break; - - case P('m','l'): + switch(f1->fi_code) { + case FI_COMMA: /* fall through */ + case FI_ADD: + case FI_SUBTRACT: + case FI_MULTIPLY: + case FI_DIVIDE: + case FI_OR: + case FI_AND: + case FI_PAIR_CONSTRUCT: + case FI_EC_CONSTRUCT: + case FI_NEQ: + case FI_EQ: + case FI_LT: + case FI_LTE: TWOARGS; break; + + case FI_NOT: ONEARG; break; + case FI_NOT_MATCH: + case FI_MATCH: TWOARGS; break; + case FI_DEFINED: ONEARG; break; + case FI_TYPE: ONEARG; break; + + case FI_LC_CONSTRUCT: TWOARGS; if (!i_same(INST3(f1).p, INST3(f2).p)) return 0; break; - case 's': + case FI_SET: ARG(v2, a2.p); { struct symbol *s1, *s2; @@ -1655,7 +1646,7 @@ i_same(struct f_inst *f1, struct f_inst *f2) } break; - case 'c': + case FI_CONSTANT: switch (f1->aux) { case T_PREFIX_SET: @@ -1678,44 +1669,44 @@ i_same(struct f_inst *f1, struct f_inst *f2) } break; - case 'C': + case FI_CONSTANT_INDIRECT: if (!val_same(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a1.p)) return 0; break; - case 'V': + case FI_VARIABLE: if (strcmp((char *) f1->a2.p, (char *) f2->a2.p)) return 0; break; - case 'p': case 'L': ONEARG; break; - case '?': TWOARGS; break; - case '0': case 'E': break; - case P('p',','): ONEARG; A2_SAME; break; - case 'P': - case 'a': A2_SAME; break; - case P('e','a'): A2_SAME; break; - case P('P','S'): - case P('a','S'): - case P('e','S'): ONEARG; A2_SAME; break; - - case 'r': ONEARG; break; - case P('c','p'): ONEARG; break; - case P('R','D'): ONEARG; break; - case P('c','a'): /* Call rewriting trickery to avoid exponential behaviour */ + case FI_PRINT: case FI_LENGTH: ONEARG; break; + case FI_CONDITION: TWOARGS; break; + case FI_NOP: case FI_EMPTY: break; + case FI_PRINT_AND_DIE: ONEARG; A2_SAME; break; + case FI_PREF_GET: + case FI_RTA_GET: A2_SAME; break; + case FI_EA_GET: A2_SAME; break; + case FI_PREF_SET: + case FI_RTA_SET: + case FI_EA_SET: ONEARG; A2_SAME; break; + + case FI_RETURN: ONEARG; break; + case FI_IP: ONEARG; break; + case FI_ROUTE_DISTINGUISHER: ONEARG; break; + case FI_CALL: /* Call rewriting trickery to avoid exponential behaviour */ ONEARG; if (!i_same(f1->a2.p, f2->a2.p)) return 0; f2->a2.p = f1->a2.p; break; - case P('c','v'): break; /* internal instruction */ - case P('S','W'): ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break; - case P('i','M'): TWOARGS; break; - case P('A','p'): TWOARGS; break; - case P('C','a'): TWOARGS; break; - case P('a','f'): - case P('a','l'): - case P('a','L'): ONEARG; break; - case P('R','C'): + case FI_CLEAR_LOCAL_VARS: break; /* internal instruction */ + case FI_SWITCH: ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break; + case FI_IP_MASK: TWOARGS; break; + case FI_PATH_PREPEND: TWOARGS; break; + case FI_CLIST_ADD_DEL: TWOARGS; break; + case FI_AS_PATH_FIRST: + case FI_AS_PATH_LAST: + case FI_AS_PATH_LAST_NAG: ONEARG; break; + case FI_ROA_CHECK: TWOARGS; /* Does not really make sense - ROA check results may change anyway */ if (strcmp(((struct f_inst_roa_check *) f1)->rtc->name, @@ -1723,7 +1714,7 @@ i_same(struct f_inst *f1, struct f_inst *f2) return 0; break; default: - bug( "Unknown instruction %d in same (%c)", f1->code, f1->code & 0xff); + bug( "Unknown instruction %d in same (%c)", f1->fi_code, f1->fi_code & 0xff); } return i_same(f1->next, f2->next); } diff --git a/filter/filter.h b/filter/filter.h index 49004c33..b1fc6c29 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -14,9 +14,74 @@ #include "nest/route.h" #include "nest/attrs.h" +/* Filter instruction types */ + +#define FI__TWOCHAR(a,b) ((a<<8) | b) +#define FI__LIST \ + F(FI_COMMA, 0, ',') \ + F(FI_ADD, 0, '+') \ + F(FI_SUBTRACT, 0, '-') \ + F(FI_MULTIPLY, 0, '*') \ + F(FI_DIVIDE, 0, '/') \ + F(FI_AND, 0, '&') \ + F(FI_OR, 0, '|') \ + F(FI_PAIR_CONSTRUCT, 'm', 'p') \ + F(FI_EC_CONSTRUCT, 'm', 'c') \ + F(FI_LC_CONSTRUCT, 'm', 'l') \ + F(FI_NEQ, '!', '=') \ + F(FI_EQ, '=', '=') \ + F(FI_LT, 0, '<') \ + F(FI_LTE, '<', '=') \ + F(FI_NOT, 0, '!') \ + F(FI_MATCH, 0, '~') \ + F(FI_NOT_MATCH, '!', '~') \ + F(FI_DEFINED, 'd', 'e') \ + F(FI_TYPE, 0, 'T') \ + F(FI_IS_V4, 'I', 'i') \ + F(FI_SET, 0, 's') \ + F(FI_CONSTANT, 0, 'c') \ + F(FI_VARIABLE, 0, 'V') \ + F(FI_CONSTANT_INDIRECT, 0, 'C') \ + F(FI_PRINT, 0, 'p') \ + F(FI_CONDITION, 0, '?') \ + F(FI_NOP, 0, '0') \ + F(FI_PRINT_AND_DIE, 'p', ',') \ + F(FI_RTA_GET, 0, 'a') \ + F(FI_RTA_SET, 'a', 'S') \ + F(FI_EA_GET, 'e', 'a') \ + F(FI_EA_SET, 'e', 'S') \ + F(FI_PREF_GET, 0, 'P') \ + F(FI_PREF_SET, 'P', 'S') \ + F(FI_LENGTH, 0, 'L') \ + F(FI_ROA_MAXLEN, 'R', 'M') \ + F(FI_ROA_ASN, 'R', 'A') \ + F(FI_IP, 'c', 'p') \ + F(FI_ROUTE_DISTINGUISHER, 'R', 'D') \ + F(FI_AS_PATH_FIRST, 'a', 'f') \ + F(FI_AS_PATH_LAST, 'a', 'l') \ + F(FI_AS_PATH_LAST_NAG, 'a', 'L') \ + F(FI_RETURN, 0, 'r') \ + F(FI_CALL, 'c', 'a') \ + F(FI_CLEAR_LOCAL_VARS, 'c', 'V') \ + F(FI_SWITCH, 'S', 'W') \ + F(FI_IP_MASK, 'i', 'M') \ + F(FI_EMPTY, 0, 'E') \ + F(FI_PATH_PREPEND, 'A', 'p') \ + F(FI_CLIST_ADD_DEL, 'C', 'a') \ + F(FI_ROA_CHECK, 'R', 'C') \ + F(FI_FORMAT, 0, 'F') \ + F(FI_ASSERT, 'a', 's') + +enum f_instruction_code { +#define F(c,a,b) \ + c = FI__TWOCHAR(a,b), +FI__LIST +#undef F +} PACKED; + struct f_inst { /* Instruction */ struct f_inst *next; /* Structure is 16 bytes, anyway */ - u16 code; /* Instruction code, see the interpret() function and P() macro */ + enum f_instruction_code fi_code; u16 aux; /* Extension to instruction code, T_*, EA_*, EAF_* */ union { uint i; @@ -70,15 +135,32 @@ struct f_val { } val; }; +struct f_dynamic_attr { + int type; + int f_type; + int ea_code; +}; + +struct f_static_attr { + int f_type; + int sa_code; + int readonly; +}; + struct filter { char *name; struct f_inst *root; }; -struct f_inst *f_new_inst(void); -struct f_inst *f_new_dynamic_attr(int type, int f_type, int code); /* Type as core knows it, type as filters know it, and code of dynamic attribute */ +struct f_inst *f_new_inst(enum f_instruction_code fi_code); +struct f_inst *f_new_inst_da(enum f_instruction_code fi_code, struct f_dynamic_attr da); +struct f_inst *f_new_inst_sa(enum f_instruction_code fi_code, struct f_static_attr sa); +static inline struct f_dynamic_attr f_new_dynamic_attr(int type, int f_type, int code) /* Type as core knows it, type as filters know it, and code of dynamic attribute */ +{ return (struct f_dynamic_attr) { .type = type, .f_type = f_type, .ea_code = code }; } /* f_type currently unused; will be handy for static type checking */ +static inline struct f_static_attr f_new_static_attr(int f_type, int code, int readonly) +{ return (struct f_static_attr) { .f_type = f_type, .sa_code = code, .readonly = readonly }; } struct f_tree *f_new_tree(void); -struct f_inst *f_generate_complex(int operation, int operation_aux, struct f_inst *dyn, struct f_inst *argument); +struct f_inst *f_generate_complex(int operation, int operation_aux, struct f_dynamic_attr da, struct f_inst *argument); struct f_inst *f_generate_roa_check(struct rtable_config *table, struct f_inst *prefix, struct f_inst *asn); |