mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-04-19 05:24:37 +00:00
RPKI: protocol version 2, loading ASPA
Implemented draft-ietf-sidrops-8210bis-16, interoperable with StayRTR development branches.
This commit is contained in:
parent
224fbe5980
commit
fa65e06372
@ -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,35 @@ struct pdu_error {
|
||||
* Error Diagnostic Message */
|
||||
} PACKED;
|
||||
|
||||
/*
|
||||
*0 8 16 24 31
|
||||
* .-------------------------------------------.
|
||||
* | Protocol | PDU | | |
|
||||
* | Version | Type | Flags | zero |
|
||||
* | 2 | 11 | | |
|
||||
* +-------------------------------------------+
|
||||
* | |
|
||||
* | Length |
|
||||
* | |
|
||||
* +-------------------------------------------+
|
||||
* | |
|
||||
* | Customer Autonomous System Number |
|
||||
* | |
|
||||
* +-------------------------------------------+
|
||||
* | |
|
||||
* ~ Provider Autonomous System Numbers ~
|
||||
* | |
|
||||
* ~-------------------------------------------~ */
|
||||
struct pdu_aspa {
|
||||
u8 ver;
|
||||
u8 type;
|
||||
u8 flags;
|
||||
u8 zero;
|
||||
u32 len;
|
||||
u32 customer_as_num;
|
||||
u32 provider_as_nums[0];
|
||||
} PACKED;
|
||||
|
||||
struct pdu_reset_query {
|
||||
u8 ver;
|
||||
u8 type;
|
||||
@ -230,9 +261,13 @@ 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,
|
||||
};
|
||||
|
||||
static inline int rpki_pdu_aspa_provider_asn_count(const struct pdu_aspa *pdu)
|
||||
{ return (pdu->len - sizeof(struct pdu_aspa)) / (sizeof(u32)); }
|
||||
|
||||
static int rpki_send_error_pdu(struct rpki_cache *cache, const enum pdu_error_type error_code, const u32 err_pdu_len, const struct pdu_header *erroneous_pdu, const char *fmt, ...);
|
||||
|
||||
static void
|
||||
@ -293,7 +328,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)
|
||||
{
|
||||
struct pdu_end_of_data_v1 *eod1 = (void *) pdu;
|
||||
eod1->expire_interval = ntohl(eod1->expire_interval);
|
||||
@ -329,6 +364,21 @@ rpki_pdu_to_host_byte_order(struct pdu_header *pdu)
|
||||
break;
|
||||
}
|
||||
|
||||
case ASPA:
|
||||
{
|
||||
struct pdu_aspa *aspa = (void *) pdu;
|
||||
int provider_asn_count = rpki_pdu_aspa_provider_asn_count(aspa);
|
||||
|
||||
/* Convert customer ASN */
|
||||
aspa->customer_as_num = ntohl(aspa->customer_as_num);
|
||||
|
||||
/* Convert provider ASNs */
|
||||
for (int i = 0; i < provider_asn_count ; i++)
|
||||
aspa->provider_as_nums[i] = ntohl(aspa->provider_as_nums[i]);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ROUTER_KEY:
|
||||
/* Router Key PDU is not supported yet */
|
||||
|
||||
@ -354,6 +404,9 @@ rpki_pdu_to_host_byte_order(struct pdu_header *pdu)
|
||||
static struct pdu_header *
|
||||
rpki_pdu_back_to_network_byte_order(struct pdu_header *out, const struct pdu_header *in)
|
||||
{
|
||||
/* Only valid for fixed-length PDUs */
|
||||
ASSERT_DIE(in->type != ERROR && in->type != ASPA);
|
||||
|
||||
memcpy(out, in, in->len);
|
||||
rpki_pdu_to_host_byte_order(out);
|
||||
return out;
|
||||
@ -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)
|
||||
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));
|
||||
@ -455,6 +508,25 @@ rpki_log_packet(struct rpki_cache *cache, const struct pdu_header *pdu, const en
|
||||
break;
|
||||
}
|
||||
|
||||
case ASPA:
|
||||
{
|
||||
const struct pdu_aspa *aspa = (void *) pdu;
|
||||
int provider_asn_count = rpki_pdu_aspa_provider_asn_count(aspa);
|
||||
|
||||
if (provider_asn_count <= 0)
|
||||
SAVE(bsnprintf(detail + strlen(detail), sizeof(detail) - strlen(detail),
|
||||
"%u transit", aspa->customer_as_num));
|
||||
else
|
||||
{
|
||||
SAVE(bsnprintf(detail + strlen(detail), sizeof(detail) - strlen(detail),
|
||||
"%u (providers", aspa->customer_as_num));
|
||||
for (int i = 0; i < provider_asn_count; i++)
|
||||
SAVE(bsnprintf(detail + strlen(detail), sizeof(detail) - strlen(detail),
|
||||
" %u%c", aspa->provider_as_nums[i], (i == provider_asn_count-1) ? ')' : ','));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
*detail = '\0';
|
||||
}
|
||||
@ -571,7 +643,9 @@ rpki_check_receive_packet(struct rpki_cache *cache, const struct pdu_header *pdu
|
||||
}
|
||||
}
|
||||
|
||||
if ((pdu->type >= PDU_TYPE_MAX) || (pdu->ver == RPKI_VERSION_0 && pdu->type == ROUTER_KEY))
|
||||
if ((pdu->type >= PDU_TYPE_MAX) ||
|
||||
(pdu->ver < RPKI_VERSION_1 && pdu->type == ROUTER_KEY) ||
|
||||
(pdu->ver < RPKI_VERSION_2 && pdu->type == ASPA))
|
||||
{
|
||||
rpki_send_error_pdu(cache, UNSUPPORTED_PDU_TYPE, pdu_len, pdu, "Unsupported PDU type %u received", pdu->type);
|
||||
return RPKI_ERROR;
|
||||
@ -797,6 +871,29 @@ 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;
|
||||
uint providers_length = aspa->len - sizeof(struct pdu_aspa);
|
||||
|
||||
if (!channel)
|
||||
{
|
||||
CACHE_TRACE(D_ROUTES, cache, "Skip AS%u, missing aspa channel", aspa->customer_as_num);
|
||||
return RPKI_ERROR;
|
||||
}
|
||||
|
||||
cache->last_rx_prefix = current_time();
|
||||
|
||||
if (aspa->flags & RPKI_ADD_FLAG)
|
||||
rpki_table_add_aspa(cache, channel, aspa->customer_as_num, aspa->provider_as_nums, providers_length);
|
||||
else
|
||||
rpki_table_remove_aspa(cache, channel, aspa->customer_as_num);
|
||||
|
||||
return RPKI_SUCCESS;
|
||||
}
|
||||
|
||||
static uint
|
||||
rpki_check_interval(struct rpki_cache *cache, const char *(check_fn)(uint), uint interval)
|
||||
{
|
||||
@ -822,7 +919,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)
|
||||
{
|
||||
if (!cf->keep_refresh_interval && rpki_check_interval(cache, rpki_check_refresh_interval, pdu->refresh_interval))
|
||||
cache->refresh_interval = pdu->refresh_interval;
|
||||
@ -849,6 +946,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 +1012,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);
|
||||
};
|
||||
|
@ -23,8 +23,10 @@
|
||||
* +4 bytes (Length of inserted text)
|
||||
* +800 bytes (UTF-8 text 400*2 bytes)
|
||||
* ------------
|
||||
* = 848 bytes (Maximal expected PDU size) */
|
||||
#define RPKI_PDU_MAX_LEN 848
|
||||
* = 848 bytes (Maximal expected PDU size)
|
||||
*
|
||||
* Received ASPA PDU can have any size, so let's start with 4k */
|
||||
#define RPKI_PDU_MAX_LEN 4096
|
||||
|
||||
/* RX buffer size has a great impact to scheduler granularity */
|
||||
#define RPKI_RX_BUFFER_SIZE 4096
|
||||
|
@ -140,6 +140,37 @@ 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, void *providers, uint providers_length)
|
||||
{
|
||||
struct rpki_proto *p = cache->p;
|
||||
|
||||
net_addr_union n = { .aspa = NET_ADDR_ASPA(customer) };
|
||||
rta a0 = {
|
||||
.pref = channel->preference,
|
||||
.source = RTS_RPKI,
|
||||
.scope = SCOPE_UNIVERSE,
|
||||
.dest = RTD_NONE,
|
||||
};
|
||||
|
||||
ea_set_attr_data(&a0.eattrs, tmp_linpool, EA_ASPA_PROVIDERS, 0,
|
||||
EAF_TYPE_INT_SET, providers, providers_length);
|
||||
|
||||
rta *a = rta_lookup(&a0);
|
||||
rte *e = rte_get_temp(a, p->p.main_source);
|
||||
|
||||
rte_update2(channel, &n.n, e, e->src);
|
||||
}
|
||||
|
||||
void
|
||||
rpki_table_remove_aspa(struct rpki_cache *cache, struct channel *channel, u32 customer)
|
||||
{
|
||||
struct rpki_proto *p = cache->p;
|
||||
net_addr_union n = { .aspa = NET_ADDR_ASPA(customer) };
|
||||
rte_update2(channel, &n.n, NULL, p->p.main_source);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* RPKI Protocol Logic
|
||||
@ -773,7 +804,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)
|
||||
@ -795,6 +827,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;
|
||||
}
|
||||
@ -908,6 +941,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");
|
||||
}
|
||||
}
|
||||
|
||||
@ -979,7 +1017,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,
|
||||
|
@ -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,9 @@ 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, void *providers, uint providers_length);
|
||||
void rpki_table_remove_aspa(struct rpki_cache *cache, struct channel *channel, u32 customer);
|
||||
|
||||
|
||||
/*
|
||||
* RPKI Protocol Logic
|
||||
@ -110,6 +114,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() */
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user