From 126683feeda03ffb5a4ce23611e59a4598382d49 Mon Sep 17 00:00:00 2001 From: Ondrej Zajicek Date: Mon, 29 Mar 2010 19:29:03 +0200 Subject: 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. --- filter/filter.c | 74 ++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 16 deletions(-) (limited to 'filter/filter.c') diff --git a/filter/filter.c b/filter/filter.c index de7a97b..ae3b03a 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; -- cgit v1.2.3