diff --git a/filter/config.Y b/filter/config.Y index 37c0f3f3..9d5dc43a 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -20,7 +20,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, INT, BOOL, IP, PREFIX, PAIR, SET, STRING, BGPMASK, BGPPATH, CLIST, IF, THEN, ELSE, CASE, TRUE, FALSE, - FROM, GW, NET, MASK, SOURCE, SCOPE, CAST, DEST, + FROM, GW, NET, MASK, SOURCE, SCOPE, CAST, DEST, PREFERENCE, LEN, DEFINED, ADD, DELETE, CONTAINS, RESET, @@ -325,13 +325,12 @@ function_call: ; static_attr: -/* FIXME (maybe?) rta.from read/write */ - FROM { $$ = f_new_inst(); $$->aux = T_IP; $$->a2.i = OFFSETOF(struct rta, from); } + FROM { $$ = f_new_inst(); $$->aux = T_IP; $$->a2.i = OFFSETOF(struct rta, from); $$->a1.i = 1; } - | GW { $$ = f_new_inst(); $$->aux = T_IP; $$->a2.i = OFFSETOF(struct rta, gw); } /* FIXME: want it read/write */ + | GW { $$ = f_new_inst(); $$->aux = T_IP; $$->a2.i = OFFSETOF(struct rta, gw); $$->a1.i = 1; } | NET { $$ = f_new_inst(); $$->aux = T_PREFIX; $$->a2.i = 0x12345678; /* This is actually ok - T_PREFIX is special-cased. */ } | SOURCE { $$ = f_new_inst(); $$->aux = T_ENUM_RTS; $$->a2.i = OFFSETOF(struct rta, source); } - | SCOPE { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = OFFSETOF(struct rta, scope); } /* FIXME: want it read/write */ + | SCOPE { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = OFFSETOF(struct rta, scope); $$->a1.i = 1; } | CAST { $$ = f_new_inst(); $$->aux = T_ENUM_RTC; $$->a2.i = OFFSETOF(struct rta, cast); } | DEST { $$ = f_new_inst(); $$->aux = T_ENUM_RTD; $$->a2.i = OFFSETOF(struct rta, dest); } ; @@ -380,7 +379,7 @@ term: } } -/* FIXME rte.Preference - read/write */ + | PREFERENCE { $$ = f_new_inst(); $$->code = 'P'; } | rtadot static_attr { $$ = $2; $$->code = 'a'; } @@ -507,9 +506,21 @@ cmd: } | rtadot dynamic_attr '=' term ';' { $$ = $2; - $$->code = P('e','S'); + $$->code = P('e','S'); $$->a1.p = $4; } + | rtadot static_attr '=' term ';' { + $$ = $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'); + $$->a1.p = $3; + } | UNSET '(' rtadot dynamic_attr ')' ';' { $$ = $4; $$->aux = EAF_TYPE_UNDEF | EAF_TEMP; diff --git a/filter/filter.c b/filter/filter.c index e69e9e10..59b96588 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -412,6 +412,25 @@ interpret(struct f_inst *what) } } break; + case P('a','S'): + ONEARG; + if (what->aux != v1.type) + runtime( "Attempt to set static attribute to invalid type" ); + rta_cow(); + { + struct rta *rta = (*f_rte)->attrs; + switch (what->aux) { + case T_ENUM: + * ((char *) rta + what->a2.i) = v1.val.i; + break; + case T_IP: + * (ip_addr *) ((char *) rta + what->a2.i) = v1.val.px.ip; + break; + default: + bug( "Unknown type in set of static attribute" ); + } + } + break; case P('e','a'): /* Access to extended attributes */ { eattr *e = NULL; @@ -498,7 +517,17 @@ interpret(struct f_inst *what) } } break; - + case 'P': + res.type = T_INT; + res.val.i = (*f_rte)->pref; + break; + case P('P','S'): + ONEARG; + if (v1.type != T_INT) + runtime( "Can not set preference to non-integer" ); + *f_rte = rte_cow(*f_rte); + (*f_rte)->pref = v1.val.i; + break; case 'L': /* Get length of */ ONEARG; res.type = T_INT; @@ -661,8 +690,11 @@ i_same(struct f_inst *f1, struct f_inst *f2) 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;