]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
Some fixes in filter code.
authorOndrej Zajicek <santiago@crfreenet.org>
Wed, 2 Oct 2013 12:41:37 +0000 (14:41 +0200)
committerOndrej Zajicek <santiago@crfreenet.org>
Wed, 2 Oct 2013 12:41:37 +0000 (14:41 +0200)
Thanks to Sergey Popovich for original patches.

filter/filter.c
filter/filter.h
filter/test.conf
filter/tree.c
filter/trie.c
nest/route.h
nest/rt-attr.c

index 4198a408582e44d428a8992d969117737a04d368..50e3f403ae26b3f9b2edc71265cf56ed54e78694 100644 (file)
@@ -58,22 +58,6 @@ adata_empty(struct linpool *pool, int l)
   return res;
 }
 
-static int
-pm_path_compare(struct f_path_mask *m1, struct f_path_mask *m2)
-{
-  while (1) {
-    if ((!m1) || (!m2))
-      return !((!m1) && (!m2));
-
-    /* FIXME: buggy, should return -1, 0, 1; but it doesn't matter */
-    if ((m1->kind != m2->kind) || (m1->val != m2->val)) return 1;
-    m1 = m1->next;
-    m2 = m2->next;
-  }
-}
-
-u32 f_eval_asn(struct f_inst *expr);
-
 static void
 pm_format(struct f_path_mask *p, byte *buf, unsigned int size)
 {
@@ -135,9 +119,9 @@ u64_cmp(u64 i1, u64 i2)
  * @v1: first value
  * @v2: second value
  *
- * Compares two values and returns -1, 0, 1 on <, =, > or 999 on error.
- * Tree module relies on this giving consistent results so that it can
- * build balanced trees.
+ * Compares two values and returns -1, 0, 1 on <, =, > or CMP_ERROR on
+ * error. Tree module relies on this giving consistent results so
+ * that it can be used for building balanced trees.
  */
 int
 val_compare(struct f_val v1, struct f_val v2)
@@ -161,7 +145,10 @@ val_compare(struct f_val v1, struct f_val v2)
     debug( "Types do not match in val_compare\n" );
     return CMP_ERROR;
   }
+
   switch (v1.type) {
+  case T_VOID:
+    return 0;
   case T_ENUM:
   case T_INT:
   case T_BOOL:
@@ -177,22 +164,62 @@ val_compare(struct f_val v1, struct f_val v2)
     if (rc = ipa_compare(v1.val.px.ip, v2.val.px.ip))
       return rc;
     return int_cmp(v1.val.px.len, v2.val.px.len);
-  case T_PATH_MASK:
-    return pm_path_compare(v1.val.path_mask, v2.val.path_mask);
   case T_STRING:
     return strcmp(v1.val.s, v2.val.s);
-  case T_VOID:
-    return 0;
   default:
-    debug( "Compare of unknown entities: %x\n", v1.type );
     return CMP_ERROR;
   }
 }
 
-int 
-tree_compare(const void *p1, const void *p2)
+static int
+pm_path_same(struct f_path_mask *m1, struct f_path_mask *m2)
+{
+  while (m1 && m2)
+  {
+    if ((m1->kind != m2->kind) || (m1->val != m2->val))
+      return 0;
+
+    m1 = m1->next;
+    m2 = m2->next;
+  }
+
+ return !m1 && !m2;
+}
+
+/**
+ * val_same - compare two values
+ * @v1: first value
+ * @v2: second value
+ *
+ * Compares two values and returns 1 if they are same and 0 if not.
+ * Comparison of values of different types is valid and returns 0.
+ */
+int
+val_same(struct f_val v1, struct f_val v2)
 {
-  return val_compare((* (struct f_tree **) p1)->from, (* (struct f_tree **) p2)->from);
+  int rc;
+
+  rc = val_compare(v1, v2);
+  if (rc != CMP_ERROR)
+    return !rc;
+
+  if (v1.type != v2.type)
+    return 0;
+
+  switch (v1.type) {
+  case T_PATH_MASK:
+    return pm_path_same(v1.val.path_mask, v2.val.path_mask);
+  case T_PATH:
+  case T_CLIST:
+  case T_ECLIST:
+    return adata_same(v1.val.ad, v2.val.ad);
+  case T_SET:
+    return same_tree(v1.val.t, v2.val.t);
+  case T_PREFIX_SET:
+    return trie_same(v1.val.ti, v2.val.ti);
+  default:
+    bug("Invalid type in val_same(): %x", v1.type);
+  }
 }
 
 void
@@ -687,8 +714,15 @@ interpret(struct f_inst *what)
     res.val.i = (x); \
     break;
 
-  case P('!','='): COMPARE(i!=0);
-  case P('=','='): COMPARE(i==0);
+#define SAME(x) \
+    TWOARGS; \
+    i = val_same(v1, v2); \
+    res.type = T_BOOL; \
+    res.val.i = (x); \
+    break;
+
+  case P('!','='): SAME(!i);
+  case P('=','='): SAME(i);
   case '<': COMPARE(i==-1);
   case P('<','='): COMPARE(i!=1);
 
@@ -1379,33 +1413,12 @@ i_same(struct f_inst *f1, struct f_inst *f2)
       A2_SAME;
     }
     break;
