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 | |
parent | 4df2019ebfc0f77feb16b6a33dea6d5ac595f55e (diff) |
Rewrites static attribute filter code and adds ifname/ifindex attributes.
Thanks to Sergey Popovich for the original ifname/ifindex patch.
-rw-r--r-- | doc/bird.sgml | 28 | ||||
-rw-r--r-- | filter/config.Y | 21 | ||||
-rw-r--r-- | filter/filter.c | 57 | ||||
-rw-r--r-- | filter/filter.h | 13 |
4 files changed, 75 insertions, 44 deletions
diff --git a/doc/bird.sgml b/doc/bird.sgml index b3f6a85c..f43eb4bf 100644 --- a/doc/bird.sgml +++ b/doc/bird.sgml @@ -928,10 +928,16 @@ incompatible with each other (that is to prevent you from shooting in the foot). from 0 to 255. Literals of this type are written like IPv4 addresses. - <tag/string/ This is a string of characters. There are no ways to modify strings in - filters. You can pass them between functions, assign them to variables of type <cf/string/, print - such variables, but you can't concatenate two strings. String literals - are written as <cf/"This is a string constant"/. + <tag/string/ This is a string of characters. There are no ways + to modify strings in filters. You can pass them between + functions, assign them to variables of type <cf/string/, + print such variables, use standard string comparison + operations (e.g. <cf/=, !=, <, >, <=, >=/), but + you can't concatenate two strings. String literals are + written as <cf/"This is a string constant"/. Additionaly + matching <cf/˜/ operator could be used to match a + string value against a shell pattern (represented also as a + string). <tag/ip/ This type can hold a single IP address. Depending on the compile-time configuration of BIRD you are using, it is either an IPv4 or IPv6 address. IP addresses are written in the standard notation (<cf/10.20.30.40/ or <cf/fec0:3:4::1/). You can apply special operator <cf>.mask(<M>num</M>)</cf> @@ -1194,7 +1200,6 @@ undefined value is regarded as empty clist for most purposes. what protocol has told me about this route. Possible values: <cf/RTS_DUMMY/, <cf/RTS_STATIC/, <cf/RTS_INHERIT/, <cf/RTS_DEVICE/, <cf/RTS_STATIC_DEVICE/, <cf/RTS_REDIRECT/, <cf/RTS_RIP/, <cf/RTS_OSPF/, <cf/RTS_OSPF_IA/, <cf/RTS_OSPF_EXT1/, <cf/RTS_OSPF_EXT2/, <cf/RTS_BGP/, <cf/RTS_PIPE/. <tag><m/enum/ cast</tag> - Route type (Currently <cf/RTC_UNICAST/ for normal routes, <cf/RTC_BROADCAST/, <cf/RTC_MULTICAST/, <cf/RTC_ANYCAST/ will be used in the future for broadcast, multicast and anycast @@ -1212,6 +1217,19 @@ undefined value is regarded as empty clist for most purposes. only to <cf/RTD_BLACKHOLE/, <cf/RTD_UNREACHABLE/ or <cf/RTD_PROHIBIT/. + <tag><m/string/ ifname</tag> + Name of the outgoing interface. Sink routes (like blackhole, + unreachable or prohibit) and multipath routes have no interface + associated with them, so <cf/ifname/ returns an empty string for + such routes. Read-only. + + <tag><m/int/ ifindex</tag> + Index of the outgoing interface. System wide index of the + interface. May be used for interface matching, however + indexes might change on interface creation/removal. Zero is + returned for routes with undefined outgoing + interfaces. Read-only. + <tag><m/int/ igp_metric</tag> The optional attribute that can be used to specify a distance to the network for routes that do not have a native protocol 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; |