diff options
Diffstat (limited to 'filter/filter.c')
-rw-r--r-- | filter/filter.c | 68 |
1 files changed, 47 insertions, 21 deletions
diff --git a/filter/filter.c b/filter/filter.c index fe3a2ac..3df0f0c 100644 --- a/filter/filter.c +++ b/filter/filter.c @@ -71,6 +71,8 @@ pm_path_compare(struct f_path_mask *m1, struct f_path_mask *m2) } } +u32 f_eval_asn(struct f_inst *expr); + static void pm_format(struct f_path_mask *p, byte *buf, unsigned int size) { @@ -84,10 +86,24 @@ pm_format(struct f_path_mask *p, byte *buf, unsigned int size) return; } - if (p->kind == PM_ASN) - buf += bsprintf(buf, " %u", p->val); - else - buf += bsprintf(buf, (p->kind == PM_ASTERISK) ? " *" : " ?"); + switch(p->kind) + { + case PM_ASN: + buf += bsprintf(buf, " %u", p->val); + break; + + case PM_QUESTION: + buf += bsprintf(buf, " ?"); + break; + + case PM_ASTERISK: + buf += bsprintf(buf, " *"); + break; + + case PM_ASN_EXPR: + buf += bsprintf(buf, " %u", f_eval_asn((struct f_inst *) p->val)); + break; + } p = p->next; } @@ -181,25 +197,11 @@ val_simple_in_range(struct f_val v1, struct f_val v2) return patmatch(v2.val.s, v1.val.s); if ((v1.type == T_IP) && (v2.type == T_PREFIX)) - return !(ipa_compare(ipa_and(v2.val.px.ip, ipa_mkmask(v2.val.px.len)), ipa_and(v1.val.px.ip, ipa_mkmask(v2.val.px.len)))); - - if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX)) { - - if (v1.val.px.len & (LEN_PLUS | LEN_MINUS | LEN_RANGE)) - return CMP_ERROR; + return ipa_in_net(v1.val.px.ip, v2.val.px.ip, v2.val.px.len); - int p1 = v1.val.px.len & LEN_MASK; - int p2 = v2.val.px.len & LEN_MASK; - ip_addr mask = ipa_mkmask(MIN(p1, p2)); + if ((v1.type == T_PREFIX) && (v2.type == T_PREFIX)) + return ipa_in_net(v1.val.px.ip, v2.val.px.ip, v2.val.px.len) && (v1.val.px.len >= v2.val.px.len); - if (ipa_compare(ipa_and(v2.val.px.ip, mask), ipa_and(v1.val.px.ip, mask))) - return 0; - - int l, h; - f_prefix_get_bounds(&v2.val.px, &l, &h); - - return ((l <= v1.val.px.len) && (v1.val.px.len <= h)); - } return CMP_ERROR; } @@ -350,6 +352,7 @@ interpret(struct f_inst *what) { struct symbol *sym; struct f_val v1, v2, res; + unsigned u1, u2; int i; res.type = T_VOID; @@ -412,6 +415,18 @@ interpret(struct f_inst *what) res.val.i = v1.val.i || v2.val.i; break; + case P('m','p'): + TWOARGS_C; + if ((v1.type != T_INT) || (v2.type != T_INT)) + runtime( "Can't operate with value of non-integer type in pair constructor" ); + u1 = v1.val.i; + u2 = v2.val.i; + if ((u1 > 0xFFFF) || (u2 > 0xFFFF)) + runtime( "Can't operate with value out of bounds in pair constructor" ); + res.val.i = (u1 << 16) | u2; + res.type = T_PAIR; + break; + /* Relational operators */ #define COMPARE(x) \ @@ -828,6 +843,7 @@ i_same(struct f_inst *f1, struct f_inst *f2) case '/': case '|': case '&': + case P('m','p'): case P('!','='): case P('=','='): case '<': @@ -957,6 +973,16 @@ f_eval_int(struct f_inst *expr) return res.val.i; } +u32 +f_eval_asn(struct f_inst *expr) +{ + struct f_val res = interpret(expr); + if (res.type != T_INT) + cf_error("Can't operate with value of non-integer type in AS path mask constructor"); + + return res.val.i; +} + /** * filter_same - compare two filters * @new: first filter to be compared |