diff options
Diffstat (limited to 'filter/filter.c')
-rw-r--r-- | filter/filter.c | 121 |
1 files changed, 67 insertions, 54 deletions
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) +{ + 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; |