summaryrefslogtreecommitdiff
path: root/filter
diff options
context:
space:
mode:
authorOndrej Zajicek <santiago@crfreenet.org>2012-03-18 17:32:30 +0100
committerOndrej Zajicek <santiago@crfreenet.org>2012-03-18 17:32:30 +0100
commitaf582c4811175d9a27ed5d08a4f6d5eaa69ecec7 (patch)
tree3b2793cb9db3c67efddfb379e6c8adc16b143604 /filter
parentfd087589f80a435a42cedb87b917c71363b11860 (diff)
Route Origin Authorization basics.
- ROA tables, which are used as a basic part for RPKI. - Commands for examining and modifying ROA tables. - Filter operators based on ROA tables consistent with RFC 6483.
Diffstat (limited to 'filter')
-rw-r--r--filter/config.Y5
-rw-r--r--filter/f-util.c18
-rw-r--r--filter/filter.c41
-rw-r--r--filter/filter.h9
-rw-r--r--filter/test.conf28
5 files changed, 98 insertions, 3 deletions
diff --git a/filter/config.Y b/filter/config.Y
index 7828bf8b..2e8b522e 100644
--- a/filter/config.Y
+++ b/filter/config.Y
@@ -259,6 +259,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
DEFINED,
ADD, DELETE, CONTAINS, RESET,
PREPEND, FIRST, LAST, MATCH,
+ ROA_CHECK,
EMPTY,
FILTER, WHERE, EVAL)
@@ -755,6 +756,9 @@ term:
| DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; }
| FILTER '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'f'; }
+ | ROA_CHECK '(' SYM ')' { $$ = f_generate_roa_check($3, NULL, NULL); }
+ | ROA_CHECK '(' SYM ',' term ',' term ')' { $$ = f_generate_roa_check($3, $5, $7); }
+
/* | term '.' LEN { $$->code = P('P','l'); } */
/* function_call is inlined here */
@@ -801,7 +805,6 @@ print_list: /* EMPTY */ { $$ = NULL; }
$$ = $1;
} else $$ = $3;
}
-
;
var_listn: term {
diff --git a/filter/f-util.c b/filter/f-util.c
index ec86a4b2..5908ac64 100644
--- a/filter/f-util.c
+++ b/filter/f-util.c
@@ -54,6 +54,24 @@ f_generate_complex(int operation, int operation_aux, struct f_inst *dyn, struct
return set_dyn;
}
+
+struct f_inst *
+f_generate_roa_check(struct symbol *sym, struct f_inst *prefix, struct f_inst *asn)
+{
+ struct f_inst_roa_check *ret = cfg_allocz(sizeof(struct f_inst_roa_check));
+ ret->i.code = P('R','C');
+ ret->i.lineno = ifs->conf_lino;
+ ret->i.arg1 = prefix;
+ ret->i.arg2 = asn;
+ /* prefix == NULL <-> asn == NULL */
+
+ if ((sym->class != SYM_ROA) || ! sym->def)
+ cf_error("%s is not a ROA table", sym->name);
+ ret->rtc = sym->def;
+
+ return &ret->i;
+}
+
char *
filter_name(struct filter *filter)
{
diff --git a/filter/filter.c b/filter/filter.c
index a087c50b..acdcfd2b 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -248,7 +248,7 @@ val_simple_in_range(struct f_val v1, struct f_val v2)
return ipa_in_net(v1.val.px.ip, v2.val.px.ip, v2.val.px.len);
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);
+ return net_in_net(v1.val.px.ip, v1.val.px.len, v2.val.px.ip, v2.val.px.len);
return CMP_ERROR;
}
@@ -1208,6 +1208,38 @@ interpret(struct f_inst *what)
break;
+ case P('R','C'): /* ROA Check */
+ if (what->arg1)
+ {
+ TWOARGS;
+ if ((v1.type != T_PREFIX) || (v2.type != T_INT))
+ runtime("Invalid argument to roa_check()");
+
+ as = v2.val.i;
+ }
+ else
+ {
+ v1.val.px.ip = (*f_rte)->net->n.prefix;
+ v1.val.px.len = (*f_rte)->net->n.pxlen;
+
+ /* We ignore temporary attributes, probably not a problem here */
+ /* 0x02 is a value of BA_AS_PATH, we don't want to include BGP headers */
+ eattr *e = ea_find((*f_rte)->attrs->eattrs, EA_CODE(EAP_BGP, 0x02));
+
+ if (!e || e->type != EAF_TYPE_AS_PATH)
+ runtime("Missing AS_PATH attribute");
+
+ as_path_get_last(e->u.ptr, &as);
+ }
+
+ struct roa_table_config *rtc = ((struct f_inst_roa_check *) what)->rtc;
+ if (!rtc->table)
+ runtime("Missing ROA table");
+
+ res.type = T_ENUM_ROA;
+ res.val.i = roa_check(rtc->table, v1.val.px.ip, v1.val.px.len, as);
+ break;
+
default:
bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
}
@@ -1332,6 +1364,13 @@ i_same(struct f_inst *f1, struct f_inst *f2)
case P('C','a'): TWOARGS; break;
case P('a','f'):
case P('a','l'): ONEARG; break;
+ case P('R','C'):
+ TWOARGS;
+ /* Does not really make sense - ROA check resuls may change anyway */
+ if (strcmp(((struct f_inst_roa_check *) f1)->rtc->name,
+ ((struct f_inst_roa_check *) f2)->rtc->name))
+ return 0;
+ break;
default:
bug( "Unknown instruction %d in same (%c)", f1->code, f1->code & 0xff);
}
diff --git a/filter/filter.h b/filter/filter.h
index 2cf4652d..2386fc95 100644
--- a/filter/filter.h
+++ b/filter/filter.h
@@ -32,6 +32,12 @@ struct f_inst { /* Instruction */
#define arg1 a1.p
#define arg2 a2.p
+/* Not enough fields in f_inst for three args used by roa_check() */
+struct f_inst_roa_check {
+ struct f_inst i;
+ struct roa_table_config *rtc;
+};
+
struct f_prefix {
ip_addr ip;
int len;
@@ -66,6 +72,8 @@ struct f_inst *f_new_inst(void);
struct f_inst *f_new_dynamic_attr(int type, int f_type, int code); /* Type as core knows it, type as filters know it, and code of dynamic attribute */
struct f_tree *f_new_tree(void);
struct f_inst *f_generate_complex(int operation, int operation_aux, struct f_inst *dyn, struct f_inst *argument);
+struct f_inst *f_generate_roa_check(struct symbol *sym, struct f_inst *prefix, struct f_inst *asn);
+
struct f_tree *build_tree(struct f_tree *);
struct f_tree *find_tree(struct f_tree *t, struct f_val val);
@@ -141,6 +149,7 @@ int tree_compare(const void *p1, const void *p2);
#define T_ENUM_SCOPE 0x32
#define T_ENUM_RTC 0x33
#define T_ENUM_RTD 0x34
+#define T_ENUM_ROA 0x35
/* new enums go here */
#define T_ENUM_EMPTY 0x3f /* Special hack for atomic_aggr */
diff --git a/filter/test.conf b/filter/test.conf
index dbb05de8..64e6d91b 100644
--- a/filter/test.conf
+++ b/filter/test.conf
@@ -52,6 +52,32 @@ function fifteen()
return 15;
}
+roa table rl
+{
+ roa 10.110.0.0/16 max 16 as 1000;
+ roa 10.120.0.0/16 max 24 as 1000;
+ roa 10.130.0.0/16 max 24 as 2000;
+ roa 10.130.128.0/18 max 24 as 3000;
+}
+
+function test_roa()
+{
+ # cannot be tested in __startup(), sorry
+ print "Testing ROA";
+ print "Should be true: ", roa_check(rl, 10.10.0.0/16, 1000) = ROA_UNKNOWN,
+ " ", roa_check(rl, 10.0.0.0/8, 1000) = ROA_UNKNOWN,
+ " ", roa_check(rl, 10.110.0.0/16, 1000) = ROA_VALID,
+ " ", roa_check(rl, 10.110.0.0/16, 2000) = ROA_INVALID,
+ " ", roa_check(rl, 10.110.32.0/20, 1000) = ROA_INVALID,
+ " ", roa_check(rl, 10.120.32.0/20, 1000) = ROA_VALID;
+ print "Should be true: ", roa_check(rl, 10.120.32.0/20, 2000) = ROA_INVALID,
+ " ", roa_check(rl, 10.120.32.32/28, 1000) = ROA_INVALID,
+ " ", roa_check(rl, 10.130.130.0/24, 1000) = ROA_INVALID,
+ " ", roa_check(rl, 10.130.130.0/24, 2000) = ROA_VALID,
+ " ", roa_check(rl, 10.130.30.0/24, 3000) = ROA_INVALID,
+ " ", roa_check(rl, 10.130.130.0/24, 3000) = ROA_VALID;
+}
+
function paths()
bgpmask pm1;
bgpmask pm2;
@@ -163,7 +189,7 @@ eclist el2;
print "eclist A isect B: ", filter( el, el2 );
print "eclist A \ B: ", delete( el, el2 );
-
+# test_roa();
}
function bla()