]> git.ipfire.org Git - thirdparty/bird.git/commitdiff
RPKI: refactore and improve
authorPavel Tvrdík <pawel.tvrdik@gmail.cz>
Wed, 7 Oct 2015 13:50:43 +0000 (15:50 +0200)
committerPavel Tvrdík <pawel.tvrdik@gmail.cz>
Wed, 7 Oct 2015 13:54:20 +0000 (15:54 +0200)
Takes into account a preferences of caches.
Fixes many bugs.

Configuration example:

    roa table roatable;

    protocol rpki {
      debug all;
      roa table roatable;

      cache "rpki-validator.realmv6.org" {
          port 3233;
          preference 1;
      };
      cache 127.0.0.1 {
          preference 2;
      };
      cache "rpki-validator.realmv6.org";
    }

nest/proto.c
proto/rpki/config.Y
proto/rpki/rpki.c
proto/rpki/rpki.h
proto/rpki/rtrlib-mockup.h

index 55bb0c77540f2bec75e4e2d0e1250cf30d7c982b..b2d5f0cba9f8d5d7fc3f83ed8245fa430e28d8af 100644 (file)
@@ -877,6 +877,7 @@ proto_build(struct protocol *p)
 
 /* FIXME: convert this call to some protocol hook */
 extern void bfd_init_all(void);
+extern void rpki_init_all(void);
 
 /**
  * protos_build - build a protocol list
index 757a94f6c15f4a5cd48561eb0adb80fc946e8697..f86be125d660796cdacc21f873f485b100eb8283 100644 (file)
@@ -18,29 +18,37 @@ static struct rpki_cache *this_rpki_cache;
 
 CF_DECLS
 
-CF_KEYWORDS(RPKI, CACHE, LIST, PREFERENCE, RTRLIB)
+CF_KEYWORDS(RPKI, CACHE, LIST, PREFERENCE)
 
 CF_GRAMMAR
 
 CF_ADDTO(proto, rpki_proto)
 
 rpki_proto:
-   rpki_proto_start proto_name '{' rpki_proto_opts '}' {
-     if (RPKI_CFG->roa_table_cf == NULL)
-     {
-       cf_error("For the RPKI protocol must be specified a roa table");
-     }
-   }
+   rpki_proto_start proto_name '{' rpki_proto_opts '}' rpki_proto_finish
  ;
 
 rpki_proto_start:
    proto_start RPKI {
      this_proto = proto_config_new(&proto_rpki, $1);
      init_list(&RPKI_CFG->cache_list);
-     RPKI_CFG->rtrlib_path = RPKI_RTRLIB_PATH;
    }
  ;
 
+rpki_proto_finish:
+{
+  if (RPKI_CFG->roa_table_cf == NULL)
+  {
+    cf_error("For the RPKI protocol must be specified a roa table");
+  }
+
+  char *rpki_err_buf = rpki_load_rtrlib();
+  if (rpki_err_buf != NULL)
+  {
+    cf_error("Cannot use a RPKI protocol: %s", rpki_err_buf);
+  }
+};
+
 rpki_proto_opts:
    /* empty */
  | rpki_proto_opts rpki_proto_item ';'
@@ -48,29 +56,32 @@ rpki_proto_opts:
 
 rpki_proto_item:
    proto_item
- | CACHE LIST '{' rpki_cache_list '}'
+ | CACHE rpki_cache
  | ROA TABLE roa_table_cf { RPKI_CFG->roa_table_cf = $3; }
- | RTRLIB text { RPKI_CFG->rtrlib_path = $2; }
- ;
-
-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;
+rpki_cache:
+   rpki_cache_init text rpki_optional_cache_opts {
+     this_rpki_cache->host = $2;
      add_tail(&RPKI_CFG->cache_list, &this_rpki_cache->n);
    }
