diff options
author | Pavel Tvrdík <pawel.tvrdik@gmail.com> | 2016-01-20 15:38:37 +0100 |
---|---|---|
committer | Pavel Tvrdík <pawel.tvrdik@gmail.com> | 2016-01-20 16:46:58 +0100 |
commit | 0264ccf6f4acaea5313dee2cd3bc3bdb28c74f60 (patch) | |
tree | ea9267e1209f85c51a266bb8950edff418586b58 /nest | |
parent | cb1bd816db5b69acb8c6f72211d13f987a494304 (diff) |
Rewrite roa_check() for integrated BIRD
Thanks to Ondrej Zajicek for his support with writing this code.
Diffstat (limited to 'nest')
-rw-r--r-- | nest/route.h | 6 | ||||
-rw-r--r-- | nest/rt-fib.c | 9 | ||||
-rw-r--r-- | nest/rt-table.c | 71 |
3 files changed, 84 insertions, 2 deletions
diff --git a/nest/route.h b/nest/route.h index c6e9cb41..1cce3c01 100644 --- a/nest/route.h +++ b/nest/route.h @@ -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_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_route(struct fib *, const net_addr *); /* Longest-match routing lookup */ 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_unlock_table(rtable *); 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_get(rtable *tab, net_addr *addr) { return (net *) fib_get(&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, 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_get_temp(struct rta *); diff --git a/nest/rt-fib.c b/nest/rt-fib.c index 8bf67f8d..55387c5e 100644 --- a/nest/rt-fib.c +++ b/nest/rt-fib.c @@ -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 * @f: FIB to search in diff --git a/nest/rt-table.c b/nest/rt-table.c index 400b9d9c..f164ecd9 100644 --- a/nest/rt-table.c +++ b/nest/rt-table.c @@ -100,6 +100,77 @@ net_route_ip6(struct fib *f, net_addr_ip6 *n) 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 * net_route(rtable *tab, const net_addr *n) { |