0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-10-19 02:18:43 +00:00
bird/nest/mrtdump.c
2015-07-28 15:04:03 +02:00

160 lines
4.2 KiB
C

/*
* BIRD -- Multi-Threaded Routing Toolkit (MRT) Routing Information Export Format
*
* (c) 2015 CZ.NIC z.s.p.o.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include "nest/mrtdump.h"
void
mrt_msg_init(struct mrt_msg *msg, pool *mem_pool)
{
msg->mem_pool = mem_pool;
msg->msg_capacity = MRT_MSG_DEFAULT_CAPACITY;
msg->msg_length = 0;
msg->msg = mb_alloc(msg->mem_pool, msg->msg_capacity);
}
void
mrt_msg_free(struct mrt_msg *msg)
{
mb_free(msg->msg);
}
static byte *
mrt_peer_index_table_get_peer_count(struct mrt_peer_index_table *pit_msg)
{
struct mrt_msg * msg = pit_msg->msg;
uint collector_bgp_id_size = 4;
uint name_length_size = 2;
uint name_size = pit_msg->name_length;
uint peer_count_offset = collector_bgp_id_size + name_length_size + name_size;
return &(msg->msg[peer_count_offset]);
}
static void
mrt_grow_msg_buffer(struct mrt_msg * msg, size_t min_required_capacity)
{
msg->msg_capacity *= 2;
if (min_required_capacity > msg->msg_capacity)
msg->msg_capacity = min_required_capacity;
msg->msg = mb_realloc(msg->msg, msg->msg_capacity);
}
static void
mrt_write_to_msg(struct mrt_msg * msg, const void *data, size_t data_size)
{
if (data_size == 0)
return;
u32 i;
for (i = 0; i < data_size; i++)
debug("%02X ", ((byte*)data)[i]);
debug("| ");
size_t required_size = data_size + msg->msg_length;
if (msg->msg_capacity < required_size)
mrt_grow_msg_buffer(msg, required_size);
memcpy(&msg->msg[msg->msg_length], data, data_size);
msg->msg_length += data_size;
}
#define mrt_write_to_msg_(msg, data) mrt_write_to_msg(msg, &data, sizeof(data))
void
mrt_peer_index_table_init(struct mrt_peer_index_table *pit_msg, u32 collector_bgp_id, const char *name)
{
struct mrt_msg * msg = pit_msg->msg;
pit_msg->peer_count = 0;
pit_msg->name_length = strlen(name);
mrt_write_to_msg_(msg, collector_bgp_id);
mrt_write_to_msg_(msg, pit_msg->name_length);
mrt_write_to_msg(msg, name, pit_msg->name_length);
mrt_write_to_msg_(msg, pit_msg->peer_count);
debug("\n");
}
static void
mrt_peer_index_table_inc_peer_count(struct mrt_peer_index_table *pit_msg)
{
pit_msg->peer_count++;
byte *peer_count = mrt_peer_index_table_get_peer_count(pit_msg);
put_u16(peer_count, pit_msg->peer_count);
}
void
mrt_peer_index_table_add_peer(struct mrt_peer_index_table *pit_msg, u32 peer_bgp_id, ip_addr *peer_ip_addr, u32 peer_as)
{
struct mrt_msg * msg = pit_msg->msg;
u8 peer_type = PEER_TYPE_AS_32BIT;
if (sizeof(*peer_ip_addr) > sizeof(ip4_addr))
peer_type |= PEER_TYPE_IPV6;
mrt_write_to_msg_(msg, peer_type);
mrt_write_to_msg_(msg, peer_bgp_id);
mrt_write_to_msg_(msg, *peer_ip_addr);
mrt_write_to_msg_(msg, peer_as);
mrt_peer_index_table_inc_peer_count(pit_msg);
debug("\n");
}
void
mrt_rib_table_init(struct mrt_rib_table *rt_msg, u32 sequence_number, u8 prefix_length, ip_addr *prefix)
{
struct mrt_msg *msg = rt_msg->msg;
rt_msg->entry_count = 0;
mrt_write_to_msg_(msg, sequence_number);
mrt_write_to_msg_(msg, prefix_length);
mrt_write_to_msg_(msg, *prefix);
mrt_write_to_msg_(msg, rt_msg->entry_count);
debug("\n");
}
static byte *
mrt_rib_table_get_entry_count(struct mrt_rib_table *rt_msg)
{
struct mrt_msg *msg = rt_msg->msg;
u32 sequence_number_size = 4;
u32 prefix_length_size = 1;
u32 prefix_size = 4;
if (rt_msg->type == RIB_IPV4_UNICAST)
prefix_size = 4;
else if (rt_msg->type == RIB_IPV6_UNICAST)
prefix_size = 16;
else
bug("mrt_rib_table_get_entry_count: unknown RIB type!");
u32 offset = sequence_number_size + prefix_length_size + prefix_size;
return &msg->msg[offset];
}
static void
mrt_rib_table_inc_entry_count(struct mrt_rib_table *rt_msg)
{
rt_msg->entry_count++;
byte *entry_count = mrt_rib_table_get_entry_count(rt_msg);
put_u16(entry_count, rt_msg->entry_count);
}
void
mrt_rib_table_add_entry(struct mrt_rib_table *rt_msg, const struct mrt_rib_entry *rib)
{
struct mrt_msg *msg = rt_msg->msg;
mrt_write_to_msg_(msg, rib->peer_index);
mrt_write_to_msg_(msg, rib->originated_time);
mrt_write_to_msg_(msg, rib->attributes_length);
mrt_write_to_msg(msg, rib->attributes, rib->attributes_length);
mrt_rib_table_inc_entry_count(rt_msg);
debug("\n");
}