- | rpki_cache_init ipa rpki_cache_opts {
-     this_rpki_cache->ip = $2;
+ | rpki_cache_init ipa rpki_optional_cache_opts {
+     this_rpki_cache->ip_buf = cfg_alloc(sizeof(INET6_ADDRSTRLEN));
+     bsnprintf(this_rpki_cache->ip_buf, INET6_ADDRSTRLEN, "%I", $2);
+     this_rpki_cache->host = this_rpki_cache->ip_buf;
      add_tail(&RPKI_CFG->cache_list, &this_rpki_cache->n);
    }
  ;
 
 rpki_cache_init:
-   /* empty */ { this_rpki_cache = rpki_new_cache(); }
+ {
+   this_rpki_cache = rpki_new_cache();
+ }
+ ;
+
+rpki_optional_cache_opts:
+   /* empty */
+ | '{' rpki_cache_opts '}'
  ;
 
 rpki_cache_opts:
@@ -79,8 +90,14 @@ rpki_cache_opts:
  ;
 
 rpki_cache_opts_item:
-   PORT expr           { check_u16($2); bsnprintf(this_rpki_cache->port, RPKI_PORT_MAX_LENGTH_STR, "%u", (u16) $2); }
- | PREFERENCE expr     { check_u8($2); this_rpki_cache->preference = $2; }
+   PORT expr {
+     check_u16($2);
+     bsnprintf(this_rpki_cache->port, RPKI_PORT_MAX_LENGTH_STR, "%u", (u16) $2);
+   }
+ | PREFERENCE expr {
+   check_u8($2);
+   this_rpki_cache->preference = $2;
+ }
  ;
 
 CF_CODE
index cef80d7bce008b1c34c43766188a2d291286d24d..dcc76579c89a164c7422f8fa8407c202add61902 100644 (file)
@@ -1,6 +1,8 @@
 /*
  *     BIRD -- The Resource Public Key Infrastructure (RPKI) to Router Protocol
  *
+ *     Using RTRLib: http://rpki.realmv6.org/
+ *
  *     (c) 2015 CZ.NIC
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
 #include "lib/ip.h"
 #include "nest/route.h"
 
+#define RPKI_LOG_ADD "add"
+#define RPKI_LOG_DEL "del"
+#define RPKI_LOG_ENTRY_FMT(ip_fmt) " roa " ip_fmt "/%u max %u as %u"
+#define RPKI_LOG_FMT(operation_name) operation_name RPKI_LOG_ENTRY_FMT("%I")
+#define RPKI_LOG_SKIP_FMT(operation_name) "skipped (other IP version than BIRD) " operation_name RPKI_LOG_ENTRY_FMT("%s")
+
+static inline const char *
+get_rtr_socket_ident(const struct rtr_socket *socket)
+{
+  return socket->tr_socket->ident_fp(socket->tr_socket->socket);
+}
+#define RPKI_CACHE_TRACE(p, rtr_socket, msg, args...) RPKI_TRACE(p, "%s " msg, get_rtr_socket_ident(rtr_socket), ## args);
+#define RPKI_CACHE_ERROR(p, rtr_socket, msg, args...) RPKI_ERROR(p, "%s " msg, get_rtr_socket_ident(rtr_socket), ## args);
+
 struct rpki_entry {
   node n;
   u32 asn;
@@ -29,7 +45,6 @@ struct rpki_entry {
   u8 pxlen;
   u8 maxlen;
   u8 added;
-  struct rpki_proto *rpki;
 };
 
 void pipe_drain(int fd);       /* implementation in io.c */
@@ -37,6 +52,7 @@ void pipe_kick(int fd);       /* implementation in io.c */
 
 static list rpki_proto_list;
 
+/* RTRLib and function pointers */
 static void *rtrlib;
 static struct rtr_mgr_config * (*rtr_mgr_init_fp)(
     struct rtr_mgr_group groups[], const unsigned int groups_len,
@@ -49,38 +65,40 @@ static int (*rtr_mgr_start_fp)(struct rtr_mgr_config *config);
 static const char * (*rtr_state_to_str_fp)(enum rtr_socket_state state);
 static const char * (*rtr_mgr_status_to_str_fp)(enum rtr_mgr_status status);
 static int (*tr_tcp_init_fp)(const struct tr_tcp_config *config, struct tr_socket *socket);
+static void (*tr_free_fp)(struct tr_socket *tr_sock);
 static void (*rtr_mgr_stop_fp)(struct rtr_mgr_config *config);
 static void (*rtr_mgr_free_fp)(struct rtr_mgr_config *config);
 
-static int
-was_dlsym_ok(struct rpki_proto *p)
+/*
+ * Try load system shared library RTRLib
+ * Return NULL pointer if successful
+ * Otherwise return a pointer to a description of the error
+ */
+char *
+rpki_load_rtrlib(void)
 {
-  char *err_buffer = dlerror();
+  char *err_buf = NULL;
 
-  if (err_buffer != NULL)
-  {
-    RPKI_ERROR(p, "%s. Try the latest version of RTRLib.", err_buffer);
-    return 0; /* FAIL */
-  }
-  return 1; /* OK */
-}
+  if (rtrlib != NULL)
+    return NULL; /* OK, rtrlib is loaded already */
 
-static int
-load_rtrlib(struct rpki_proto *p)
-{
-  rtrlib = dlopen(p->cf->rtrlib_path, RTLD_LAZY);
+  const char *rtrlib_name = RPKI_LIBRTR_DEFAULT;
+
+#ifdef LIBRTR
+  rtrlib_name = LIBRTR; /* use a compile variable */
+#endif
+
+  rtrlib = dlopen(rtrlib_name, RTLD_LAZY);
   if (!rtrlib)
   {
-    RPKI_ERROR(p, "dlopen(): %s. Try specify path to the shared RTRLib (http://rpki.realmv6.org/) with 'rtrlib' option"
-                 "inside of the rpki protocol configuration", dlerror());
-    return 0; /* FAIL */
-  }
-  else
-  {
-    RPKI_TRACE(p, "Loaded RTRLib from %s", p->cf->rtrlib_path);
+    /* This could be pretty frequent problem */
+    char *help_msg = "Try recompile BIRD with CFLAGS='-DLIBRTR=\\\"/path/to/librtr.so\\\"' or see BIRD User's Guide for more information.";
+    err_buf = mb_alloc(&root_pool, 512);
+    bsnprintf(err_buf, 512, "%s. %s", dlerror(), help_msg);
+    return err_buf;
   }
 
-  dlerror();    /* Clear any existing error */
+  dlerror();    /* clear any existing error */
 
   rtr_mgr_init_fp = (struct rtr_mgr_config * (*)(
       struct rtr_mgr_group groups[], const unsigned int groups_len,
@@ -89,34 +107,38 @@ load_rtrlib(struct rpki_proto *p)
       const void *spki_update_fp,
       const void *status_fp,
       void *status_fp_data)) dlsym(rtrlib, "rtr_mgr_init");
-  if (!was_dlsym_ok(p))
-    return 0; /* FAIL */
+  if ((err_buf = dlerror()) != NULL)
+    return err_buf;
 
   rtr_mgr_start_fp = (int (*)(struct rtr_mgr_config *)) dlsym(rtrlib, "rtr_mgr_start");
-  if (!was_dlsym_ok(p))
-    return 0; /* FAIL */
+  if ((err_buf = dlerror()) != NULL)
+    return err_buf;
 
   rtr_state_to_str_fp = (const char * (*)(enum rtr_socket_state state)) dlsym(rtrlib, "rtr_state_to_str");
-  if (!was_dlsym_ok(p))
-    return 0; /* FAIL */
+  if ((err_buf = dlerror()) != NULL)
+    return err_buf;
 
   rtr_mgr_status_to_str_fp = (const char * (*)(enum rtr_mgr_status status)) dlsym(rtrlib, "rtr_mgr_status_to_str");
-  if (!was_dlsym_ok(p))
-    return 0; /* FAIL */
+  if ((err_buf = dlerror()) != NULL)
+    return err_buf;
 
   tr_tcp_init_fp = (int (*)(const struct tr_tcp_config *config, struct tr_socket *socket)) dlsym(rtrlib, "tr_tcp_init");
-  if (!was_dlsym_ok(p))
-    return 0; /* FAIL */
+  if ((err_buf = dlerror()) != NULL)
+    return err_buf;
+
+  tr_free_fp = (void (*)(struct tr_socket *)) dlsym(rtrlib, "tr_free");
+  if ((err_buf = dlerror()) != NULL)
+    return err_buf;
 
   rtr_mgr_stop_fp = (void (*)(struct rtr_mgr_config *config)) dlsym(rtrlib, "rtr_mgr_stop");
-  if (!was_dlsym_ok(p))
-    return 0; /* FAIL */
+  if ((err_buf = dlerror()) != NULL)
+    return err_buf;
 
   rtr_mgr_free_fp = (void (*)(struct rtr_mgr_config *config)) dlsym(rtrlib, "rtr_mgr_free");
-  if (!was_dlsym_ok(p))
-    return 0; /* FAIL */
+  if ((err_buf = dlerror()) != NULL)
+    return err_buf;
 
-  return 1; /* OK */
+  return NULL; /* OK */
 }
 
 void
@@ -126,33 +148,26 @@ rpki_init_all(void)
   rtrlib = NULL;
 }
 
+
 static void
-status_cb(const struct rtr_mgr_group *group, enum rtr_mgr_status status, const struct rtr_socket *socket, void *data)
+rtr_thread_status_hook(const struct rtr_mgr_group *group, enum rtr_mgr_status status, const struct rtr_socket *socket, void *data)
 {
   struct rpki_proto *p = data;
 
+#define RPKI_STATUS_CB_LOG_FMT "%s - %s"
+
   if (status == RTR_MGR_ERROR)
   {
-    RPKI_ERROR(p, "Error -> Should we here stop the protocol?"); /* FIXME */
+    RPKI_CACHE_ERROR(p, socket, RPKI_STATUS_CB_LOG_FMT, (*rtr_mgr_status_to_str_fp)(status), (*rtr_state_to_str_fp)(socket->state));
   }
   else
   {
-    RPKI_TRACE(p, "status: %s\t%s", (*rtr_mgr_status_to_str_fp)(status), (*rtr_state_to_str_fp)(socket->state));
+    RPKI_CACHE_TRACE(p, socket, RPKI_STATUS_CB_LOG_FMT, (*rtr_mgr_status_to_str_fp)(status), (*rtr_state_to_str_fp)(socket->state));
   }
 }
 
 static void
-send_data_to_main_thread(struct rpki_proto *p, struct rpki_entry *e)
-{
-  rpki_lock_sessions(p);
-  add_tail(&p->notify_list, &e->n);
-  rpki_unlock_sessions(p);
-
-  pipe_kick(p->notify_write_sk->fd);
-}
-
-static void
-log_skip_entry(struct rpki_proto *p, const struct pfx_record *rec, const bool added)
+log_skipped_entry(struct rpki_proto *p, const struct pfx_record *rec, const bool added)
 {
   char ip_buf[INET6_ADDRSTRLEN];
   ip4_addr ip4;
@@ -160,7 +175,7 @@ log_skip_entry(struct rpki_proto *p, const struct pfx_record *rec, const bool ad
 
   if (rec->prefix.ver == RTRLIB_IPV4)
   {
-    ip4 = ipa_from_u32(rec->prefix.u.addr4.addr);
+    ip4 = ip4_from_u32(rec->prefix.u.addr4.addr);
     ip4_ntop(ip4, ip_buf);
   }
   else
@@ -169,24 +184,21 @@ log_skip_entry(struct rpki_proto *p, const struct pfx_record *rec, const bool ad
     ip6_ntop(ip6, ip_buf);
   }
 
-#define RPKI_LOG_ADD "add"
-#define RPKI_LOG_DEL "del"
-#define RPKI_LOG_ENTRY_FMT(ip_fmt) " roa %-25" ip_fmt "/%u-%-3u ASN: %u"
-#define RPKI_LOG_FMT(operation_name)              operation_name RPKI_LOG_ENTRY_FMT("I")
-#define RPKI_LOG_SKIP_FMT(operation_name) "skip " operation_name RPKI_LOG_ENTRY_FMT("s") " (unsupported IP version)"
-
   if (added)
   {
-    RPKI_TRACE(p, RPKI_LOG_SKIP_FMT(RPKI_LOG_ADD), ip_buf, rec->min_len, rec->max_len, rec->asn);
+    RPKI_CACHE_TRACE(p, rec->socket, RPKI_LOG_SKIP_FMT(RPKI_LOG_ADD), ip_buf, rec->min_len, rec->max_len, rec->asn);
   }
   else
   {
-    RPKI_TRACE(p, RPKI_LOG_SKIP_FMT(RPKI_LOG_DEL), ip_buf, rec->min_len, rec->max_len, rec->asn);
+    RPKI_CACHE_TRACE(p, rec->socket, RPKI_LOG_SKIP_FMT(RPKI_LOG_DEL), ip_buf, rec->min_len, rec->max_len, rec->asn);
   }
 }
 
+/*
+ * Return (struct rpki_proto *) or NULL
+ */
 static struct rpki_proto *
-find_rpki_proto_by_rtr_socket(const struct rtr_socket *socket)
+get_rpki_proto_by_rtr_socket(const struct rtr_socket *socket)
 {
   struct rpki_proto *p_not_skipped_back;
   unsigned int i, j;
@@ -204,51 +216,58 @@ find_rpki_proto_by_rtr_socket(const struct rtr_socket *socket)
       }
     }
   }
