Rewrites static attribute filter code and adds ifname/ifindex attributes.
Thanks to Sergey Popovich for the original ifname/ifindex patch.
This commit is contained in:
parent
4df2019ebf
commit
a5fc59587f
4 changed files with 75 additions and 44 deletions
|
@ -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
|
from 0 to 255. Literals of this type are written like IPv4
|
||||||
addresses.
|
addresses.
|
||||||
|
|
||||||
<tag/string/ This is a string of characters. There are no ways to modify strings in
|
<tag/string/ This is a string of characters. There are no ways
|
||||||
filters. You can pass them between functions, assign them to variables of type <cf/string/, print
|
to modify strings in filters. You can pass them between
|
||||||
such variables, but you can't concatenate two strings. String literals
|
functions, assign them to variables of type <cf/string/,
|
||||||
are written as <cf/"This is a string constant"/.
|
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
|
<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>
|
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/.
|
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>
|
<tag><m/enum/ cast</tag>
|
||||||
|
|
||||||
Route type (Currently <cf/RTC_UNICAST/ for normal routes,
|
Route type (Currently <cf/RTC_UNICAST/ for normal routes,
|
||||||
<cf/RTC_BROADCAST/, <cf/RTC_MULTICAST/, <cf/RTC_ANYCAST/ will
|
<cf/RTC_BROADCAST/, <cf/RTC_MULTICAST/, <cf/RTC_ANYCAST/ will
|
||||||
be used in the future for broadcast, multicast and anycast
|
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
|
only to <cf/RTD_BLACKHOLE/, <cf/RTD_UNREACHABLE/ or
|
||||||
<cf/RTD_PROHIBIT/.
|
<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>
|
<tag><m/int/ igp_metric</tag>
|
||||||
The optional attribute that can be used to specify a distance
|
The optional attribute that can be used to specify a distance
|
||||||
to the network for routes that do not have a native protocol
|
to the network for routes that do not have a native protocol
|
||||||
|
|
|
@ -261,7 +261,8 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
||||||
SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST,
|
SET, STRING, BGPMASK, BGPPATH, CLIST, ECLIST,
|
||||||
IF, THEN, ELSE, CASE,
|
IF, THEN, ELSE, CASE,
|
||||||
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
|
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,
|
LEN,
|
||||||
DEFINED,
|
DEFINED,
|
||||||
ADD, DELETE, CONTAINS, RESET,
|
ADD, DELETE, CONTAINS, RESET,
|
||||||
|
@ -680,14 +681,16 @@ symbol:
|
||||||
}
|
}
|
||||||
|
|
||||||
static_attr:
|
static_attr:
|
||||||
FROM { $$ = f_new_inst(); $$->aux = T_IP; $$->a2.i = OFFSETOF(struct rta, from); $$->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 = OFFSETOF(struct rta, gw); $$->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 = 0x12345678; /* This is actually ok - T_PREFIX is special-cased. */ }
|
| NET { $$ = f_new_inst(); $$->aux = T_PREFIX; $$->a2.i = SA_NET; }
|
||||||
| PROTO { $$ = f_new_inst(); $$->aux = T_STRING; $$->a2.i = 0x12345678; /* T_STRING is also special-cased. */ }
|
| PROTO { $$ = f_new_inst(); $$->aux = T_STRING; $$->a2.i = SA_PROTO; }
|
||||||
| SOURCE { $$ = f_new_inst(); $$->aux = T_ENUM_RTS; $$->a2.i = OFFSETOF(struct rta, source); }
|
| SOURCE { $$ = f_new_inst(); $$->aux = T_ENUM_RTS; $$->a2.i = SA_SOURCE; }
|
||||||
| SCOPE { $$ = f_new_inst(); $$->aux = T_ENUM_SCOPE; $$->a2.i = OFFSETOF(struct rta, scope); $$->a1.i = 1; }
|
| 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 = OFFSETOF(struct rta, cast); }
|
| CAST { $$ = f_new_inst(); $$->aux = T_ENUM_RTC; $$->a2.i = SA_CAST; }
|
||||||
| DEST { $$ = f_new_inst(); $$->aux = T_ENUM_RTD; $$->a2.i = OFFSETOF(struct rta, dest); $$->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; }
|
||||||
;
|
;
|
||||||
|
|
||||||
term:
|
term:
|
||||||
|
|
|
@ -824,24 +824,23 @@ interpret(struct f_inst *what)
|
||||||
ACCESS_RTE;
|
ACCESS_RTE;
|
||||||
struct rta *rta = (*f_rte)->attrs;
|
struct rta *rta = (*f_rte)->attrs;
|
||||||
res.type = what->aux;
|
res.type = what->aux;
|
||||||
switch(res.type) {
|
|
||||||
case T_IP:
|
switch (what->a2.i)
|
||||||
res.val.px.ip = * (ip_addr *) ((char *) rta + what->a2.i);
|
{
|
||||||
break;
|
case SA_FROM: res.val.px.ip = rta->from; break;
|
||||||
case T_ENUM:
|
case SA_GW: res.val.px.ip = rta->gw; break;
|
||||||
res.val.i = * ((char *) rta + what->a2.i);
|
case SA_NET: res.val.px.ip = (*f_rte)->net->n.prefix;
|
||||||
break;
|
res.val.px.len = (*f_rte)->net->n.pxlen; break;
|
||||||
case T_STRING: /* Warning: this is a special case for proto attribute */
|
case SA_PROTO: res.val.s = rta->proto->name; break;
|
||||||
res.val.s = rta->proto->name;
|
case SA_SOURCE: res.val.i = rta->source; break;
|
||||||
break;
|
case SA_SCOPE: res.val.i = rta->scope; break;
|
||||||
case T_PREFIX: /* Warning: this works only for prefix of network */
|
case SA_CAST: res.val.i = rta->cast; break;
|
||||||
{
|
case SA_DEST: res.val.i = rta->dest; break;
|
||||||
res.val.px.ip = (*f_rte)->net->n.prefix;
|
case SA_IFNAME: res.val.s = rta->iface ? rta->iface->name : ""; break;
|
||||||
res.val.px.len = (*f_rte)->net->n.pxlen;
|
case SA_IFINDEX: res.val.i = rta->iface ? rta->iface->index : 0; break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
bug( "Invalid type for rta access (%x)", res.type );
|
bug("Invalid static attribute access (%x)", res.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -850,19 +849,20 @@ interpret(struct f_inst *what)
|
||||||
ONEARG;
|
ONEARG;
|
||||||
if (what->aux != v1.type)
|
if (what->aux != v1.type)
|
||||||
runtime( "Attempt to set static attribute to incompatible type" );
|
runtime( "Attempt to set static attribute to incompatible type" );
|
||||||
|
|
||||||
f_rta_cow();
|
f_rta_cow();
|
||||||
{
|
{
|
||||||
struct rta *rta = (*f_rte)->attrs;
|
struct rta *rta = (*f_rte)->attrs;
|
||||||
ip_addr ip;
|
|
||||||
|
|
||||||
switch (what->aux) {
|
switch (what->a2.i)
|
||||||
|
{
|
||||||
|
case SA_FROM:
|
||||||
|
rta->from = v1.val.px.ip;
|
||||||
|
break;
|
||||||
|
|
||||||
case T_IP:
|
case SA_GW:
|
||||||
ip = v1.val.px.ip;
|
|
||||||
|
|
||||||
/* "gw" attribute? */
|
|
||||||
if (what->a2.i == OFFSETOF(struct rta, gw))
|
|
||||||
{
|
{
|
||||||
|
ip_addr ip = v1.val.px.ip;
|
||||||
neighbor *n = neigh_find(rta->proto, &ip, 0);
|
neighbor *n = neigh_find(rta->proto, &ip, 0);
|
||||||
if (!n || (n->scope == SCOPE_HOST))
|
if (!n || (n->scope == SCOPE_HOST))
|
||||||
runtime( "Invalid gw address" );
|
runtime( "Invalid gw address" );
|
||||||
|
@ -873,16 +873,13 @@ interpret(struct f_inst *what)
|
||||||
rta->nexthops = NULL;
|
rta->nexthops = NULL;
|
||||||
rta->hostentry = NULL;
|
rta->hostentry = NULL;
|
||||||
}
|
}
|
||||||
else /* or "from" attribute? */
|
|
||||||
rta->from = ip;
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_ENUM_SCOPE:
|
case SA_SCOPE:
|
||||||
rta->scope = v1.val.i;
|
rta->scope = v1.val.i;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case T_ENUM_RTD:
|
case SA_DEST:
|
||||||
i = v1.val.i;
|
i = v1.val.i;
|
||||||
if ((i != RTD_BLACKHOLE) && (i != RTD_UNREACHABLE) && (i != RTD_PROHIBIT))
|
if ((i != RTD_BLACKHOLE) && (i != RTD_UNREACHABLE) && (i != RTD_PROHIBIT))
|
||||||
runtime( "Destination can be changed only to blackhole, unreachable or prohibit" );
|
runtime( "Destination can be changed only to blackhole, unreachable or prohibit" );
|
||||||
|
@ -895,7 +892,7 @@ interpret(struct f_inst *what)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
bug( "Unknown type in set of static attribute" );
|
bug("Invalid static attribute access (%x)", res.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -172,6 +172,19 @@ void val_print(struct f_val v);
|
||||||
#define T_SET 0x80
|
#define T_SET 0x80
|
||||||
#define T_PREFIX_SET 0x81
|
#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 {
|
||||||
struct f_tree *left, *right;
|
struct f_tree *left, *right;
|
||||||
struct f_val from, to;
|
struct f_val from, to;
|
||||||
|
|
Loading…
Reference in a new issue