]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Rewrites static attribute filter code and adds ifname/ifindex attributes.
authorOndrej Zajicek <santiago@crfreenet.org>
Thu, 26 Sep 2013 20:08:21 +0000 (22:08 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Thu, 26 Sep 2013 20:08:21 +0000 (22:08 +0200)
Thanks to Sergey Popovich for the original ifname/ifindex patch.

doc/bird.sgml
filter/config.Y
filter/filter.c
filter/filter.h

index b3f6a85cf53e12760f146022547126aa4685fe41..f43eb4bf4d7b2edfe9bf1bb060443fbb304a5629 100644 (file)
@@ -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/=, !=, &lt;, &gt;, &lt;=, &gt;=/), but
+         you can't concatenate two strings. String literals are
+         written as <cf/"This is a string constant"/. Additionaly
+         matching <cf/&tilde;/ 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
index 6623405078283f9a7cee031ab799790a49e23b46..04acfbabeee78df72c4a403aa4e48ade704ebbe3 100644 (file)
@@ -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:
index 1f0905284a6717dd01777d044bbb4d56f80d495b..0fc10f1f1281c15652856a7d282d39238df7e667 100644 (file)
@@ -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;
index 1d5150e72c01d2c16a0f8820f0779d042ed59173..dcac8253fe2896d282ff0b4e1c7d51000cfaab1a 100644 (file)
@@ -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;