summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--filter/config.Y25
-rw-r--r--filter/filter.c34
2 files changed, 51 insertions, 8 deletions
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;