-  case 'C': 
-    {
-      struct f_val *v1 = (struct f_val *) f1->a1.p;
-      struct f_val *v2 = (struct f_val *) f2->a1.p;
-
-      /* Handle some cases that are not handled by val_compare()
-         also T_PATH, T_CLIST and T_ECLIST does not work,
-         but you cannot easily create such constants */
-
-      if ((v1->type == T_SET) && (v2->type == T_SET))
-      {
-       if (!same_tree(v1->val.t, v2->val.t))
-         return 0;
-       break;
-      }
 
-      if ((v1->type == T_PREFIX_SET) && (v2->type == T_PREFIX_SET))
-      {
-       if (!trie_same(v1->val.ti, v2->val.ti))
-         return 0;
-       break;
-      }
-
-      if (val_compare(*v1 , *v2))
-       return 0;
-    }
+  case 'C':
+    if (!val_same(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a1.p))
+      return 0;
     break;
+
   case 'V': 
     if (strcmp((char *) f1->a2.p, (char *) f2->a2.p))
       return 0;
index dcac8253fe2896d282ff0b4e1c7d51000cfaab1a..5570a8a32de43f74c04238aec2463a871d8edddf 100644 (file)
@@ -116,7 +116,7 @@ int filter_same(struct filter *new, struct filter *old);
 int i_same(struct f_inst *f1, struct f_inst *f2);
 
 int val_compare(struct f_val v1, struct f_val v2);
-int tree_compare(const void *p1, const void *p2);
+int val_same(struct f_val v1, struct f_val v2);
 
 void val_print(struct f_val v);
 
index 048983b593afe2319c8c795ebcc8725d8a8baee7..b8f706cbaf69e1eb6a08583be7c4c44bbe4b7d9c 100644 (file)
@@ -282,6 +282,12 @@ string s;
 #      if 1 <= 1 then printn "."; else { print "*** FAIL: test 3"; }
        if 1234 < 1234 then { print "*** FAIL: test 4"; quitbird; } else print "ok";
        is = [ 2, 3, 4, 7..11 ];
+
+       print "must be true:  ", 1 = 1, " ", 1 != (0,1), " ", 1 != "a", " ", +empty+ = +empty+, " ", -empty- = -empty-, " ", --empty-- = --empty-- ,
+                       " ", [1,4..10,20] = [1,4..10,20] , " ", [ 10.0.0.0/8{ 15 , 17 } ] = [ 10.0.0.0/8{ 15 , 17 } ];
+       print "must be false: ", 1 != 1, " ", 1 = (0,1), " ", 1 = "a", " ", +empty+ = -empty-, " ", -empty- = --empty--, " ", --empty-- = +empty+ ,
+                       " ", [1,2] = [1,3], " ", [ 10.0.0.0/8{ 15 , 17 } ] = [ 11.0.0.0/8{ 15 , 17 } ];
+
        print "  must be true: ", 1.2.0.0/16 ~ [ 1.0.0.0/8{ 15 , 17 } ];
        print "  data types; must be true: ", 1.2.3.4 = 1.2.3.4, ",", 1 ~ [1,2,3], ",", 5 ~ [1..20], ",", 10 ~ is, ",", 2 ~ [ 1, 2, 3 ], ",", 5 ~ [ 4 .. 7 ], ",", 1.2.3.4 ~ [ 1.2.3.3..1.2.3.5 ], ",", 1.2.3.4 ~ 1.0.0.0/8, ",", 1.0.0.0/8 ~ 1.0.0.0/8, ",", 1.0.0.0/8 ~ [ 1.0.0.0/8+ ];
        print "  must be true: ", true && true, ",", true || false, ",", ! false && ! false && true, ",", 1 < 2 && 1 != 3, ",", true && true && ! false, ",", true || 1+"a", ",", !(false && 1+"a");
index f6ab75b4ab85dc95f06ffd8828e96f0eea1b2e8d..d27db18b7d90a02824050e61c2254c1c5eee37c5 100644 (file)
@@ -53,6 +53,11 @@ build_tree_rec(struct f_tree **buf, int l, int h)
   return n;
 }
 
+static int 
+tree_compare(const void *p1, const void *p2)
+{
+  return val_compare((* (struct f_tree **) p1)->from, (* (struct f_tree **) p2)->from);
+}
 
 /**
  * build_tree
index 581332c65c96895d3781dd1ab0120b6da8dc3719..f42afb84871a5aa882c2bf3539b5ef033a6a3ecc 100644 (file)
@@ -293,7 +293,7 @@ trie_print(struct f_trie *t)
   logn("[");
   if (t->zero)
     {
-      logn("0.0.0.0/0");
+      logn("%I/%d", IPA_NONE, 0);
       sep = ", ";
     }
   trie_node_print(&t->root, &sep);
index 35b5fa19335ff195ad09f04f3a7f787d646f3230..e0b88551545b4c0ea3ed74365f17169b7c358b63 100644 (file)
@@ -405,6 +405,10 @@ struct adata {
   byte data[0];
 };
 
+static inline int adata_same(struct adata *a, struct adata *b)
+{ return (a->length == b->length && !memcmp(a->data, b->data, a->length)); }
+
+
 typedef struct ea_list {
   struct ea_list *next;                        /* In case we have an override list */
   byte flags;                          /* Flags: EALF_... */
index 6aed318b1cf3ce41df2075ae852b86cb5d756cc2..3f79ee5949639a0a41723d67c14f56827ed7cc74 100644 (file)
@@ -366,8 +366,7 @@ ea_same(ea_list *x, ea_list *y)
       if (a->id != b->id ||
          a->flags != b->flags ||
          a->type != b->type ||
-         ((a->type & EAF_EMBEDDED) ? a->u.data != b->u.data :
-          (a->u.ptr->length != b->u.ptr->length || memcmp(a->u.ptr->data, b->u.ptr->data, a->u.ptr->length))))
+         ((a->type & EAF_EMBEDDED) ? a->u.data != b->u.data : !adata_same(a->u.ptr, b->u.ptr)))
        return 0;
     }
   return 1;