summaryrefslogtreecommitdiff
path: root/filter
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2010-03-29 19:29:03 +0200
committerOndrej Zajicek <santiago@crfreenet.org>2010-03-29 19:29:03 +0200
commit126683feeda03ffb5a4ce23611e59a4598382d49 (patch)
tree9aeb9632949113b218b485100a9e52e008e8c1b9 /filter
parenteb0f129fcedcecbee85403095abad8f59b82683c (diff)
Filter language updates; new route attributes and datatype.
- Adds bgp_originator_id and bgp_cluster_list route attributes. - Adds dotted quad filter datatype (for router IDs, used by bgp_originator_id and ospf_router_id route attributes). - Fixes pair ~ pair set matching. - Documentation updates.
Diffstat (limited to 'filter')
-rw-r--r--filter/config.Y9
-rw-r--r--filter/filter.c74
-rw-r--r--filter/filter.h1
-rw-r--r--filter/test.conf15
4 files changed, 80 insertions, 19 deletions
diff --git a/filter/config.Y b/filter/config.Y
index 1af5649c..77236586 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -29,7 +29,7 @@ CF_DECLS
CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
ACCEPT, REJECT, ERROR, QUITBIRD,
- INT, BOOL, IP, PREFIX, PAIR, SET, STRING, BGPMASK, BGPPATH, CLIST,
+ INT, BOOL, IP, PREFIX, PAIR, QUAD, SET, STRING, BGPMASK, BGPPATH, CLIST,
IF, THEN, ELSE, CASE,
TRUE, FALSE,
FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, PREFERENCE,
@@ -75,6 +75,7 @@ type:
| IP { $$ = T_IP; }
| PREFIX { $$ = T_PREFIX; }
| PAIR { $$ = T_PAIR; }
+ | QUAD { $$ = T_QUAD; }
| STRING { $$ = T_STRING; }
| BGPMASK { $$ = T_PATH_MASK; }
| BGPPATH { $$ = T_PATH; }
@@ -82,8 +83,9 @@ type:
| type SET {
switch ($1) {
case T_INT:
- case T_IP:
case T_PAIR:
+ case T_QUAD:
+ case T_IP:
$$ = T_SET;
break;
@@ -234,6 +236,7 @@ fipa:
set_atom:
NUM { $$.type = T_INT; $$.val.i = $1; }
+ | RTRID { $$.type = T_QUAD; $$.val.i = $1; }
| cpair { $$.type = T_PAIR; $$.val.i = $1; }
| fipa { $$ = $1; }
| ENUM { $$.type = $1 >> 16; $$.val.i = $1 & 0xffff; }
@@ -340,6 +343,7 @@ constant:
| TEXT { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_STRING; $$->a2.p = $1; }
| fipa { NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
| fprefix_s {NEW_F_VAL; $$ = f_new_inst(); $$->code = 'C'; $$->a1.p = val; *val = $1; }
+ | RTRID { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_QUAD; $$->a2.i = $1; }
| '[' set_items ']' { DBG( "We've got a set here..." ); $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_SET; $$->a2.p = build_tree($2); DBG( "ook\n" ); }
| '[' fprefix_set ']' { $$ = f_new_inst(); $$->code = 'c'; $$->aux = T_PREFIX_SET; $$->a2.p = $2; }
| ENUM { $$ = f_new_inst(); $$->code = 'c'; $$->aux = $1 >> 16; $$->a2.i = $1 & 0xffff; }
@@ -396,6 +400,7 @@ symbol:
case SYM_VARIABLE | T_BOOL:
case SYM_VARIABLE | T_INT:
case SYM_VARIABLE | T_PAIR:
+ case SYM_VARIABLE | T_QUAD:
case SYM_VARIABLE | T_STRING:
case SYM_VARIABLE | T_IP:
case SYM_VARIABLE | T_PREFIX:
diff --git a/filter/filter.c b/filter/filter.c
index de7a97bc..ae3b03ab 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -65,6 +65,7 @@ pm_path_compare(struct f_path_mask *m1, struct f_path_mask *m2)
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;
@@ -111,6 +112,13 @@ pm_format(struct f_path_mask *p, byte *buf, unsigned int size)
*buf = 0;
}
+static inline int int_cmp(int i1, int i2)
+{
+ if (i1 == i2) return 0;
+ if (i1 < i2) return -1;
+ else return 1;
+}
+
/**
* val_compare - compare two values
* @v1: first value
@@ -133,6 +141,14 @@ val_compare(struct f_val v1, struct f_val v2)
return 1;
if (v1.type != v2.type) {
+#ifndef IPV6
+ /* IP->Quad implicit conversion */
+ if ((v1.type == T_QUAD) && (v2.type == T_IP))
+ return int_cmp(v1.val.i, ipa_to_u32(v2.val.px.ip));
+ if ((v1.type == T_IP) && (v2.type == T_QUAD))
+ return int_cmp(ipa_to_u32(v1.val.px.ip), v2.val.i);
+#endif
+
debug( "Types do not match in val_compare\n" );
return CMP_ERROR;
}
@@ -141,9 +157,8 @@ val_compare(struct f_val v1, struct f_val v2)
case T_INT:
case T_BOOL:
case T_PAIR:
- if (v1.val.i == v2.val.i) return 0;
- if (v1.val.i < v2.val.i) return -1;
- return 1;
+ case T_QUAD:
+ return int_cmp(v1.val.i, v2.val.i);
case T_IP:
return ipa_compare(v1.val.px.ip, v2.val.px.ip);
case T_PREFIX:
@@ -196,8 +211,13 @@ val_simple_in_range(struct f_val v1, struct f_val v2)
{
if ((v1.type == T_PATH) && (v2.type == T_PATH_MASK))
return as_path_match(v1.val.ad, v2.val.path_mask);
- if ((v1.type == T_PAIR) && (v2.type == T_CLIST))
+ if (((v1.type == T_PAIR) || (v1.type == T_QUAD)) && (v2.type == T_CLIST))
return int_set_contains(v2.val.ad, v1.val.i);
+#ifndef IPV6
+ /* IP->Quad implicit conversion */
+ if ((v1.type == T_IP) && (v2.type == T_CLIST))
+ return int_set_contains(v2.val.ad, ipa_to_u32(v1.val.px.ip));
+#endif
if ((v1.type == T_STRING) && (v2.type == T_STRING))
return patmatch(v2.val.s, v1.val.s);
@@ -235,8 +255,9 @@ val_in_range(struct f_val v1, struct f_val v2)
switch (v1.type) {
case T_ENUM:
case T_INT:
+ case T_PAIR:
+ case T_QUAD:
case T_IP:
- case T_PREFIX:
{
struct f_tree *n;
n = find_tree(v2.val.t, v1);
@@ -280,6 +301,7 @@ val_print(struct f_val v)
case T_IP: PRINTF( "%I", v.val.px.ip ); break;
case T_PREFIX: PRINTF( "%I/%d", v.val.px.ip, v.val.px.len ); break;
case T_PAIR: PRINTF( "(%d,%d)", v.val.i >> 16, v.val.i & 0xffff ); break;
+ case T_QUAD: PRINTF( "%R", v.val.i ); break;
case T_PREFIX_SET: trie_print(v.val.ti, buf, 2040); break;
case T_SET: tree_print( v.val.t ); PRINTF( "\n" ); break;
case T_ENUM: PRINTF( "(enum %x)%d", v.type, v.val.i ); break;
@@ -355,7 +377,7 @@ static struct f_val
interpret(struct f_inst *what)
{
struct symbol *sym;
- struct f_val v1, v2, res;
+ struct f_val v1, v2, res, *vp;
unsigned u1, u2;
int i;
u32 as;
@@ -435,11 +457,11 @@ interpret(struct f_inst *what)
/* Relational operators */
#define COMPARE(x) \
- TWOARGS_C; \
- res.type = T_BOOL; \
+ TWOARGS; \
i = val_compare(v1, v2); \
if (i==CMP_ERROR) \
- runtime( "Error in comparison" ); \
+ runtime( "Can't compare values of incompatible types" ); \
+ res.type = T_BOOL; \
res.val.i = (x); \
break;
@@ -473,10 +495,19 @@ interpret(struct f_inst *what)
case 's':
ARG(v2, a2.p);
sym = what->a1.p;
- if ((sym->class != (SYM_VARIABLE | v2.type)) &&
- (v2.type != T_VOID))
+ vp = sym->def;
+ if ((sym->class != (SYM_VARIABLE | v2.type)) && (v2.type != T_VOID)) {
+#ifndef IPV6
+ /* IP->Quad implicit conversion */
+ if ((sym->class == (SYM_VARIABLE | T_QUAD)) && (v2.type == T_IP)) {
+ vp->type = T_QUAD;
+ vp->val.i = ipa_to_u32(v2.val.px.ip);
+ break;
+ }
+#endif
runtime( "Assigning to variable of incompatible type" );
- * (struct f_val *) sym->def = v2;
+ }
+ *vp = v2;
break;
/* some constants have value in a2, some in *a1.p, strange. */
@@ -597,10 +628,13 @@ interpret(struct f_inst *what)
switch (what->aux & EAF_TYPE_MASK) {
case EAF_TYPE_INT:
- case EAF_TYPE_ROUTER_ID:
res.type = T_INT;
res.val.i = e->u.data;
break;
+ case EAF_TYPE_ROUTER_ID:
+ res.type = T_QUAD;
+ res.val.i = e->u.data;
+ break;
case EAF_TYPE_OPAQUE:
res.type = T_ENUM_EMPTY;
res.val.i = 0;
@@ -808,13 +842,21 @@ interpret(struct f_inst *what)
v1.val.ad = adata_empty(f_pool);
else if (v1.type != T_CLIST)
runtime("Can't add/delete to non-clist");
- if (v2.type != T_PAIR)
+
+ if ((v2.type == T_PAIR) || (v2.type == T_QUAD))
+ i = v2.val.i;
+#ifndef IPV6
+ /* IP->Quad implicit conversion */
+ else if (v2.type == T_IP)
+ i = ipa_to_u32(v2.val.px.ip);
+#endif
+ else
runtime("Can't add/delete non-pair");
res.type = T_CLIST;
switch (what->aux) {
- case 'a': res.val.ad = int_set_add(f_pool, v1.val.ad, v2.val.i); break;
- case 'd': res.val.ad = int_set_del(f_pool, v1.val.ad, v2.val.i); break;
+ case 'a': res.val.ad = int_set_add(f_pool, v1.val.ad, i); break;
+ case 'd': res.val.ad = int_set_del(f_pool, v1.val.ad, i); break;
default: bug("unknown Ca operation");
}
break;
diff --git a/filter/filter.h b/filter/filter.h
index 11e0623a..46dc1a23 100644
--- a/filter/filter.h
+++ b/filter/filter.h
@@ -115,6 +115,7 @@ void val_print(struct f_val v);
#define T_INT 0x10
#define T_BOOL 0x11
#define T_PAIR 0x12 /* Notice that pair is stored as integer: first << 16 | second */
+#define T_QUAD 0x13
/* Put enumerational types in 0x30..0x3f range */
#define T_ENUM_LO 0x30
diff --git a/filter/test.conf b/filter/test.conf
index 8eeb5c35..0483c3d9 100644
--- a/filter/test.conf
+++ b/filter/test.conf
@@ -138,10 +138,12 @@ bool b;
prefix px;
ip p;
pair pp;
+quad qq;
int set is;
int set is1;
int set is2;
int set is3;
+pair set ps;
prefix set pxs;
string s;
{
@@ -190,7 +192,18 @@ string s;
pp = (1, 2);
print "Testing pairs: (1,2) = ", (1,2), " = ", pp, " = ", (1,1+1), " = ", 'mkpair-a'(2);
print " must be true: ", (1,2) = (1,1+1);
- print "Testing enums: ", RTS_DUMMY, " ", RTS_STATIC;
+ print "Testing enums: ", RTS_DUMMY, " ", RTS_STATIC, " ",
+ ", true: ", RTS_STATIC ~ [RTS_STATIC, RTS_DEVICE],
+ ", false: ", RTS_BGP ~ [RTS_STATIC, RTS_DEVICE];
+
+ ps = [(1,2), (3,4)..(3,8)];
+ print "Testing pair set (TTF):", pp ~ ps, " ", (3,5) ~ ps, " ", (3,9) ~ ps;
+
+ qq = 1.2.3.4;
+ print "Testinq quad: 1.2.3.4 = ", qq,
+ ", true: ", qq = 1.2.3.4, " ", qq ~ [1.2.3.4, 5.6.7.8],
+ ", false: ", qq = 4.3.2.1, " ", qq ~ [1.2.1.1, 1.2.3.5];
+
s = "Hello";
print "Testing string: ", s, " true: ", s ~ "Hell*", " false: ", s ~ "ell*";