Commit 14922073 authored by Pavel Tvrdík's avatar Pavel Tvrdík
Browse files

Early integration of RTRlib into BIRD RPKI proto

lib/lists: add get_list_length(list *) function
parent 2c66ced1
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -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;
}
+1 −0
Original line number Diff line number Diff line
@@ -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
+42 −11
Original line number Diff line number Diff line
@@ -14,34 +14,65 @@ 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 {
rpki_proto:
   rpki_proto_start proto_name '{' rpki_proto_opts '}'

rpki_proto_start:
   proto_start RPKI {
     this_proto = proto_config_new(&proto_rpki, $1);
     init_list(&RPKI_CFG->cache_list);
   }
 ;

rpki_proto_opts:
   /* empty */
 | rpki_proto_opts rpki_proto_item ';'
 ;

rpki_proto_item:
   proto_item
 | CACHE SERVER ipa expr {
	RPKI_CFG->remote.ip = $3;
	RPKI_CFG->remote.port = $4;
 | 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_proto_opts:
rpki_cache_init:
   /* empty */ { this_rpki_cache = rpki_new_cache(); }
 ;

rpki_cache_opts:
   /* empty */
 | rpki_proto_opts rpki_proto_item ';'
 | rpki_cache_opts rpki_cache_opts_item ';'
 ;

rpki_proto:
   rpki_proto_start proto_name '{' rpki_proto_opts '}'
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

+125 −12
Original line number Diff line number Diff line
@@ -12,36 +12,149 @@

#define LOCAL_DEBUG

#include <stdlib.h>
#include <unistd.h>

#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;

  RPKI_TRACE(rpki, "------------- rpki_init -------------");

  log(L_DEBUG "------------- 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);

  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;

  log(L_DEBUG "------------- rpki_start -------------");
  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);

  RPKI_TRACE(rpki, "------------- rpki_shutdown -------------");

  log(L_DEBUG "------------- 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 -------------");
+28 −3
Original line number Diff line number Diff line
@@ -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_ */