Rewrite roa_check() for integrated BIRD
Thanks to Ondrej Zajicek for his support with writing this code.
This commit is contained in:
parent
cb1bd816db
commit
0264ccf6f4
7 changed files with 101 additions and 20 deletions
|
@ -278,6 +278,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
||||||
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
|
TRUE, FALSE, RT, RO, UNKNOWN, GENERIC,
|
||||||
FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, IFNAME, IFINDEX,
|
FROM, GW, NET, MASK, PROTO, SOURCE, SCOPE, CAST, DEST, IFNAME, IFINDEX,
|
||||||
PREFERENCE,
|
PREFERENCE,
|
||||||
|
ROA_CHECK,
|
||||||
LEN,
|
LEN,
|
||||||
DEFINED,
|
DEFINED,
|
||||||
ADD, DELETE, CONTAINS, RESET,
|
ADD, DELETE, CONTAINS, RESET,
|
||||||
|
@ -759,10 +760,8 @@ term:
|
||||||
| DELETE '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'd'; }
|
| 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'; }
|
| FILTER '(' term ',' term ')' { $$ = f_new_inst(); $$->code = P('C','a'); $$->a1.p = $3; $$->a2.p = $5; $$->aux = 'f'; }
|
||||||
|
|
||||||
/*
|
| ROA_CHECK '(' rtable ')' { $$ = f_generate_roa_check($3, NULL, NULL); }
|
||||||
| ROA_CHECK '(' SYM ')' { $$ = f_generate_roa_check($3, NULL, NULL); }
|
| ROA_CHECK '(' rtable ',' term ',' term ')' { $$ = f_generate_roa_check($3, $5, $7); }
|
||||||
| ROA_CHECK '(' SYM ',' term ',' term ')' { $$ = f_generate_roa_check($3, $5, $7); }
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* | term '.' LEN { $$->code = P('P','l'); } */
|
/* | term '.' LEN { $$->code = P('P','l'); } */
|
||||||
|
|
||||||
|
|
|
@ -54,9 +54,8 @@ f_generate_complex(int operation, int operation_aux, struct f_inst *dyn, struct
|
||||||
return set_dyn;
|
return set_dyn;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
struct f_inst *
|
struct f_inst *
|
||||||
f_generate_roa_check(struct symbol *sym, struct f_inst *prefix, struct f_inst *asn)
|
f_generate_roa_check(struct rtable_config *table, struct f_inst *prefix, struct f_inst *asn)
|
||||||
{
|
{
|
||||||
struct f_inst_roa_check *ret = cfg_allocz(sizeof(struct f_inst_roa_check));
|
struct f_inst_roa_check *ret = cfg_allocz(sizeof(struct f_inst_roa_check));
|
||||||
ret->i.code = P('R','C');
|
ret->i.code = P('R','C');
|
||||||
|
@ -65,13 +64,12 @@ f_generate_roa_check(struct symbol *sym, struct f_inst *prefix, struct f_inst *a
|
||||||
ret->i.arg2 = asn;
|
ret->i.arg2 = asn;
|
||||||
/* prefix == NULL <-> asn == NULL */
|
/* prefix == NULL <-> asn == NULL */
|
||||||
|
|
||||||
if ((sym->class != SYM_ROA) || ! sym->def)
|
if (table->addr_type != NET_ROA4 && table->addr_type != NET_ROA6)
|
||||||
cf_error("%s is not a ROA table", sym->name);
|
cf_error("%s is not a ROA table", table->name);
|
||||||
ret->rtc = sym->def;
|
ret->rtc = table;
|
||||||
|
|
||||||
return &ret->i;
|
return &ret->i;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
char *
|
char *
|
||||||
filter_name(struct filter *filter)
|
filter_name(struct filter *filter)
|
||||||
|
|
|
@ -39,6 +39,8 @@
|
||||||
#include "lib/socket.h"
|
#include "lib/socket.h"
|
||||||
#include "lib/string.h"
|
#include "lib/string.h"
|
||||||
#include "lib/unaligned.h"
|
#include "lib/unaligned.h"
|
||||||
|
#include "lib/net.h"
|
||||||
|
#include "lib/ip.h"
|
||||||
#include "nest/route.h"
|
#include "nest/route.h"
|
||||||
#include "nest/protocol.h"
|
#include "nest/protocol.h"
|
||||||
#include "nest/iface.h"
|
#include "nest/iface.h"
|
||||||
|
@ -1241,7 +1243,7 @@ interpret(struct f_inst *what)
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
#if 0
|
|
||||||
case P('R','C'): /* ROA Check */
|
case P('R','C'): /* ROA Check */
|
||||||
if (what->arg1)
|
if (what->arg1)
|
||||||
{
|
{
|
||||||
|
@ -1266,15 +1268,15 @@ interpret(struct f_inst *what)
|
||||||
as_path_get_last(e->u.ptr, &as);
|
as_path_get_last(e->u.ptr, &as);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct roa_table_config *rtc = ((struct f_inst_roa_check *) what)->rtc;
|
struct rtable *table = ((struct f_inst_roa_check *) what)->rtc->table;
|
||||||
if (!rtc->table)
|
if (!table || table->addr_type != (v1.val.net->type == NET_IP4 ? NET_ROA4 : NET_ROA6))
|
||||||
runtime("Missing ROA table");
|
runtime("Missing ROA table");
|
||||||
|
|
||||||
res.type = T_ENUM_ROA;
|
res.type = T_ENUM_ROA;
|
||||||
res.val.i = ROA_UNKNOWN;
|
res.val.i = net_roa_check(table, v1.val.net, as);
|
||||||
// XXXX res.val.i = roa_check_net(rtc->table, &v1.val.net, as);
|
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
|
bug( "Unknown instruction %d (%c)", what->code, what->code & 0xff);
|
||||||
|
|
|
@ -35,7 +35,7 @@ struct f_inst { /* Instruction */
|
||||||
/* Not enough fields in f_inst for three args used by roa_check() */
|
/* Not enough fields in f_inst for three args used by roa_check() */
|
||||||
struct f_inst_roa_check {
|
struct f_inst_roa_check {
|
||||||
struct f_inst i;
|
struct f_inst i;
|
||||||
struct roa_table_config *rtc;
|
struct rtable_config *rtc;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct f_prefix {
|
struct f_prefix {
|
||||||
|
@ -67,7 +67,7 @@ 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_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_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_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_inst *f_generate_roa_check(struct rtable_config *table, struct f_inst *prefix, struct f_inst *asn);
|
||||||
|
|
||||||
|
|
||||||
struct f_tree *build_tree(struct f_tree *);
|
struct f_tree *build_tree(struct f_tree *);
|
||||||
|
|
|
@ -72,6 +72,7 @@ static inline struct fib_node * fib_user_to_node(struct fib *f, void *e)
|
||||||
|
|
||||||
void fib_init(struct fib *f, pool *p, uint addr_type, uint node_size, uint node_offset, uint hash_order, fib_init_fn init);
|
void fib_init(struct fib *f, pool *p, uint addr_type, uint node_size, uint node_offset, uint hash_order, fib_init_fn init);
|
||||||
void *fib_find(struct fib *, const net_addr *); /* Find or return NULL if doesn't exist */
|
void *fib_find(struct fib *, const net_addr *); /* Find or return NULL if doesn't exist */
|
||||||
|
void *fib_get_chain(struct fib *f, const net_addr *a); /* Find first node in linked list from hash table */
|
||||||
void *fib_get(struct fib *, const net_addr *); /* Find or create new if nonexistent */
|
void *fib_get(struct fib *, const net_addr *); /* Find or create new if nonexistent */
|
||||||
void *fib_route(struct fib *, const net_addr *); /* Longest-match routing lookup */
|
void *fib_route(struct fib *, const net_addr *); /* Longest-match routing lookup */
|
||||||
void fib_delete(struct fib *, void *); /* Remove fib entry */
|
void fib_delete(struct fib *, void *); /* Remove fib entry */
|
||||||
|
@ -273,8 +274,9 @@ void rt_commit(struct config *new, struct config *old);
|
||||||
void rt_lock_table(rtable *);
|
void rt_lock_table(rtable *);
|
||||||
void rt_unlock_table(rtable *);
|
void rt_unlock_table(rtable *);
|
||||||
void rt_setup(pool *, rtable *, char *, struct rtable_config *);
|
void rt_setup(pool *, rtable *, char *, struct rtable_config *);
|
||||||
static inline net *net_find(rtable *tab, net_addr *addr) { return (net *) fib_find(&tab->fib, addr); }
|
static inline net *net_find(rtable *tab, const net_addr *addr) { return (net *) fib_find(&tab->fib, addr); }
|
||||||
static inline net *net_get(rtable *tab, net_addr *addr) { return (net *) fib_get(&tab->fib, addr); }
|
static inline net *net_get(rtable *tab, const net_addr *addr) { return (net *) fib_get(&tab->fib, addr); }
|
||||||
|
byte net_roa_check(rtable *tab, const net_addr *n, u32 asn);
|
||||||
|
|
||||||
rte *rte_find(net *net, struct rte_src *src);
|
rte *rte_find(net *net, struct rte_src *src);
|
||||||
rte *rte_get_temp(struct rta *);
|
rte *rte_get_temp(struct rta *);
|
||||||
|
|
|
@ -195,6 +195,15 @@ fib_hash(struct fib *f, const net_addr *a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
fib_get_chain(struct fib *f, const net_addr *a)
|
||||||
|
{
|
||||||
|
ASSERT(f->addr_type == a->type);
|
||||||
|
|
||||||
|
struct fib_node *e = f->hash_table[fib_hash(f, a)];
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fib_find - search for FIB node by prefix
|
* fib_find - search for FIB node by prefix
|
||||||
* @f: FIB to search in
|
* @f: FIB to search in
|
||||||
|
|
|
@ -100,6 +100,77 @@ net_route_ip6(struct fib *f, net_addr_ip6 *n)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static byte
|
||||||
|
net_roa4_check(rtable *tab, const net_addr_ip4 *px, u32 asn)
|
||||||
|
{
|
||||||
|
struct net_addr_roa4 n = NET_ADDR_ROA4(px->prefix, px->pxlen, 0, 0);
|
||||||
|
byte anything = 0;
|
||||||
|
|
||||||
|
struct fib_node *fn;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
for (fn = fib_get_chain(&tab->fib, (net_addr *) &n); fn; fn = fn->next)
|
||||||
|
{
|
||||||
|
net *r = fib_node_to_user(&tab->fib, fn);
|
||||||
|
if (rte_is_valid(r->routes) && ipa_in_netX(ipa_from_ip4(px->prefix), r->n.addr))
|
||||||
|
{
|
||||||
|
net_addr_roa4 *roa = (void *) r->n.addr;
|
||||||
|
anything = 1;
|
||||||
|
if (asn && (roa->asn == asn) && (roa->max_pxlen >= px->pxlen))
|
||||||
|
return ROA_VALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n.pxlen == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
n.pxlen--;
|
||||||
|
ip4_clrbit(&n.prefix, n.pxlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
return anything ? ROA_INVALID : ROA_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static byte
|
||||||
|
net_roa6_check(rtable *tab, const net_addr_ip6 *px, u32 asn)
|
||||||
|
{
|
||||||
|
struct net_addr_roa6 n = NET_ADDR_ROA6(px->prefix, px->pxlen, 0, 0);
|
||||||
|
byte anything = 0;
|
||||||
|
|
||||||
|
struct fib_node *fn;
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
for (fn = fib_get_chain(&tab->fib, (net_addr *) &n); fn; fn = fn->next)
|
||||||
|
{
|
||||||
|
net *r = fib_node_to_user(&tab->fib, fn);
|
||||||
|
if (rte_is_valid(r->routes) && ipa_in_netX(ipa_from_ip6(px->prefix), r->n.addr))
|
||||||
|
{
|
||||||
|
net_addr_roa6 *roa = (void *) r->n.addr;
|
||||||
|
anything = 1;
|
||||||
|
if (asn && (roa->asn == asn) && (roa->max_pxlen >= px->pxlen))
|
||||||
|
return ROA_VALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n.pxlen == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
n.pxlen--;
|
||||||
|
ip6_clrbit(&n.prefix, n.pxlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
return anything ? ROA_INVALID : ROA_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte
|
||||||
|
net_roa_check(rtable *tab, const net_addr *n, u32 asn)
|
||||||
|
{
|
||||||
|
if (tab->addr_type == NET_ROA4)
|
||||||
|
return net_roa4_check(tab, (const net_addr_ip4 *) n, asn);
|
||||||
|
else
|
||||||
|
return net_roa6_check(tab, (const net_addr_ip6 *) n, asn);
|
||||||
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
net_route(rtable *tab, const net_addr *n)
|
net_route(rtable *tab, const net_addr *n)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue