summaryrefslogtreecommitdiff
path: root/filter
diff options
context:
space:
mode:
Diffstat (limited to 'filter')
-rw-r--r--filter/config.Y16
-rw-r--r--filter/filter.c36
-rw-r--r--filter/test.conf12
-rw-r--r--filter/tree.c8
4 files changed, 53 insertions, 19 deletions
diff --git a/filter/config.Y b/filter/config.Y
index 3e70a63e..3eb5b08f 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -618,16 +618,17 @@ bgp_path:
;
bgp_path_tail1:
- NUM bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN; $$->val = $1; }
- | '*' bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASTERISK; $$->val = 0; }
- | '?' bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_QUESTION; $$->val = 0; }
- | bgp_path_expr bgp_path_tail1 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN_EXPR; $$->val = (uintptr_t) $1; }
- | { $$ = NULL; }
+ NUM bgp_path_tail1 { $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN; $$->val = $1; }
+ | NUM DDOT NUM bgp_path_tail1 { $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $4; $$->kind = PM_ASN_RANGE; $$->val = $1; $$->val2 = $3; }
+ | '*' bgp_path_tail1 { $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASTERISK; }
+ | '?' bgp_path_tail1 { $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_QUESTION; }
+ | bgp_path_expr bgp_path_tail1 { $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN_EXPR; $$->val = (uintptr_t) $1; }
+ | { $$ = NULL; }
;
bgp_path_tail2:
- NUM bgp_path_tail2 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN; $$->val = $1; }
- | '?' bgp_path_tail2 { $$ = cfg_alloc(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASTERISK; $$->val = 0; }
+ NUM bgp_path_tail2 { $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASN; $$->val = $1; }
+ | '?' bgp_path_tail2 { $$ = cfg_allocz(sizeof(struct f_path_mask)); $$->next = $2; $$->kind = PM_ASTERISK; }
| { $$ = NULL; }
;
@@ -725,6 +726,7 @@ term:
| term '>' term { $$ = f_new_inst(); $$->code = '<'; $$->a1.p = $3; $$->a2.p = $1; }
| term GEQ term { $$ = f_new_inst(); $$->code = P('<','='); $$->a1.p = $3; $$->a2.p = $1; }
| term '~' term { $$ = f_new_inst(); $$->code = '~'; $$->a1.p = $1; $$->a2.p = $3; }
+ | term NMA term { $$ = f_new_inst(); $$->code = P('!','~'); $$->a1.p = $1; $$->a2.p = $3; }
| '!' term { $$ = f_new_inst(); $$->code = '!'; $$->a1.p = $2; }
| DEFINED '(' term ')' { $$ = f_new_inst(); $$->code = P('d','e'); $$->a1.p = $3; }
diff --git a/filter/filter.c b/filter/filter.c
index 7b3e550f..3282bd50 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -81,6 +81,10 @@ pm_format(struct f_path_mask *p, buffer *buf)
buffer_puts(buf, "* ");
break;
+ case PM_ASN_RANGE:
+ buffer_print(buf, "%u..%u ", p->val, p->val2);
+ break;
+
case PM_ASN_EXPR:
buffer_print(buf, "%u ", f_eval_asn((struct f_inst *) p->val));
break;
@@ -146,18 +150,29 @@ val_compare(struct f_val v1, struct f_val v2)
}
static int
-pm_path_same(struct f_path_mask *m1, struct f_path_mask *m2)
+pm_same(struct f_path_mask *m1, struct f_path_mask *m2)
{
while (m1 && m2)
{
- if ((m1->kind != m2->kind) || (m1->val != m2->val))
+ if (m1->kind != m2->kind)
return 0;
+ if (m1->kind == PM_ASN_EXPR)
+ {
+ if (!i_same((struct f_inst *) m1->val, (struct f_inst *) m2->val))
+ return 0;
+ }
+ else
+ {
+ if ((m1->val != m2->val) || (m1->val2 != m2->val2))
+ return 0;
+ }
+
m1 = m1->next;
m2 = m2->next;
}
- return !m1 && !m2;
+ return !m1 && !m2;
}
/**
@@ -182,7 +197,7 @@ val_same(struct f_val v1, struct f_val v2)
switch (v1.type) {
case T_PATH_MASK:
- return pm_path_same(v1.val.path_mask, v2.val.path_mask);
+ return pm_same(v1.val.path_mask, v2.val.path_mask);
case T_PATH:
case T_CLIST:
case T_ECLIST:
@@ -673,6 +688,16 @@ interpret(struct f_inst *what)
runtime( "~ applied on unknown type pair" );
res.val.i = !!res.val.i;
break;
+
+ case P('!','~'):
+ TWOARGS;
+ res.type = T_BOOL;
+ res.val.i = val_in_range(v1, v2);
+ if (res.val.i == CMP_ERROR)
+ runtime( "!~ applied on unknown type pair" );
+ res.val.i = !res.val.i;
+ break;
+
case P('d','e'):
ONEARG;
res.type = T_BOOL;
@@ -1415,7 +1440,8 @@ i_same(struct f_inst *f1, struct f_inst *f2)
case P('A','p'): TWOARGS; break;
case P('C','a'): TWOARGS; break;
case P('a','f'):
- case P('a','l'): ONEARG; break;
+ case P('a','l'):
+ case P('a','L'): ONEARG; break;
#if 0
case P('R','C'):
TWOARGS;
diff --git a/filter/test.conf b/filter/test.conf
index 5cafe551..a8c3a508 100644
--- a/filter/test.conf
+++ b/filter/test.conf
@@ -96,22 +96,28 @@ clist l2;
eclist el;
eclist el2;
{
+ print "Entering path test...";
pm1 = / 4 3 2 1 /;
- pm2 = [= 4 3 2 1 =];
+ pm2 = [= 3..6 3 2 1..2 =];
print "Testing path masks: ", pm1, " ", pm2;
p2 = prepend( + empty +, 1 );
p2 = prepend( p2, 2 );
p2 = prepend( p2, 3 );
p2 = prepend( p2, 4 );
- print "Testing paths: ", p2;
+ print "Testing path: (4 3 2 1) = ", p2;
print "Should be true: ", p2 ~ pm1, " ", p2 ~ pm2, " ", 3 ~ p2, " ", p2 ~ [2, 10..20], " ", p2 ~ [4, 10..20];
print "4 = ", p2.len;
p2 = prepend( p2, 5 );
- print "Should be false: ", p2 ~ pm1, " ", p2 ~ pm2, " ", 10 ~ p2, " ", p2 ~ [8, ten..(2*ten)];
+ print "Testing path: (5 4 3 2 1) = ", p2;
+ print "Should be false: ", p2 ~ pm1, " ", p2 ~ pm2, " ", 10 ~ p2, " ", p2 ~ [8, ten..(2*ten)], " ", p2 ~ [= 1..4 4 3 2 1 =], " ", p2 ~ [= 5 4 4..100 2 1 =];
print "Should be true: ", p2 ~ / ? 4 3 2 1 /, " ", p2, " ", / ? 4 3 2 1 /;
print "Should be true: ", p2 ~ [= * 4 3 * 1 =], " ", p2, " ", [= * 4 3 * 1 =];
+ print "Should be true: ", p2 ~ [= 5..6 4..10 1..3 1..3 1..65536 =];
print "Should be true: ", p2 ~ [= (3+2) (2*2) 3 2 1 =], " ", p2 ~ mkpath(5, 4);
print "Should be true: ", p2.len = 5, " ", p2.first = 5, " ", p2.last = 1;
+ print "Should be true: ", pm1 = [= 4 3 2 1 =], " ", pm1 != [= 4 3 1 2 =], " ",
+ pm2 = [= 3..6 3 2 1..2 =], " ", pm2 != [= 3..6 3 2 1..3 =], " ",
+ [= 1 2 (1+2) =] = [= 1 2 (1+2) =], " ", [= 1 2 (1+2) =] != [= 1 2 (2+1) =];
print "5 = ", p2.len;
print "Delete 3: ", delete(p2, 3);
print "Filter 1-3: ", filter(p2, [1..3]);
diff --git a/filter/tree.c b/filter/tree.c
index ee9f448a..328c7184 100644
--- a/filter/tree.c
+++ b/filter/tree.c
@@ -82,7 +82,7 @@ build_tree(struct f_tree *from)
if (len <= 1024)
buf = alloca(len * sizeof(struct f_tree *));
else
- buf = malloc(len * sizeof(struct f_tree *));
+ buf = xmalloc(len * sizeof(struct f_tree *));
/* Convert a degenerated tree into an sorted array */
i = 0;
@@ -94,7 +94,7 @@ build_tree(struct f_tree *from)
root = build_tree_rec(buf, 0, len);
if (len > 1024)
- free(buf);
+ xfree(buf);
return root;
}
@@ -163,9 +163,9 @@ tree_format(struct f_tree *t, buffer *buf)
{
buffer_puts(buf, "[");
- tree_node_format(t, buf);
+ tree_node_format(t, buf);
- /* Undo last separator */
+ /* Undo last separator */
if (buf->pos[-1] != '[')
buf->pos -= 2;