summaryrefslogtreecommitdiff
path: root/filter
diff options
context:
space:
mode:
Diffstat (limited to 'filter')
-rw-r--r--filter/config.Y4
-rw-r--r--filter/filter.c35
-rw-r--r--filter/filter.h3
-rw-r--r--filter/test.conf1
-rw-r--r--filter/trie.c2
5 files changed, 36 insertions, 9 deletions
diff --git a/filter/config.Y b/filter/config.Y
index ee4e638d..22206d09 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -36,7 +36,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
LEN,
DEFINED,
ADD, DELETE, CONTAINS, RESET,
- PREPEND, MATCH,
+ PREPEND, FIRST, LAST, MATCH,
EMPTY,
FILTER, WHERE, EVAL)
@@ -448,6 +448,8 @@ term:
| term '.' IP { $$ = f_new_inst(); $$->code = P('c','p'); $$->a1.p = $1; $$->aux = T_IP; }
| term '.' LEN { $$ = f_new_inst(); $$->code = 'L'; $$->a1.p = $1; }
| term '.' MASK '(' term ')' { $$ = f_new_inst(); $$->code = P('i','M'); $$->a1.p = $1; $$->a2.p = $5; }
+ | term '.' FIRST { $$ = f_new_inst(); $$->code = P('a','f'); $$->a1.p = $1; }
+ | term '.' LAST { $$ = f_new_inst(); $$->code = P('a','l'); $$->a1.p = $1; }
/* Communities */
/* This causes one shift/reduce conflict
diff --git a/filter/filter.c b/filter/filter.c
index 3df0f0c6..07a25f4a 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -291,7 +291,6 @@ static struct rte **f_rte, *f_rte_old;
static struct linpool *f_pool;
static struct ea_list **f_tmp_attrs;
static int f_flags;
-static rta *f_rta_copy;
/*
* rta_cow - prepare rta for modification by filter
@@ -299,8 +298,8 @@ static rta *f_rta_copy;
static void
rta_cow(void)
{
- if (!f_rta_copy) {
- f_rta_copy = lp_alloc(f_pool, sizeof(rta));
+ if ((*f_rte)->attrs->aflags & RTAF_CACHED) {
+ rta *f_rta_copy = lp_alloc(f_pool, sizeof(rta));
memcpy(f_rta_copy, (*f_rte)->attrs, sizeof(rta));
f_rta_copy->aflags = 0;
*f_rte = rte_cow(*f_rte);
@@ -354,6 +353,7 @@ interpret(struct f_inst *what)
struct f_val v1, v2, res;
unsigned u1, u2;
int i;
+ u32 as;
res.type = T_VOID;
if (!what)
@@ -665,6 +665,7 @@ interpret(struct f_inst *what)
struct adata *ad = lp_alloc(f_pool, sizeof(struct adata) + len);
ad->length = len;
(* (ip_addr *) ad->data) = v1.val.px.ip;
+ l->attrs[0].u.ptr = ad;
break;
case EAF_TYPE_AS_PATH:
if (v1.type != T_PATH)
@@ -686,8 +687,8 @@ interpret(struct f_inst *what)
if (!(what->aux & EAF_TEMP) && (!(f_flags & FF_FORCE_TMPATTR))) {
rta_cow();
- l->next = f_rta_copy->eattrs;
- f_rta_copy->eattrs = l;
+ l->next = (*f_rte)->attrs->eattrs;
+ (*f_rte)->attrs->eattrs = l;
} else {
l->next = (*f_tmp_attrs);
(*f_tmp_attrs) = l;
@@ -702,6 +703,8 @@ interpret(struct f_inst *what)
ONEARG;
if (v1.type != T_INT)
runtime( "Can't set preference to non-integer" );
+ if ((v1.val.i < 0) || (v1.val.i > 0xFFFF))
+ runtime( "Setting preference value out of bounds" );
*f_rte = rte_cow(*f_rte);
(*f_rte)->pref = v1.val.i;
break;
@@ -725,6 +728,26 @@ interpret(struct f_inst *what)
default: bug( "Unknown prefix to conversion" );
}
break;
+ case P('a','f'): /* Get first ASN from AS PATH */
+ ONEARG;
+ if (v1.type != T_PATH)
+ runtime( "AS Path expected" );
+
+ as = 0;
+ as_path_get_first(v1.val.ad, &as);
+ res.type = T_INT;
+ res.val.i = as;
+ break;
+ case P('a','l'): /* Get last ASN from AS PATH */
+ ONEARG;
+ if (v1.type != T_PATH)
+ runtime( "AS path expected" );
+
+ as = 0;
+ as_path_get_last(v1.val.ad, &as);
+ res.type = T_INT;
+ res.val.i = as;
+ break;
case 'r':
ONEARG;
res = v1;
@@ -944,7 +967,6 @@ f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struc
f_tmp_attrs = tmp_attrs;
f_rte = rte;
f_rte_old = *rte;
- f_rta_copy = NULL;
f_pool = tmp_pool;
inst = filter->root;
res = interpret(inst);
@@ -965,7 +987,6 @@ f_eval_int(struct f_inst *expr)
f_tmp_attrs = NULL;
f_rte = NULL;
f_rte_old = NULL;
- f_rta_copy = NULL;
f_pool = cfg_mem;
res = interpret(expr);
if (res.type != T_INT)
diff --git a/filter/filter.h b/filter/filter.h
index 8e0d1793..e526a79b 100644
--- a/filter/filter.h
+++ b/filter/filter.h
@@ -81,10 +81,13 @@ struct rte;
int f_run(struct filter *filter, struct rte **rte, struct ea_list **tmp_attrs, struct linpool *tmp_pool, int flags);
int f_eval_int(struct f_inst *expr);
+u32 f_eval_asn(struct f_inst *expr);
+
char *filter_name(struct filter *filter);
int filter_same(struct filter *new, struct filter *old);
int i_same(struct f_inst *f1, struct f_inst *f2);
+void f_prefix_get_bounds(struct f_prefix *px, int *l, int *h);
void f_prefix_get_bounds(struct f_prefix *px, int *l, int *h);
int val_compare(struct f_val v1, struct f_val v2);
diff --git a/filter/test.conf b/filter/test.conf
index f3b79619..7114fd28 100644
--- a/filter/test.conf
+++ b/filter/test.conf
@@ -62,6 +62,7 @@ clist l;
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 ~ [= (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 "5 = ", p2.len;
pm1 = [= 1 2 * 3 4 5 =];
diff --git a/filter/trie.c b/filter/trie.c
index 2257c8b6..fb405ded 100644
--- a/filter/trie.c
+++ b/filter/trie.c
@@ -70,6 +70,7 @@
*/
#include "nest/bird.h"
+#include "lib/string.h"
#include "conf/conf.h"
#include "filter/filter.h"
@@ -177,7 +178,6 @@ trie_add_prefix(struct f_trie *t, struct f_prefix *px)
{
int l, h;
int plen = px->len & LEN_MASK;
- ip_addr pmask = ipa_mkmask(plen);
/* 'l' and 'h' are lower and upper bounds on accepted
prefix lengths, both inclusive. 0 <= l, h <= 32 */