diff options
author | Ondrej Zajicek <santiago@crfreenet.org> | 2012-03-18 17:32:30 +0100 |
---|---|---|
committer | Ondrej Zajicek <santiago@crfreenet.org> | 2012-03-18 17:32:30 +0100 |
commit | af582c4811175d9a27ed5d08a4f6d5eaa69ecec7 (patch) | |
tree | 3b2793cb9db3c67efddfb379e6c8adc16b143604 /filter | |
parent | fd087589f80a435a42cedb87b917c71363b11860 (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.Y | 5 | ||||
-rw-r--r-- | filter/f-util.c | 18 | ||||
-rw-r--r-- | filter/filter.c | 41 | ||||
-rw-r--r-- | filter/filter.h | 9 | ||||
-rw-r--r-- | filter/test.conf | 28 |
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() |