diff --git a/lib/lists.c b/lib/lists.c index d323a4b6..0606d265 100644 --- a/lib/lists.c +++ b/lib/lists.c @@ -175,3 +175,19 @@ add_tail_list(list *to, list *l) q->next = (node *) &to->null; to->tail = q; } + +/** + * get_list_size - get count of items in list + * @l: list + */ +LIST_INLINE uint +get_list_length(list *l) +{ + unsigned int size = 0; + node *n; + WALK_LIST(n, *l) + { + size++; + } + return size; +} diff --git a/lib/lists.h b/lib/lists.h index 80a4dc93..50ce3063 100644 --- a/lib/lists.h +++ b/lib/lists.h @@ -65,6 +65,7 @@ void rem2_node(node *); void add_tail_list(list *, list *); void init_list(list *); void insert_node(node *, node *); +uint get_list_length(list *); #endif #endif diff --git a/proto/rpki/config.Y b/proto/rpki/config.Y index b45e3a1d..1e6b4a24 100644 --- a/proto/rpki/config.Y +++ b/proto/rpki/config.Y @@ -14,25 +14,24 @@ CF_DEFINES #define RPKI_CFG ((struct rpki_config *) this_proto) +static struct rpki_cache *this_rpki_cache; + CF_DECLS -CF_KEYWORDS(RPKI, CACHE, SERVER, SERVERS) +CF_KEYWORDS(RPKI, CACHE, LIST, PREFERENCE) CF_GRAMMAR CF_ADDTO(proto, rpki_proto) -rpki_proto_start: proto_start RPKI { - this_proto = proto_config_new(&proto_rpki, $1); - } - ; +rpki_proto: + rpki_proto_start proto_name '{' rpki_proto_opts '}' -rpki_proto_item: - proto_item - | CACHE SERVER ipa expr { - RPKI_CFG->remote.ip = $3; - RPKI_CFG->remote.port = $4; - } +rpki_proto_start: + proto_start RPKI { + this_proto = proto_config_new(&proto_rpki, $1); + init_list(&RPKI_CFG->cache_list); + } ; rpki_proto_opts: @@ -40,8 +39,40 @@ rpki_proto_opts: | rpki_proto_opts rpki_proto_item ';' ; -rpki_proto: - rpki_proto_start proto_name '{' rpki_proto_opts '}' +rpki_proto_item: + proto_item + | CACHE LIST '{' rpki_cache_list '}' + ; + +rpki_cache_list: + rpki_cache_list_item + | rpki_cache_list ',' rpki_cache_list_item + ; + +rpki_cache_list_item: + rpki_cache_init text rpki_cache_opts { + this_rpki_cache->full_domain_name = $2; + add_tail(&RPKI_CFG->cache_list, &this_rpki_cache->n); + } + | rpki_cache_init ipa rpki_cache_opts { + this_rpki_cache->ip = $2; + add_tail(&RPKI_CFG->cache_list, &this_rpki_cache->n); + } + ; + +rpki_cache_init: + /* empty */ { this_rpki_cache = rpki_new_cache(); } + ; + +rpki_cache_opts: + /* empty */ + | rpki_cache_opts rpki_cache_opts_item ';' + ; + +rpki_cache_opts_item: + PORT expr { bsnprintf(this_rpki_cache->port, RPKI_PORT_MAX_LENGTH_STR, "%u", (u16) $2); } + | PREFERENCE expr { this_rpki_cache->preference = $2; } + ; CF_CODE diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c index 301769f3..4d665321 100644 --- a/proto/rpki/rpki.c +++ b/proto/rpki/rpki.c @@ -12,36 +12,149 @@ #define LOCAL_DEBUG +#include +#include + #include "proto/rpki/rpki.h" +#include "lib/socket.h" + +struct proto *ugly_hack_to_get_proto; + +static void status_cb(const struct rtr_mgr_group *group, enum rtr_mgr_status status, const struct rtr_socket *socket, void *data) +{ + struct rpki_proto *rpki = data; + if(status == RTR_MGR_ERROR) + { + RPKI_TRACE(rpki, "Error -> Should we here stop the protocol?"); /* FIXME */ + } + + RPKI_TRACE(rpki, "Status: %s\t%s", rtr_mgr_status_to_str(status), rtr_state_to_str(socket->state)); +} + +static void update_cb(struct pfx_table *p, const struct pfx_record rec, const bool added) +{ + /* FIXME: update_cb() should have void *data attribute, same like status_cb() */ + struct proto *P = ugly_hack_to_get_proto; + struct rpki_proto *rpki = (struct rpki_proto *) P; + + ip4_addr ip4 = {}; + ip6_addr ip6 = {}; + char ip[INET6_ADDRSTRLEN]; + if (rec.prefix.ver == RTRLIB_IPV4) + { + ip4 = ipa_from_u32(rec.prefix.u.addr4.addr); + ip4_ntop(ip4, ip); + } + else + { + ip6 = ip6_build(rec.prefix.u.addr6.addr[0], rec.prefix.u.addr6.addr[1], rec.prefix.u.addr6.addr[2], rec.prefix.u.addr6.addr[3]); + ip6_ntop(ip6, ip); + } + + if(added) + { + RPKI_TRACE(rpki, "+++ %45s/%u-%-3u \tASN: %10u", ip, rec.min_len, rec.max_len, rec.asn); +// P->rte_insert(); + } + else + { + RPKI_TRACE(rpki, "--- %45s/%u-%-3u \tASN: %10u", ip, rec.min_len, rec.max_len, rec.asn); +// P->rte_remove(); + } +} static struct proto * -rpki_init(struct proto_config *c) +rpki_init(struct proto_config *C) { - struct proto *p = proto_new(c, sizeof(struct rpki_proto)); + struct proto *P = proto_new(C, sizeof(struct rpki_proto)); + struct rpki_proto *rpki = (struct rpki_proto *) P; + struct rpki_config *cf = (struct rpki_config *) C; - log(L_DEBUG "------------- rpki_init -------------"); + RPKI_TRACE(rpki, "------------- rpki_init -------------"); + + ugly_hack_to_get_proto = P; /* TODO: Add defaults */ - return p; + return P; +} + +struct rpki_cache * +rpki_new_cache(void) +{ + struct rpki_cache *cache = (struct rpki_cache *)cfg_allocz(sizeof(struct rpki_cache)); + strcpy(cache->port, RPKI_PORT); + return cache; +} + +static void +normalize_fulfillment_of_cache(struct rpki_cache *cache) +{ + if (cache->full_domain_name == NULL) + { + bsnprintf(cache->ip_buf, INET6_ADDRSTRLEN, "%I", cache->ip); + cache->full_domain_name = cache->ip_buf; + } + + bzero(&cache->rtr_tcp, sizeof(struct rtr_socket)); + bzero(&cache->tcp_config, sizeof(struct tr_tcp_config)); + bzero(&cache->tr_tcp, sizeof(struct tr_socket)); } static int -rpki_start(struct proto *p) +rpki_start(struct proto *P) { - struct proto_rpki *rpki = (struct proto_rpki *) p; - struct rpki_config *cf = (struct rpki_config *) (p->cf); + struct rpki_proto *rpki = (struct rpki_proto *) P; + struct rpki_config *cf = (struct rpki_config *) (P->cf); - log(L_DEBUG "------------- rpki_start -------------"); + RPKI_TRACE(rpki, "------------- rpki_start -------------"); + + rpki->rtr_groups_len = get_list_length(&cf->cache_list); + rpki->rtr_groups = mb_allocz(P->pool, rpki->rtr_groups_len * sizeof(struct rtr_mgr_group)); + struct rtr_mgr_group *groups = rpki->rtr_groups; + + uint idx = 0; + struct rpki_cache *cache; + WALK_LIST(cache, cf->cache_list) + { + struct tr_tcp_config *tcp_config = &cache->tcp_config; + struct rtr_socket *rtr_tcp = &cache->rtr_tcp; + struct tr_socket *tr_tcp = &cache->tr_tcp; + + normalize_fulfillment_of_cache(cache); + + tcp_config->host = cache->full_domain_name; + tcp_config->port = cache->port; + tr_tcp_init(tcp_config, tr_tcp); + + // create an rtr_socket and associate it with the transport socket + rtr_tcp->tr_socket = tr_tcp; + + groups[idx].sockets = mb_allocz(P->pool, 1 * sizeof(struct rtr_socket *)); + groups[idx].sockets_len = 1; + groups[idx].sockets[0] = rtr_tcp; + groups[idx].preference = cache->preference; + + idx++; + } + + rpki->rtr_conf = rtr_mgr_init(groups, rpki->rtr_groups_len, 30, 520, &update_cb, NULL, &status_cb, rpki); + rtr_mgr_start(rpki->rtr_conf); return PS_UP; } static int -rpki_shutdown(struct proto *p) +rpki_shutdown(struct proto *P) { - struct proto_rpki *rp = (struct proto_rpki *) p; + struct rpki_proto *rpki = (struct rpki_proto *) P; + struct rpki_config *cf = (struct rpki_config *) (P->cf); - log(L_DEBUG "------------- rpki_shutdown -------------"); + RPKI_TRACE(rpki, "------------- rpki_shutdown -------------"); + + rtr_mgr_stop(rpki->rtr_conf); + rtr_mgr_free(rpki->rtr_conf); + + /* TODO: fix memory leaks created by start->disable->enable rpki protocol */ return PS_DOWN; } @@ -49,7 +162,7 @@ rpki_shutdown(struct proto *p) static int rpki_reconfigure(struct proto *p, struct proto_config *c) { - struct proto_rpki *rpki = (struct proto_rpki *) p; + struct rpki_proto *rpki = (struct rpki_proto *) p; struct rpki_config *new = (struct rpki_config *) c; log(L_DEBUG "------------- rpki_reconfigure -------------"); diff --git a/proto/rpki/rpki.h b/proto/rpki/rpki.h index 6e79053a..eaa94c0a 100644 --- a/proto/rpki/rpki.h +++ b/proto/rpki/rpki.h @@ -9,22 +9,47 @@ #ifndef _BIRD_RPKI_H_ #define _BIRD_RPKI_H_ +#include "rtrlib/rtrlib.h" + #include "nest/bird.h" #include "nest/protocol.h" -struct cache_server { +#define RPKI_PORT "8282" +#define RPKI_PORT_MAX_LENGTH_STR 6 + +#define RPKI_TRACE(rpki, msg, args...) \ + do { \ + if (rpki->p.debug) \ + log(L_TRACE "%s: " msg, rpki->p.name , ## args ); \ + } while(0) + +struct rpki_cache { + node n; /* in struct rpki_config.cache_list */ ip_addr ip; - u16 port; + char *full_domain_name; + char port[RPKI_PORT_MAX_LENGTH_STR]; /* the highest port is "65535" */ + u8 preference; + + /* below are private variables */ + + struct rtr_socket rtr_tcp; + struct tr_socket tr_tcp; + struct tr_tcp_config tcp_config; + char ip_buf[INET6_ADDRSTRLEN]; }; struct rpki_config { struct proto_config c; - struct cache_server remote; + list cache_list; /* (struct rpki_cache *) */ }; struct rpki_proto { struct proto p; + struct rtr_mgr_config *rtr_conf; + struct rtr_mgr_group *rtr_groups; + uint rtr_groups_len; }; +struct rpki_cache *rpki_new_cache(void); #endif /* _BIRD_RPKI_H_ */