diff --git a/nest/proto.c b/nest/proto.c index 88f4813e..b3ff62a9 100644 --- a/nest/proto.c +++ b/nest/proto.c @@ -64,7 +64,7 @@ static inline int channel_is_active(struct channel *c) { return (c->channel_state == CS_START) || (c->channel_state == CS_UP); } static inline int channel_reloadable(struct channel *c) -{ return c->proto->reload_routes && c->reloadable; } +{return c->proto->reload_routes && c->reloadable; } static inline void channel_log_state_change(struct channel *c) @@ -375,6 +375,7 @@ channel_roa_subscribe(struct channel *c, rtable *tab, int dir) add_tail(&c->roa_subscriptions, &s->roa_node); } + static void channel_roa_unsubscribe(struct roa_subscription *s) { @@ -422,6 +423,11 @@ channel_roa_subscribe_filter(struct channel *c, int dir) found = 1; break; + case FI_ASPA_CHECK_EXPLICIT: + tab = fi->i_FI_ASPA_CHECK_EXPLICIT.rtc->table; + if (valid) channel_roa_subscribe(c, tab, dir); + found = 1; + break; default: break; } diff --git a/proto/rpki/packets.c b/proto/rpki/packets.c index d246dd50..2af8c7aa 100644 --- a/proto/rpki/packets.c +++ b/proto/rpki/packets.c @@ -62,6 +62,7 @@ enum pdu_type { CACHE_RESET = 8, ROUTER_KEY = 9, ERROR = 10, + ASPA = 11, PDU_TYPE_MAX }; @@ -76,7 +77,8 @@ static const char *str_pdu_type_[] = { [END_OF_DATA] = "End of Data", [CACHE_RESET] = "Cache Reset", [ROUTER_KEY] = "Router Key", - [ERROR] = "Error" + [ERROR] = "Error", + [ASPA] = "ASPA" }; static const char *str_pdu_type(uint type) { @@ -193,6 +195,41 @@ struct pdu_error { * Error Diagnostic Message */ } PACKED; +/* +* 0 8 16 24 31 +* .-------------------------------------------. +* | Protocol | PDU | | +* | Version | Type | zero | +* | 2 | 11 | | +* +-------------------------------------------+ +* | | +* | Length | +* | | +* +-------------------------------------------+ +* | | | | +* | Flags | AFI Flags| Provider AS Count | +* | | | | +* +-------------------------------------------+ +* | | +* | Customer Autonomous System Number | +* | | +* +-------------------------------------------+ +* | | +* ~ Provider Autonomous System Numbers ~ +* | | +* ~-------------------------------------------~ */ +struct pdu_aspa { + u8 ver; + u8 type; + u16 zero; + u32 len; + u8 flags; + u8 afi_flags; /* must be 11000000 in version 2 */ + u16 provider_as_count; + u32 customer_as_num; + u32 provider_as_nums[0]; +} PACKED; + struct pdu_reset_query { u8 ver; u8 type; @@ -230,6 +267,7 @@ static const size_t min_pdu_size[] = { [END_OF_DATA] = sizeof(struct pdu_end_of_data_v0), [CACHE_RESET] = sizeof(struct pdu_cache_response), [ROUTER_KEY] = sizeof(struct pdu_header), /* FIXME */ + [ASPA] = sizeof(struct pdu_aspa), [ERROR] = 16, }; @@ -293,7 +331,7 @@ rpki_pdu_to_host_byte_order(struct pdu_header *pdu) struct pdu_end_of_data_v0 *eod0 = (void *) pdu; eod0->serial_num = ntohl(eod0->serial_num); /* Same either for version 1 */ - if (pdu->ver == RPKI_VERSION_1) + if (pdu->ver != RPKI_VERSION_0) //TODO version { struct pdu_end_of_data_v1 *eod1 = (void *) pdu; eod1->expire_interval = ntohl(eod1->expire_interval); @@ -328,6 +366,21 @@ rpki_pdu_to_host_byte_order(struct pdu_header *pdu) *err_text_len = htonl(*err_text_len); break; } + + case ASPA: + { + struct pdu_aspa *aspa = (void *) pdu; + aspa->customer_as_num = ntohl(aspa->customer_as_num); + + aspa->provider_as_count = ntohl(aspa->provider_as_count); + /* Count provider_as_num_count from length and compare */ + int provider_num_counted = (aspa->len - sizeof(struct pdu_aspa)) / (sizeof(u32)); + + for (int i = 0; i < provider_num_counted ; i++) + { + aspa->provider_as_nums[i] = ntohl(aspa->provider_as_nums[i]); + } + } case ROUTER_KEY: /* Router Key PDU is not supported yet */ @@ -364,7 +417,7 @@ rpki_log_packet(struct rpki_cache *cache, const struct pdu_header *pdu, const en { if (!(cache->p->p.debug & D_PACKETS)) return; - + log("packet arrived, version %i", pdu->ver); const char *str_type = str_pdu_type(pdu->type); char detail[256]; @@ -387,7 +440,7 @@ rpki_log_packet(struct rpki_cache *cache, const struct pdu_header *pdu, const en case END_OF_DATA: { const struct pdu_end_of_data_v1 *eod = (void *) pdu; - if (eod->ver == RPKI_VERSION_1) + if (eod->ver != RPKI_VERSION_0) //TODO versions SAVE(bsnprintf(detail, sizeof(detail), "(session id: %u, serial number: %u, refresh: %us, retry: %us, expire: %us)", eod->session_id, eod->serial_num, eod->refresh_interval, eod->retry_interval, eod->expire_interval)); else SAVE(bsnprintf(detail, sizeof(detail), "(session id: %u, serial number: %u)", eod->session_id, eod->serial_num)); @@ -729,8 +782,8 @@ rpki_prefix_pdu_2_net_addr(const struct pdu_header *pdu, net_addr_union *n) static int rpki_handle_prefix_pdu(struct rpki_cache *cache, const struct pdu_header *pdu) { + log("prefix pdu"); const struct rpki_config *cf = (void *) cache->p->p.cf; - const enum pdu_type type = pdu->type; ASSERT(type == IPV4_PREFIX || type == IPV6_PREFIX); @@ -797,6 +850,32 @@ rpki_handle_prefix_pdu(struct rpki_cache *cache, const struct pdu_header *pdu) return RPKI_SUCCESS; } +static int +rpki_handle_aspa_pdu(struct rpki_cache *cache, const struct pdu_header *pdu) +{ + struct pdu_aspa *aspa = (void *) pdu; + struct channel *channel = cache->p->aspa_channel; + + if (!channel) + { + CACHE_TRACE(D_ROUTES, cache, "Skip %i, missing %s channel", aspa->customer_as_num, "aspa"); + return RPKI_ERROR; + } + cache->last_rx_prefix = current_time(); + + u32 customer_as_num = aspa->customer_as_num; + + /* We reuse pdu memory instead of memcopy all providers numbers to new adata struct. + * We can do that, because aspa pdu will not be used anymore and the data will be memcopied in next functions anyway. + */ + struct adata *providers = SKIP_BACK(adata, data, &aspa->provider_as_nums); + providers->length = aspa->len - sizeof(struct pdu_aspa); + + rpki_table_add_aspa(cache, channel, customer_as_num, providers); + + return RPKI_SUCCESS; +} + static uint rpki_check_interval(struct rpki_cache *cache, const char *(check_fn)(uint), uint interval) { @@ -822,7 +901,7 @@ rpki_handle_end_of_data_pdu(struct rpki_cache *cache, const struct pdu_end_of_da return; } - if (pdu->ver == RPKI_VERSION_1) + if (pdu->ver != RPKI_VERSION_0) //TODO versions { if (!cf->keep_refresh_interval && rpki_check_interval(cache, rpki_check_refresh_interval, pdu->refresh_interval)) cache->refresh_interval = pdu->refresh_interval; @@ -849,6 +928,8 @@ rpki_handle_end_of_data_pdu(struct rpki_cache *cache, const struct pdu_end_of_da rt_refresh_end(cache->p->roa4_channel->table, cache->p->roa4_channel); if (cache->p->roa6_channel) rt_refresh_end(cache->p->roa6_channel->table, cache->p->roa6_channel); + if (cache->p->aspa_channel) + rt_refresh_end(cache->p->aspa_channel->table, cache->p->aspa_channel); } cache->last_update = current_time(); @@ -913,6 +994,10 @@ rpki_rx_packet(struct rpki_cache *cache, struct pdu_header *pdu) /* TODO: Implement Router Key PDU handling */ break; + case ASPA: + rpki_handle_aspa_pdu(cache, (void *) pdu); + break; + default: CACHE_TRACE(D_PACKETS, cache, "Received unsupported type (%u)", pdu->type); }; diff --git a/proto/rpki/rpki.c b/proto/rpki/rpki.c index 4ec48e3b..bbeb016c 100644 --- a/proto/rpki/rpki.c +++ b/proto/rpki/rpki.c @@ -140,6 +140,36 @@ rpki_table_remove_roa(struct rpki_cache *cache, struct channel *channel, const n rte_update2(channel, &pfxr->n, NULL, p->p.main_source); } +void +rpki_table_add_aspa(struct rpki_cache *cache, struct channel *channel, + u32 customer, adata *providers) +{ + struct rpki_proto *p = cache->p; + + net_addr_union n = { .aspa = NET_ADDR_ASPA(customer) }; + + ea_list *ea = alloca(sizeof(ea_list) + sizeof(eattr)); + *ea = (ea_list) { .flags = EALF_SORTED, .count = 1, }; + ea->attrs[0] = (eattr) { + .id = EA_ASPA_PROVIDERS, + .type = EAF_TYPE_INT_SET, + .u.ptr = providers, + }; + + rta a0 = { + .pref = channel->preference, + .source = RTS_RPKI, + .scope = SCOPE_UNIVERSE, + .dest = RTD_NONE, + .eattrs = ea, + }; + + rta *a = rta_lookup(&a0); + rte *e = rte_get_temp(a, p->p.main_source); + + rte_update2(channel, &n.n, e, e->src); +} + /* * RPKI Protocol Logic @@ -755,7 +785,8 @@ rpki_reconfigure(struct proto *P, struct proto_config *CF) struct rpki_cache *cache = p->cache; if (!proto_configure_channel(&p->p, &p->roa4_channel, proto_cf_find_channel(CF, NET_ROA4)) || - !proto_configure_channel(&p->p, &p->roa6_channel, proto_cf_find_channel(CF, NET_ROA6))) + !proto_configure_channel(&p->p, &p->roa6_channel, proto_cf_find_channel(CF, NET_ROA6)) || + !proto_configure_channel(&p->p, &p->aspa_channel, proto_cf_find_channel(CF, NET_ASPA))) return NEED_RESTART; if (rpki_reconfigure_cache(p, cache, new, old) != SUCCESSFUL_RECONF) @@ -777,6 +808,7 @@ rpki_init(struct proto_config *CF) proto_configure_channel(&p->p, &p->roa4_channel, proto_cf_find_channel(CF, NET_ROA4)); proto_configure_channel(&p->p, &p->roa6_channel, proto_cf_find_channel(CF, NET_ROA6)); + proto_configure_channel(&p->p, &p->aspa_channel, proto_cf_find_channel(CF, NET_ASPA)); return P; } @@ -886,6 +918,11 @@ rpki_show_proto_info(struct proto *P) channel_show_info(p->roa6_channel); else cli_msg(-1006, " No roa6 channel"); + + if (p->aspa_channel) + channel_show_info(p->aspa_channel); + else + cli_msg(-1006, " No aspa channel"); } } @@ -957,7 +994,7 @@ struct protocol proto_rpki = { .init = rpki_init, .start = rpki_start, .postconfig = rpki_postconfig, - .channel_mask = (NB_ROA4 | NB_ROA6), + .channel_mask = (NB_ROA4 | NB_ROA6 | NB_ASPA), .show_proto_info = rpki_show_proto_info, .shutdown = rpki_shutdown, .copy_config = rpki_copy_config, diff --git a/proto/rpki/rpki.h b/proto/rpki/rpki.h index e67eb0e3..f9338c8e 100644 --- a/proto/rpki/rpki.h +++ b/proto/rpki/rpki.h @@ -29,7 +29,8 @@ #define RPKI_VERSION_0 0 #define RPKI_VERSION_1 1 -#define RPKI_MAX_VERSION RPKI_VERSION_1 +#define RPKI_VERSION_2 2 +#define RPKI_MAX_VERSION RPKI_VERSION_2 /* @@ -83,6 +84,8 @@ const char *rpki_cache_state_to_str(enum rpki_cache_state state); void rpki_table_add_roa(struct rpki_cache *cache, struct channel *channel, const net_addr_union *pfxr); void rpki_table_remove_roa(struct rpki_cache *cache, struct channel *channel, const net_addr_union *pfxr); +void rpki_table_add_aspa(struct rpki_cache *cache, struct channel *channel, u32 customer, adata *providers); + /* * RPKI Protocol Logic @@ -110,6 +113,7 @@ struct rpki_proto { struct channel *roa4_channel; struct channel *roa6_channel; + struct channel *aspa_channel; u8 refresh_channels; /* For non-incremental updates using rt_refresh_begin(), rt_refresh_end() */ };