diff --git a/filter/filter.c b/filter/filter.c index 4198a408..50e3f403 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -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) { - return val_compare((* (struct f_tree **) p1)->from, (* (struct f_tree **) p2)->from); + 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) +{ + 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; diff --git a/filter/filter.h b/filter/filter.h index dcac8253..5570a8a3 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -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); diff --git a/filter/test.conf b/filter/test.conf index 048983b5..b8f706cb 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -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"); diff --git a/filter/tree.c b/filter/tree.c index f6ab75b4..d27db18b 100644 --- a/filter/tree.c +++ b/filter/tree.c @@ -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 diff --git a/filter/trie.c b/filter/trie.c index 581332c6..f42afb84 100644 --- a/filter/trie.c +++ b/filter/trie.c @@ -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); diff --git a/nest/route.h b/nest/route.h index 35b5fa19..e0b88551 100644 --- a/nest/route.h +++ b/nest/route.h @@ -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_... */ diff --git a/nest/rt-attr.c b/nest/rt-attr.c index 6aed318b..3f79ee59 100644 --- a/nest/rt-attr.c +++ b/nest/rt-attr.c @@ -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;