diff options
-rw-r--r-- | filter/filter.c | 113 | ||||
-rw-r--r-- | filter/filter.h | 3 | ||||
-rw-r--r-- | filter/test.conf | 2 | ||||
-rw-r--r-- | filter/tree.c | 20 |
4 files changed, 115 insertions, 23 deletions
diff --git a/filter/filter.c b/filter/filter.c index 558ee61..103710e 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -28,25 +28,6 @@ struct f_inst *startup_func = NULL; -#define runtime(x) do { \ - log( L_ERR x ); \ - res.type = T_RETURN; \ - res.val.i = F_ERROR; \ - return res; \ - } while(0) - -#define ARG(x,y) \ - x = interpret(what->y); \ - if (x.type == T_RETURN) \ - return x; - -#define ONEARG ARG(v1, a1.p) -#define TWOARGS ARG(v1, a1.p) \ - ARG(v2, a2.p) -#define TWOARGS_C TWOARGS \ - if (v1.type != v2.type) \ - runtime( "Can not operate with values of incompatible types" ); - #define CMP_ERROR 999 /* Compare two values, returns -1, 0, 1 compared, ERROR 999 */ @@ -160,7 +141,24 @@ val_print(struct f_val v) static struct rte **f_rte, *f_rte_old; static struct linpool *f_pool; -static struct f_val interpret(struct f_inst *what); +#define runtime(x) do { \ + log( L_ERR x ); \ + res.type = T_RETURN; \ + res.val.i = F_ERROR; \ + return res; \ + } while(0) + +#define ARG(x,y) \ + x = interpret(what->y); \ + if (x.type == T_RETURN) \ + return x; + +#define ONEARG ARG(v1, a1.p) +#define TWOARGS ARG(v1, a1.p) \ + ARG(v2, a2.p) +#define TWOARGS_C TWOARGS \ + if (v1.type != v2.type) \ + runtime( "Can not operate with values of incompatible types" ); static struct f_val interpret(struct f_inst *what) @@ -412,6 +410,77 @@ interpret(struct f_inst *what) return res; } +#define ARG(x,y) \ + if (!i_same(f1->y, f2->y)) \ + return 0; + +#define ONEARG ARG(v1, a1.p) +#define TWOARGS ARG(v1, a1.p) \ + ARG(v2, a2.p) + +#define A2_SAME if (f1->a2.i != f2->a2.i) return 0; + +int +i_same(struct f_inst *f1, struct f_inst *f2) +{ + if (!f1) + return 1; + if ((!!f1) != (!!f2)) + return 0; + if (f1->aux != f2->aux) + return 0; + if (f1->code != f2->code) + return 0; + + switch(f1->code) { + case ',': /* fall through */ + case '+': + case '/': + case '!=': + case '==': + case '<': + case '<=': TWOARGS; break; + + case '~': TWOARGS; break; + case 'de': ONEARG; break; + + case 's': + ARG(v2, a2.p); + { + struct symbol *s1, *s2; + s1 = f1->a1.p; + s2 = f2->a1.p; + if (strcmp(s1->name, s2->name)) + return 0; + if (s1->class != s2->class) + return 0; + } + break; + + case 'c': A2_SAME; break; + case 'C': + if (val_compare(* (struct f_val *) f1->a1.p, * (struct f_val *) f2->a2.p)) + return 0; + break; + case 'p': ONEARG; break; + case '?': TWOARGS; break; + case '0': break; + case 'p,': ONEARG; A2_SAME; break; + case 'a': A2_SAME; break; + case 'ea': A2_SAME; break; + case 'eS': ONEARG; A2_SAME; break; + + case 'cp': ONEARG; break; + case 'ca': /* CALL, FIXME: exponential in some cases */ + ONEARG; if (!i_same(f1->a2.p, f2->a2.p)) return 0; break; + case 'SW': ONEARG; if (!same_tree(f1->a2.p, f2->a2.p)) return 0; break; + case 'iM': TWOARGS; break; + default: + bug( "Unknown instruction %d in same (%c)", f1->code, f1->code & 0xff); + } + return i_same(f1->next, f2->next); +} + /* FIXME: tmp_attrs is unreferenced. That can't be right */ int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool) @@ -432,6 +501,7 @@ f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struc } + void filters_postconfig(void) { @@ -448,6 +518,5 @@ filters_postconfig(void) int filter_same(struct filter *new, struct filter *old) { - /* FIXME: This has to be defined! */ - return new == old; + return i_same(new->root, old->root); } diff --git a/filter/filter.h b/filter/filter.h index 2fe6653..ace72e4 100644 --- a/filter/filter.h +++ b/filter/filter.h @@ -61,6 +61,7 @@ struct f_tree *f_new_tree(void); struct f_tree *build_tree(struct f_tree *); struct f_tree *find_tree(struct f_tree *t, struct f_val val); +int same_tree(struct f_tree *t1, struct f_tree *t2); struct ea_list; struct rte; @@ -69,6 +70,8 @@ int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, s char *filter_name(struct filter *filter); 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); void val_print(struct f_val v); diff --git a/filter/test.conf b/filter/test.conf index e2da6d7..616dbc5 100644 --- a/filter/test.conf +++ b/filter/test.conf @@ -42,7 +42,7 @@ ip p; print " data types: must be false: " 1 ~ [ 2, 3, 4 ] "," 5 ~ [ 2, 3, 4, 7..11 ] "," 1.2.3.4 ~ [ 1.2.3.3, 1.2.3.5 ] "," (1,2) > (2,2) "," (1,1) > (1,1) "," 1.0.0.0/8 ~ [ 1.0.0.0/8- ] "," 1.2.0.0/17 ~ [ 1.0.0.0/8{ 15 , 16 } ]; px = 1.2.0.0/18; - print "Testing prefixes: 1.0.0.0/18 = " px; + print "Testing prefixes: 1.2.0.0/18 = " px; p = 127.1.2.3; print "Testing mask : 127.0.0.0 = " p.mask(8); print "Testing pairs: (1,2) = " (1,2); diff --git a/filter/tree.c b/filter/tree.c index 43888f0..5e57bb7 100644 --- a/filter/tree.c +++ b/filter/tree.c @@ -123,3 +123,23 @@ f_new_tree(void) ret->data = NULL; return ret; } + +int +same_tree(struct f_tree *t1, struct f_tree *t2) +{ + if ((!!t1) != (!!t2)) + return 0; + if (!t1) + return 1; + if (val_compare(t1->from, t2->from)) + return 0; + if (val_compare(t1->to, t2->to)) + return 0; + if (!same_tree(t1->left, t2->left)) + return 0; + if (!same_tree(t1->right, t2->right)) + return 0; + if (!i_same(t1->data, t2->data)) + return 0; + return 1; +} |