]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Filter: Handle undefined BGP paths as empty
authorOndrej Zajicek (work) <santiago@crfreenet.org>
Wed, 3 Jan 2018 14:44:05 +0000 (15:44 +0100)
committerOndrej Zajicek (work) <santiago@crfreenet.org>
Wed, 3 Jan 2018 14:44:05 +0000 (15:44 +0100)
The same is already done for clists. Also fixes defined() to work
properly for paths and clists.

doc/bird.sgml
filter/filter.c

index c725081adc080b2991d08f3614d2b1bc79b170c1..3a2607b42a5c7277717ca1c095ea2014d402af08 100644 (file)
@@ -1498,8 +1498,8 @@ if 1234 = i then printn "."; else {
 like it accesses variables. Attempts to access undefined attribute result in a
 runtime error; you can check if an attribute is defined by using the
 <cf>defined( <m>attribute</m> )</cf> operator. One notable exception to this
-rule are attributes of clist type, where undefined value is regarded as empty
-clist for most purposes.
+rule are attributes of bgppath and *clist types, where undefined value is
+regarded as empty bgppath/*clist for most purposes.
 
 <descrip>
        <tag><label id="rta-net"><m/prefix/ net</tag>
index aef4f44af2799d3186728b091a284e228dd0791d..4e17f9746a23e2804c4f2fba1b41e5e21e2c8c43 100644 (file)
 
 void (*bt_assert_hook)(int result, struct f_inst *assert);
 
+static struct adata undef_adata;       /* adata of length 0 used for undefined */
+
+/* Special undef value for paths and clists */
+static inline int
+undef_value(struct f_val v)
+{
+  return ((v.type == T_PATH) || (v.type == T_CLIST) ||
+         (v.type == T_ECLIST) || (v.type == T_LCLIST)) &&
+    (v.val.ad == &undef_adata);
+}
+
 static struct adata *
 adata_empty(struct linpool *pool, int l)
 {
@@ -815,7 +826,7 @@ interpret(struct f_inst *what)
   case P('d','e'):
     ONEARG;
     res.type = T_BOOL;
-    res.val.i = (v1.type != T_VOID);
+    res.val.i = (v1.type != T_VOID) && !undef_value(v1);
     break;
   case 'T':
     ONEARG;
@@ -1001,24 +1012,31 @@ interpret(struct f_inst *what)
        e = ea_find((*f_rte)->attrs->eattrs, code);
 
       if (!e) {
-       /* A special case: undefined int_set looks like empty int_set */
+       /* A special case: undefined as_path looks like empty as_path */
+       if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_AS_PATH) {
+         res.type = T_PATH;
+         res.val.ad = &undef_adata;
+         break;
+       }
+
+       /* The same special case for int_set */
        if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_INT_SET) {
          res.type = T_CLIST;
-         res.val.ad = adata_empty(f_pool, 0);
+         res.val.ad = &undef_adata;
          break;
        }
 
        /* The same special case for ec_set */
        if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_EC_SET) {
          res.type = T_ECLIST;
-         res.val.ad = adata_empty(f_pool, 0);
+         res.val.ad = &undef_adata;
          break;
        }
 
        /* The same special case for lc_set */
        if ((what->aux & EAF_TYPE_MASK) == EAF_TYPE_LC_SET) {
          res.type = T_LCLIST;
-         res.val.ad = adata_empty(f_pool, 0);
+         res.val.ad = &undef_adata;
          break;
        }