diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2013-09-26 22:08:21 +0200 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2013-09-26 22:08:21 +0200 |
commit | a5fc59587fe864e4fcfb44eb3be57231b4ca339b (patch) | |
tree | 8c9459d5a432e85e8a3febb0c42fa6674fede9df /filter | |
parent | 4df2019ebfc0f77feb16b6a33dea6d5ac595f55e (diff) |
Rewrites static attribute filter code and adds ifname/ifindex attributes.
Thanks to Sergey Popovich for the original ifname/ifindex patch.
Diffstat (limited to 'filter')
-rw-r--r-- | filter/config.Y | 21 | ||||
-rw-r--r-- | filter/filter.c | 57 | ||||
-rw-r--r-- | filter/filter.h | 13 |
3 files changed, 52 insertions, 39 deletions
diff --git a/filter/config.Y b/filter/config.Y index 66234050..04acfbab 100644 --- a/filter/config.Y +++ b/filter/config.Y @@ -261,7 +261,8 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN, SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST, IF, THEN, ELSE, CASE, TRUE, FALSE, RT, RO, UNKNOWN, GENERIC, - FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, PREFERENCE, + FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, IFNAME, IFINDEX, + PREFERENCE, LEN, DEFINED, ADD, DELETE, CONTAINS, RESET, @@ -680,14 +681,16 @@ symbol: } static_attr: - 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); $$->a1.i = 1; } - | NET { $$ = f_new_inst(); $$->aux = T_PREFIX; $$->a2.i = 0x12345678; /* This is actually ok - T_PREFIX is special-cased. */ } - | PROTO { $$ = f_new_inst(); $$->aux = T_STRING; $$->a2.i = 0x12345678; /* T_STRING is also 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); $$->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); $$->a1.i = 1; } + 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_PREFIX; $$->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; } + | CAST { $$ = f_new_inst(); $$->aux = T_ENUM_RTC; $$->a2.i = SA_CAST; } + | 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; } ; term: diff --git a/filter/filter.c b/filter/filter.c index 1f090528..0fc10f1f 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -824,24 +824,23 @@ interpret(struct f_inst *what) ACCESS_RTE; struct rta *rta = (*f_rte)->attrs; res.type = what->aux; - switch(res.type) { - case T_IP: - res.val.px.ip = * (ip_addr *) ((char *) rta + what->a2.i); - break; - case T_ENUM: - res.val.i = * ((char *) rta + what->a2.i); - break; - case T_STRING: /* Warning: this is a special case for proto attribute */ - res.val.s = rta->proto->name; - break; - case T_PREFIX: /* Warning: this works only for prefix of network */ - { - res.val.px.ip = (*f_rte)->net->n.prefix; - res.val.px.len = (*f_rte)->net->n.pxlen; - break; - } + + switch (what->a2.i) + { + case SA_FROM: res.val.px.ip = rta->from; break; + case SA_GW: res.val.px.ip = rta->gw; break; + case SA_NET: res.val.px.ip = (*f_rte)->net->n.prefix; + res.val.px.len = (*f_rte)->net->n.pxlen; break; + case SA_PROTO: res.val.s = rta->proto->name; break; + case SA_SOURCE: res.val.i = rta->source; break; + case SA_SCOPE: res.val.i = rta->scope; break; + case SA_CAST: res.val.i = rta->cast; break; + case SA_DEST: res.val.i = rta->dest; break; + case SA_IFNAME: res.val.s = rta->iface ? rta->iface->name : ""; break; + case SA_IFINDEX: res.val.i = rta->iface ? rta->iface->index : 0; break; + default: - bug( "Invalid type for rta access (%x)", res.type ); + bug("Invalid static attribute access (%x)", res.type); } } break; @@ -850,19 +849,20 @@ interpret(struct f_inst *what) ONEARG; if (what->aux != v1.type) runtime( "Attempt to set static attribute to incompatible type" ); + f_rta_cow(); { struct rta *rta = (*f_rte)->attrs; - ip_addr ip; - - switch (what->aux) { - case T_IP: - ip = v1.val.px.ip; + switch (what->a2.i) + { + case SA_FROM: + rta->from = v1.val.px.ip; + break; - /* "gw" attribute? */ - if (what->a2.i == OFFSETOF(struct rta, gw)) + case SA_GW: { + ip_addr ip = v1.val.px.ip; neighbor *n = neigh_find(rta->proto, &ip, 0); if (!n || (n->scope == SCOPE_HOST)) runtime( "Invalid gw address" ); @@ -873,16 +873,13 @@ interpret(struct f_inst *what) rta->nexthops = NULL; rta->hostentry = NULL; } - else /* or "from" attribute? */ - rta->from = ip; - break; - case T_ENUM_SCOPE: + case SA_SCOPE: rta->scope = v1.val.i; break; - case T_ENUM_RTD: + case SA_DEST: i = v1.val.i; if ((i != RTD_BLACKHOLE) && (i != RTD_UNREACHABLE) && (i != RTD_PROHIBIT)) runtime( "Destination can be changed only to blackhole, unreachable or prohibit" ); @@ -895,7 +892,7 @@ interpret(struct f_inst *what) break; default: - bug( "Unknown type in set of static attribute" ); + bug("Invalid static attribute access (%x)", res.type); } } break; diff --git a/filter/filter.h b/filter/filter.h index 1d5150e7..dcac8253 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -172,6 +172,19 @@ void val_print(struct f_val v); #define T_SET 0x80 #define T_PREFIX_SET 0x81 + +#define SA_FROM 1 +#define SA_GW 2 +#define SA_NET 3 +#define SA_PROTO 4 +#define SA_SOURCE 5 +#define SA_SCOPE 6 +#define SA_CAST 7 +#define SA_DEST 8 +#define SA_IFNAME 9 +#define SA_IFINDEX 10 + + struct f_tree { struct f_tree *left, *right; struct f_val from, to; |