+  return NULL; /* FAIL */
+}
 
-  return NULL;
+static void
+send_data_to_main_thread(struct rpki_proto *p, struct rpki_entry *e)
+{
+  rpki_lock_notify(p);
+  add_tail(&p->notify_list, &e->n);
+  rpki_unlock_notify(p);
+  pipe_kick(p->notify_write_sk->fd);
 }
 
 static void
-rtr_thread_update_hook(struct pfx_table *pfx_table, const struct pfx_record rec, const bool added)
+rtr_thread_update_hook(void *pfx_table, const struct pfx_record rec, const bool added)
 {
-  struct rpki_proto *p = find_rpki_proto_by_rtr_socket(rec.socket);
+  struct rpki_proto *p = get_rpki_proto_by_rtr_socket(rec.socket);
 
   /* process only records that are the same with BIRD IP version */
 #ifdef IPV6
   if (rec.prefix.ver != RTRLIB_IPV6)
   {
-    log_skip_entry(p, &rec);
+    log_skipped_entry(p, &rec, added);
     return;
   }
+
+  ip_addr ip = 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]);
 #else
   if (rec.prefix.ver != RTRLIB_IPV4)
   {
-    log_skip_entry(p, &rec, added);
+    log_skipped_entry(p, &rec, added);
     return;
   }
