Some fixes in filter code.
Thanks to Sergey Popovich for original patches.
This commit is contained in:
parent
70c5780535
commit
28a10f84cb
7 changed files with 85 additions and 58 deletions
121
filter/filter.c
121
filter/filter.c
|
@ -58,22 +58,6 @@ adata_empty(struct linpool *pool, int l)
|
||||||
return res;
|
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
|
static void
|
||||||
pm_format(struct f_path_mask *p, byte *buf, unsigned int size)
|
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
|
* @v1: first value
|
||||||
* @v2: second value
|
* @v2: second value
|
||||||
*
|
*
|
||||||
* Compares two values and returns -1, 0, 1 on <, =, > or 999 on error.
|
* Compares two values and returns -1, 0, 1 on <, =, > or CMP_ERROR on
|
||||||
* Tree module relies on this giving consistent results so that it can
|
* error. Tree module relies on this giving consistent results so
|
||||||
* build balanced trees.
|
* that it can be used for building balanced trees.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
val_compare(struct f_val v1, struct f_val v2)
|
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" );
|
debug( "Types do not match in val_compare\n" );
|
||||||
return CMP_ERROR;
|
return CMP_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (v1.type) {
|
switch (v1.type) {
|
||||||
|
case T_VOID:
|
||||||
|
return 0;
|
||||||
case T_ENUM:
|
case T_ENUM:
|
||||||
case T_INT:
|
case T_INT:
|
||||||
case T_BOOL:
|
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))
|
if (rc = ipa_compare(v1.val.px.ip, v2.val.px.ip))
|
||||||
return rc;
|
return rc;
|
||||||
return int_cmp(v1.val.px.len, v2.val.px.len);
|
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:
|
case T_STRING:
|
||||||
return strcmp(v1.val.s, v2.val.s);
|
return strcmp(v1.val.s, v2.val.s);
|
||||||
case T_VOID:
|
|
||||||
return 0;
|
|
||||||
default:
|
default:
|
||||||
debug( "Compare of unknown entities: %x\n", v1.type );
|
|
||||||
return CMP_ERROR;
|
return CMP_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
tree_compare(const void *p1, const void *p2)
|
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
|
void
|
||||||
|
@ -687,8 +714,15 @@ interpret(struct f_inst *what)
|
||||||
res.val.i = (x); \
|
res.val.i = (x); \
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case P('!','='): COMPARE(i!=0);
|
#define SAME(x) \
|
||||||
case P('=','='): COMPARE(i==0);
|
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 '<': COMPARE(i==-1);
|
||||||
case P('<','='): COMPARE(i!=1);
|
case P('<','='): COMPARE(i!=1);
|
||||||
|
|
||||||
|
@ -1379,33 +1413,12 @@ i_same(struct f_inst *f1, struct f_inst *f2)
|
||||||
A2_SAME;
|
A2_SAME;
|
||||||
}
|
}
|
||||||
break;
|
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()
|
case 'C':
|
||||||
also T_PATH, T_CLIST and T_ECLIST does not work,
|
if (!val_same(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a1.p))
|
||||||
but you cannot easily create such constants */
|
return 0;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'V':
|
case 'V':
|
||||||
if (strcmp((char *) f1->a2.p, (char *) f2->a2.p))
|
if (strcmp((char *) f1->a2.p, (char *) f2->a2.p))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -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 i_same(struct f_inst *f1, struct f_inst *f2);
|
||||||
|
|
||||||
int val_compare(struct f_val v1, struct f_val v2);
|
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);
|
void val_print(struct f_val v);
|
||||||
|
|
||||||
|
|
|
@ -282,6 +282,12 @@ string s;
|
||||||
# if 1 <= 1 then printn "."; else { print "*** FAIL: test 3"; }
|
# if 1 <= 1 then printn "."; else { print "*** FAIL: test 3"; }
|
||||||
if 1234 < 1234 then { print "*** FAIL: test 4"; quitbird; } else print "ok";
|
if 1234 < 1234 then { print "*** FAIL: test 4"; quitbird; } else print "ok";
|
||||||
is = [ 2, 3, 4, 7..11 ];
|
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 " 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 " 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");
|
print " must be true: ", true && true, ",", true || false, ",", ! false && ! false && true, ",", 1 < 2 && 1 != 3, ",", true && true && ! false, ",", true || 1+"a", ",", !(false && 1+"a");
|
||||||
|
|
|
@ -53,6 +53,11 @@ build_tree_rec(struct f_tree **buf, int l, int h)
|
||||||
return n;
|
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
|
* build_tree
|
||||||
|
|
|
@ -293,7 +293,7 @@ trie_print(struct f_trie *t)
|
||||||
logn("[");
|
logn("[");
|
||||||
if (t->zero)
|
if (t->zero)
|
||||||
{
|
{
|
||||||
logn("0.0.0.0/0");
|
logn("%I/%d", IPA_NONE, 0);
|
||||||
sep = ", ";
|
sep = ", ";
|
||||||
}
|
}
|
||||||
trie_node_print(&t->root, &sep);
|
trie_node_print(&t->root, &sep);
|
||||||
|
|
|
@ -405,6 +405,10 @@ struct adata {
|
||||||
byte data[0];
|
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 {
|
typedef struct ea_list {
|
||||||
struct ea_list *next; /* In case we have an override list */
|
struct ea_list *next; /* In case we have an override list */
|
||||||
byte flags; /* Flags: EALF_... */
|
byte flags; /* Flags: EALF_... */
|
||||||
|
|
|
@ -366,8 +366,7 @@ ea_same(ea_list *x, ea_list *y)
|
||||||
if (a->id != b->id ||
|
if (a->id != b->id ||
|
||||||
a->flags != b->flags ||
|
a->flags != b->flags ||
|
||||||
a->type != b->type ||
|
a->type != b->type ||
|
||||||
((a->type & EAF_EMBEDDED) ? a->u.data != b->u.data :
|
((a->type & EAF_EMBEDDED) ? a->u.data != b->u.data : !adata_same(a->u.ptr, b->u.ptr)))
|
||||||
(a->u.ptr->length != b->u.ptr->length || memcmp(a->u.ptr->data, b->u.ptr->data, a->u.ptr->length))))
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Reference in a new issue