summaryrefslogtreecommitdiffstats
path: root/filter/filter.c
diff options
context:
space:
mode:
Diffstat (limited to 'filter/filter.c')
-rw-r--r--filter/filter.c68
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