-#endif
 
-#ifdef IPV6
-  ip_addr ip = 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]);
-#else
-  ip_addr ip = ipa_from_u32(rec.prefix.u.addr4.addr);
+  ip_addr ip = ip4_from_u32(rec.prefix.u.addr4.addr);
 #endif
 
+  /* TODO: Make more effective solution with thread-safe pool/queue of rpki_entry structures
+   *       without endless allocations and frees */
   struct rpki_entry *e = mb_allocz(p->p.pool, sizeof(struct rpki_entry));
   e->added = added;
   e->asn = rec.asn;
   e->ip = ip;
   e->pxlen = rec.min_len;
   e->maxlen = rec.max_len;
-  e->rpki = p;
 
   if (e->added)
   {
-    RPKI_TRACE(p, RPKI_LOG_FMT(RPKI_LOG_ADD), e->ip, e->pxlen, e->maxlen, e->asn);
+    RPKI_CACHE_TRACE(p, rec.socket, RPKI_LOG_FMT(RPKI_LOG_ADD), e->ip, e->pxlen, e->maxlen, e->asn);
   }
   else
   {
-    RPKI_TRACE(p, RPKI_LOG_FMT(RPKI_LOG_DEL), e->ip, e->pxlen, e->maxlen, e->asn);
+    RPKI_CACHE_TRACE(p, rec.socket, RPKI_LOG_FMT(RPKI_LOG_DEL), e->ip, e->pxlen, e->maxlen, e->asn);
   }
 
   send_data_to_main_thread(p, e);
@@ -271,61 +290,62 @@ rpki_new_cache(void)
 {
   struct rpki_cache *cache = (struct rpki_cache *)cfg_allocz(sizeof(struct rpki_cache));
   strcpy(cache->port, RPKI_PORT);
-  cache->preference = ~0;
+  cache->preference = RPKI_DEFAULT_CACHE_PREFERENCE;
   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_notify_hook(struct birdsock *sk, int size)
+recv_data_in_main_thread(struct birdsock *sk, int size)
 {
   struct rpki_proto *p = sk->data;
-  struct rpki_entry *entry;
+  struct rpki_entry *e;
+  list tmp_list;
 
   pipe_drain(sk->fd);
 
-  rpki_lock_sessions(p);
-  /* TODO: optimize like in the BFD proto */
-  WALK_LIST_FIRST(entry, p->notify_list)
+  rpki_lock_notify(p);
+  init_list(&tmp_list);
+  add_tail_list(&tmp_list, &p->notify_list);
+  init_list(&p->notify_list);
+  rpki_unlock_notify(p);
+
+  WALK_LIST_FIRST(e, tmp_list)
   {
-    rem2_node(&entry->n);
-    if (entry->added)
-      roa_add_item(p->cf->roa_table_cf->table, entry->ip, entry->pxlen, entry->maxlen, entry->asn, ROA_SRC_RPKI);
+    rpki_lock_notify(p);
+    rem2_node(&e->n);
+    rpki_unlock_notify(p);
+
+    if (e->added)
+      roa_add_item(p->cf->roa_table_cf->table, e->ip, e->pxlen, e->maxlen, e->asn, ROA_SRC_RPKI);
     else
-      roa_delete_item(p->cf->roa_table_cf->table, entry->ip, entry->pxlen, entry->maxlen, entry->asn, ROA_SRC_RPKI);
+      roa_delete_item(p->cf->roa_table_cf->table, e->ip, e->pxlen, e->maxlen, e->asn, ROA_SRC_RPKI);
+    mb_free(e);
   }
-  rpki_unlock_sessions(p);
 }
 
 static void
-rpki_noterr_hook(struct birdsock *sk, int err)
+recv_err_in_main_thread(struct birdsock *sk, int err)
 {
   struct rpki_proto *p = sk->data;
   RPKI_ERROR(p, "Notify socket error: %m", err);
 }
 
-static void
-create_read_socket(struct rpki_proto *p, int fd)
+static sock *
+create_socket(struct rpki_proto *p, int fd)
 {
   sock *sk = sk_new(p->p.pool);
   sk->type = SK_MAGIC;
   sk->fd = fd;
-  sk->rx_hook = rpki_notify_hook;
-  sk->err_hook = rpki_noterr_hook;
   sk->data = p;
+  return sk;
+}
+
+static void
+create_read_socket(struct rpki_proto *p, int fd)
+{
+  sock *sk = create_socket(p, fd);
+  sk->rx_hook = recv_data_in_main_thread;
+  sk->err_hook = recv_err_in_main_thread;
   if (sk_open(sk) < 0)
     RPKI_DIE(p, "read socket sk_open() failed");
   p->notify_read_sk = sk;
@@ -334,11 +354,8 @@ create_read_socket(struct rpki_proto *p, int fd)
 static void
 create_write_socket(struct rpki_proto *p, int fd)
 {
-  sock *sk = sk_new(p->p.pool);
-  sk->type = SK_MAGIC;
-  sk->fd = fd;
+  sock *sk = create_socket(p, fd);
   sk->flags = SKF_THREAD;
-  sk->data = p;
   if (sk_open(sk) < 0)
     RPKI_DIE(p, "write socket sk_open() failed");
   p->notify_write_sk = sk;
@@ -357,56 +374,121 @@ create_rw_sockets(struct rpki_proto *p)
   create_write_socket(p, pipe_fildes[1]);
 }
 
-static int
-rpki_start(struct proto *P)
+static uint
+count_number_of_various_preferences(list *cache_list)
 {
-  struct rpki_proto *p = (struct rpki_proto *) P;
-  struct rpki_config *cf = (struct rpki_config *) (P->cf);
+  uint i;
+  u8 preference[256];
+  bzero(preference, sizeof(preference));
 
-  RPKI_TRACE(p, "------------- rpki_start -------------");
+  struct rpki_cache *cache;
+  WALK_LIST(cache, *cache_list)
+  {
+    preference[cache->preference]++;
+  }
 
-  if (!rtrlib && !load_rtrlib(p))
-    return PS_DOWN;
+  uint count = 0;
+  for (i = 0; i < 256; i++)
+  {
+    if (preference[i])
+      count++;
+  }
+  return count;
+}
 
-  create_rw_sockets(p);
-  init_list(&p->notify_list);
-  pthread_spin_init(&p->notify_lock, PTHREAD_PROCESS_PRIVATE);
+static uint
+count_number_of_caches_with_specific_preference(list *cache_list, uint preference)
+{
+  uint count = 0;
 
-  add_tail(&rpki_proto_list, &p->rpki_node);
+  struct rpki_cache *cache;
+  WALK_LIST(cache, *cache_list)
+  {
+    if (cache->preference == preference)
+      count++;
+  }
 
-  p->rtr_sockets_len = get_list_length(&cf->cache_list);
-  p->rtr_groups = mb_allocz(P->pool, 1 * sizeof(struct rtr_mgr_group));
-  struct rtr_mgr_group *groups = p->rtr_groups;
+  return count;
+}
 
-  p->rtr_sockets = mb_allocz(P->pool, p->rtr_sockets_len * sizeof(struct rtr_socket *));
-  groups[0].sockets = p->rtr_sockets;
-  groups[0].sockets_len = p->rtr_sockets_len;
-  groups[0].preference = 1;
+static struct rtr_socket *
+create_rtrlib_tcp_socket(struct rpki_cache *cache, pool *pool)
+{
+  struct rtr_socket *rtrlib_tcp = mb_allocz(pool, sizeof(struct rtr_socket));
+  rtrlib_tcp->tr_socket = mb_allocz(pool, sizeof(struct tr_socket));
+  struct tr_tcp_config tcp_config = {
+      .host = cache->host,
+      .port = cache->port
+  };
 
-  uint idx = 0;
-  struct rpki_cache *cache;
-  WALK_LIST(cache, cf->cache_list)
-  {
-    /* TODO: Make them dynamic. Reconfigure reallocate structures */
-    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;
+  (*tr_tcp_init_fp)(&tcp_config, rtrlib_tcp->tr_socket);
+
+  return rtrlib_tcp;
+}
 
-    normalize_fulfillment_of_cache(cache);
+struct rtr_mgr_group_crate {
+  struct rtr_mgr_group *groups;
+  uint groups_len;
+};
+
+static struct rtr_mgr_group_crate
+group_cache_list_by_preferences(list *cache_list, pool *pool)
+{
+  u8 completed_preference[256];
+  bzero(completed_preference, sizeof(completed_preference));
+
+  uint groups_len = count_number_of_various_preferences(cache_list);
+  struct rtr_mgr_group *groups = mb_allocz(pool, groups_len * sizeof(struct rtr_mgr_group));
 
-    tcp_config->host = cache->full_domain_name;
-    tcp_config->port = cache->port;
-    (*tr_tcp_init_fp)(tcp_config, tr_tcp);
+  uint group_idx = 0;
+  struct rpki_cache *first_cache_in_group;
+  WALK_LIST(first_cache_in_group, *cache_list)
+  {
+    if (completed_preference[first_cache_in_group->preference])
+      continue;
+    completed_preference[first_cache_in_group->preference] = 1;
 
-    // create an rtr_socket and associate it with the transport socket
-    rtr_tcp->tr_socket = tr_tcp;
+    struct rtr_mgr_group *group = &groups[group_idx];
 
-    groups[0].sockets[idx] = rtr_tcp;
+    group->preference = first_cache_in_group->preference;
+    group->sockets_len = count_number_of_caches_with_specific_preference(cache_list, first_cache_in_group->preference);
+    group->sockets = mb_allocz(pool, group->sockets_len * sizeof(struct rtr_socket *));
 
-    idx++;
+    uint socket_idx = 0;
+    struct rpki_cache *cache;
+    WALK_LIST(cache, *cache_list)
+    {
+      if (cache->preference == groups[group_idx].preference)
+      {
+       group->sockets[socket_idx] = cache->rtr_tcp = create_rtrlib_tcp_socket(cache, pool);
+       socket_idx++;
+      }
+    }
+    group_idx++;
   }
 
-  p->rtr_conf = (*rtr_mgr_init_fp)(groups, 1, 30, 520, &rtr_thread_update_hook, NULL, &status_cb, p);
+  struct rtr_mgr_group_crate grouped_list = {
+      .groups = groups,
+      .groups_len = groups_len
+  };
+  return grouped_list;
+}
+
+static int
+rpki_start(struct proto *P)
+{
+  struct rpki_proto *p = (struct rpki_proto *) P;
+  struct rpki_config *cf = (struct rpki_config *) (P->cf);
+
+  create_rw_sockets(p);
+  init_list(&p->notify_list);
+  pthread_mutex_init(&p->notify_lock, NULL);
+
+  add_tail(&rpki_proto_list, &p->rpki_node);
+
+  struct rtr_mgr_group_crate grouped_list = group_cache_list_by_preferences(&cf->cache_list, P->pool);
+
+  p->rtr_conf = (*rtr_mgr_init_fp)(grouped_list.groups, grouped_list.groups_len, 30, 520, &rtr_thread_update_hook, NULL, &rtr_thread_status_hook, p);
   (*rtr_mgr_start_fp)(p->rtr_conf);
 
   return PS_UP;
@@ -419,8 +501,21 @@ rpki_shutdown(struct proto *P)
 
   (*rtr_mgr_stop_fp)(p->rtr_conf);
   (*rtr_mgr_free_fp)(p->rtr_conf);
-  mb_free(p->rtr_groups);
+
+  struct rpki_cache *cache;
+  WALK_LIST(cache, p->cf->cache_list)
+  {
+    (*tr_free_fp)(cache->rtr_tcp->tr_socket);
+    mb_free(cache->rtr_tcp->tr_socket);
+    mb_free(cache->rtr_tcp);
+    if (cache->ip_buf)
+      mb_free(cache->ip_buf);
+  }
+
   mb_free(p->rtr_sockets);
+  mb_free(p->rtr_groups);
+
+  pthread_mutex_destroy(&p->notify_lock);
 
   return PS_DOWN;
 }
index e5da7acd2753e76cbf3a6c3d07521e45e57ebe5b..bc67695aac15eea0a759f5d3e1443504a43bc556 100644 (file)
@@ -1,6 +1,8 @@
 /*
  *     BIRD -- The Resource Public Key Infrastructure (RPKI) to Router Protocol
  *
+ *     Using RTRLib: http://rpki.realmv6.org/
+ *
  *     (c) 2015 CZ.NIC
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
 
 #define RPKI_PORT "8282"
 #define RPKI_PORT_MAX_LENGTH_STR 6
-#define RPKI_RX_BUFFER_EXT_SIZE 0xffff
-#define RPKI_TX_BUFFER_EXT_SIZE 0xffff
-#define RPKI_RTRLIB_PATH "/usr/local/lib64/librtr.so"
+#define RPKI_LIBRTR_DEFAULT "librtr.so"
+
+#define RPKI_DEFAULT_CACHE_PREFERENCE 0xff     /* the least preference */
 
 #define RPKI_LOG(log_level, p, msg, args...)                           \
   do {                                                                         \
     log(log_level "%s: " msg, p->p.name , ## args);                    \
   } while(0)
-
 #define RPKI_TRACE(p, msg, args...)                                    \
   do {                                                                 \
     if (p->p.debug)                                                    \
       RPKI_LOG(L_TRACE, p, msg, ## args);                              \
   } while(0)
-
 #define RPKI_ERROR(p, msg, args...) RPKI_LOG(L_ERR, p, msg, ## args);
 #define RPKI_DIE(p, msg, args...)                                      \
     do {                                                               \
       exit(1);                                                         \
     } while(0)
 
+
 struct rpki_cache {
   node n;              /* in struct rpki_config.cache_list */
-  ip_addr ip;
-  char *full_domain_name;
-  char port[RPKI_PORT_MAX_LENGTH_STR]; /* TODO change to u16 */
-  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];
-  char port_buf[RPKI_PORT_MAX_LENGTH_STR]; /* the highest port is "65535" */
+  char *host;          /* full domain name or ip address */
+  char port[RPKI_PORT_MAX_LENGTH_STR]; /* the highest port is "65535" */
+  u8 preference;       /* the most prioritized are the lowest numbers, starts with 1 */
+  struct rtr_socket *rtr_tcp;
+  char *ip_buf;
 };
 
 struct rpki_config {
   struct proto_config c;
-  list cache_list;     /* (struct rpki_cache *) */
+  list cache_list;     /* struct rpki_cache * */
   struct roa_table_config *roa_table_cf;
-  const char *rtrlib_path;
 };
 
 struct rpki_proto {
   struct proto p;
-  node rpki_node;
+  node rpki_node;      /* in rpki_proto_list */
+
   struct rpki_config *cf;
   struct rtr_mgr_config *rtr_conf;
   struct rtr_mgr_group *rtr_groups;
@@ -76,14 +70,16 @@ struct rpki_proto {
   sock *notify_read_sk;
   sock *notify_write_sk;
   list notify_list;
-  pthread_spinlock_t notify_lock;
+  pthread_mutex_t notify_lock;
 };
 
 struct rpki_cache *rpki_new_cache(void);
 
-static inline void rpki_lock_sessions(struct rpki_proto *p) { pthread_spin_lock(&p->notify_lock); }
-static inline void rpki_unlock_sessions(struct rpki_proto *p) { pthread_spin_unlock(&p->notify_lock); }
+
+static inline void rpki_lock_notify(struct rpki_proto *p) { pthread_mutex_lock(&p->notify_lock); }
+static inline void rpki_unlock_notify(struct rpki_proto *p) { pthread_mutex_unlock(&p->notify_lock); }
 
 void rpki_init_all(void);
+char *rpki_load_rtrlib(void);
 
 #endif /* _BIRD_RPKI_H_ */
index 160d3e5b5d0db166b58ed0270c008a62c376d667..b632432c9b4b664e4e0786f20691156f3c1ed006 100644 (file)
@@ -47,7 +47,7 @@ struct tr_socket {
     void *free_fp;     /* voided for mockuping */
     void *send_fp;     /* voided for mockuping */
     void *recv_fp;     /* voided for mockuping */
-    void *ident_fp;    /* voided for mockuping */
+    const char * (*ident_fp)(void *);  /* edited for mockuping */
 };
 
 /**
@@ -169,7 +169,7 @@ struct rtr_mgr_group {
 struct rtr_mgr_config {
     struct rtr_mgr_group *groups;
     unsigned int len;
-    /* some items deleted */
+    /* some items deleted for mockuping */
 };