summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--filter/filter.c113
-rw-r--r--filter/filter.h3
-rw-r--r--filter/test.conf2
-rw-r--r--filter/tree.c20
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;
+}