mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-23 02:01:55 +00:00
RPKI: Add SSH Transport support
Handle reconfigure (still buggy)
This commit is contained in:
parent
df2caa8b1d
commit
695f704389
@ -10,6 +10,8 @@ CF_HDR
|
|||||||
|
|
||||||
#define PARSER 1
|
#define PARSER 1
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
#include "conf/conf.h"
|
#include "conf/conf.h"
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
@ -40,6 +42,13 @@ check_u16(unsigned val)
|
|||||||
cf_error("Value %d out of range (0-65535)", val);
|
cf_error("Value %d out of range (0-65535)", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
check_file_readability(const char *file_path)
|
||||||
|
{
|
||||||
|
if(access(file_path, R_OK) == -1)
|
||||||
|
cf_error("File %s cannot be open for read: %m", file_path);
|
||||||
|
}
|
||||||
|
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
%union {
|
%union {
|
||||||
|
@ -18,7 +18,7 @@ static struct rpki_cache *this_rpki_cache;
|
|||||||
|
|
||||||
CF_DECLS
|
CF_DECLS
|
||||||
|
|
||||||
CF_KEYWORDS(RPKI, CACHE, LIST, PREFERENCE)
|
CF_KEYWORDS(RPKI, CACHE, LIST, PREFERENCE, BIRD, PRIVATE, PUBLIC, KEY, SSH, ENCRYPTION, USER)
|
||||||
|
|
||||||
CF_GRAMMAR
|
CF_GRAMMAR
|
||||||
|
|
||||||
@ -37,16 +37,12 @@ rpki_proto_start:
|
|||||||
|
|
||||||
rpki_proto_finish:
|
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();
|
char *rpki_err_buf = rpki_load_rtrlib();
|
||||||
if (rpki_err_buf != NULL)
|
if (rpki_err_buf != NULL)
|
||||||
{
|
|
||||||
cf_error("Cannot use a RPKI protocol: %s", rpki_err_buf);
|
cf_error("Cannot use a RPKI protocol: %s", rpki_err_buf);
|
||||||
}
|
|
||||||
|
if (RPKI_CFG->roa_table_cf == NULL)
|
||||||
|
cf_error("For the RPKI protocol must be specified a roa table");
|
||||||
};
|
};
|
||||||
|
|
||||||
rpki_proto_opts:
|
rpki_proto_opts:
|
||||||
@ -61,15 +57,20 @@ rpki_proto_item:
|
|||||||
;
|
;
|
||||||
|
|
||||||
rpki_cache:
|
rpki_cache:
|
||||||
rpki_cache_init text rpki_optional_cache_opts {
|
rpki_cache_init rpki_cache_addr rpki_optional_cache_opts rpki_cache_finish {
|
||||||
this_rpki_cache->host = $2;
|
|
||||||
add_tail(&RPKI_CFG->cache_list, &this_rpki_cache->n);
|
add_tail(&RPKI_CFG->cache_list, &this_rpki_cache->n);
|
||||||
}
|
}
|
||||||
| 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);
|
rpki_cache_finish:
|
||||||
this_rpki_cache->host = this_rpki_cache->ip_buf;
|
{
|
||||||
add_tail(&RPKI_CFG->cache_list, &this_rpki_cache->n);
|
if (this_rpki_cache->port[0] == 0) /* empty? */
|
||||||
|
{
|
||||||
|
if (this_rpki_cache->ssh != NULL)
|
||||||
|
strcpy(this_rpki_cache->port, RPKI_SSH_PORT);
|
||||||
|
else
|
||||||
|
strcpy(this_rpki_cache->port, RPKI_PORT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -79,6 +80,17 @@ rpki_cache_init:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
rpki_cache_addr:
|
||||||
|
text {
|
||||||
|
this_rpki_cache = rpki_new_cache();
|
||||||
|
this_rpki_cache->host = $1;
|
||||||
|
}
|
||||||
|
| ipa {
|
||||||
|
this_rpki_cache->host = cfg_alloc(sizeof(INET6_ADDRSTRLEN));
|
||||||
|
bsnprintf(this_rpki_cache->host, INET6_ADDRSTRLEN, "%I", $1);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
rpki_optional_cache_opts:
|
rpki_optional_cache_opts:
|
||||||
/* empty */
|
/* empty */
|
||||||
| '{' rpki_cache_opts '}'
|
| '{' rpki_cache_opts '}'
|
||||||
@ -98,8 +110,50 @@ rpki_cache_opts_item:
|
|||||||
check_u8($2);
|
check_u8($2);
|
||||||
this_rpki_cache->preference = $2;
|
this_rpki_cache->preference = $2;
|
||||||
}
|
}
|
||||||
|
| SSH ENCRYPTION rpki_transport_ssh_init '{' rpki_transport_ssh_opts '}' rpki_transport_ssh_finish
|
||||||
;
|
;
|
||||||
|
|
||||||
|
rpki_transport_ssh_init:
|
||||||
|
{
|
||||||
|
this_rpki_cache->ssh = cfg_allocz(sizeof(struct rpki_ssh_config));
|
||||||
|
if (strncmp(this_rpki_cache->port, RPKI_PORT, RPKI_PORT_MAX_LENGTH_STR) == 0)
|
||||||
|
strcpy(this_rpki_cache->port, RPKI_SSH_PORT);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
rpki_transport_ssh_opts:
|
||||||
|
/* empty */
|
||||||
|
| rpki_transport_ssh_opts rpki_transport_ssh_item ';'
|
||||||
|
;
|
||||||
|
|
||||||
|
rpki_transport_ssh_item:
|
||||||
|
BIRD PRIVATE KEY text {
|
||||||
|
check_file_readability($4);
|
||||||
|
this_rpki_cache->ssh->bird_private_key = $4;
|
||||||
|
}
|
||||||
|
| CACHE PUBLIC KEY text {
|
||||||
|
check_file_readability($4);
|
||||||
|
this_rpki_cache->ssh->cache_public_key = $4;
|
||||||
|
}
|
||||||
|
| USER text {
|
||||||
|
this_rpki_cache->ssh->user = $2;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
rpki_transport_ssh_finish:
|
||||||
|
{
|
||||||
|
#define RPKI_PARSE_CACHE_MISS_SSH_OPT(what) "Miss '" what ";' option in the %s protocol at cache server %s inside the ssh encryption block"
|
||||||
|
|
||||||
|
if (!this_rpki_cache->ssh->bird_private_key)
|
||||||
|
cf_error(RPKI_PARSE_CACHE_MISS_SSH_OPT("bird private key \"/path/to/ssh_key/id_rsa\""), RPKI_CFG->c.name, this_rpki_cache->host);
|
||||||
|
|
||||||
|
if (!this_rpki_cache->ssh->cache_public_key)
|
||||||
|
cf_error(RPKI_PARSE_CACHE_MISS_SSH_OPT("cache public key \"/path/to/ssh_key/known_hosts\""), RPKI_CFG->c.name, this_rpki_cache->host);
|
||||||
|
|
||||||
|
if (!this_rpki_cache->ssh->user)
|
||||||
|
cf_error(RPKI_PARSE_CACHE_MISS_SSH_OPT("user \"ssh_username\""), RPKI_CFG->c.name, this_rpki_cache->host);
|
||||||
|
}
|
||||||
|
|
||||||
CF_CODE
|
CF_CODE
|
||||||
|
|
||||||
CF_END
|
CF_END
|
||||||
|
@ -12,6 +12,11 @@
|
|||||||
* DOC: The Resource Public Key Infrastructure (RPKI) to Router Protocol
|
* DOC: The Resource Public Key Infrastructure (RPKI) to Router Protocol
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO
|
||||||
|
* - Make correct log depending on protocol option 'debug all|off|{ states, routes, filters, interfaces, events, packets }'
|
||||||
|
*/
|
||||||
|
|
||||||
#define LOCAL_DEBUG
|
#define LOCAL_DEBUG
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -28,7 +33,7 @@
|
|||||||
#define RPKI_LOG_DEL "del"
|
#define RPKI_LOG_DEL "del"
|
||||||
#define RPKI_LOG_ENTRY_FMT(ip_fmt) " roa " ip_fmt "/%u max %u as %u"
|
#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_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")
|
#define RPKI_LOG_SKIP_FMT(operation_name) operation_name RPKI_LOG_ENTRY_FMT("%s") " skipped incompatible IP version"
|
||||||
|
|
||||||
static inline const char *
|
static inline const char *
|
||||||
get_rtr_socket_ident(const struct rtr_socket *socket)
|
get_rtr_socket_ident(const struct rtr_socket *socket)
|
||||||
@ -51,6 +56,7 @@ void pipe_drain(int fd); /* implementation in io.c */
|
|||||||
void pipe_kick(int fd); /* implementation in io.c */
|
void pipe_kick(int fd); /* implementation in io.c */
|
||||||
|
|
||||||
static list rpki_proto_list;
|
static list rpki_proto_list;
|
||||||
|
static pthread_mutex_t rpki_proto_list_lock;
|
||||||
|
|
||||||
/* RTRLib and function pointers */
|
/* RTRLib and function pointers */
|
||||||
static void *rtrlib;
|
static void *rtrlib;
|
||||||
@ -65,10 +71,23 @@ 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_state_to_str_fp)(enum rtr_socket_state state);
|
||||||
static const char * (*rtr_mgr_status_to_str_fp)(enum rtr_mgr_status status);
|
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 int (*tr_tcp_init_fp)(const struct tr_tcp_config *config, struct tr_socket *socket);
|
||||||
|
static int (*tr_ssh_init_fp)(const struct tr_ssh_config *config, struct tr_socket *socket);
|
||||||
static void (*tr_free_fp)(struct tr_socket *tr_sock);
|
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_stop_fp)(struct rtr_mgr_config *config);
|
||||||
static void (*rtr_mgr_free_fp)(struct rtr_mgr_config *config);
|
static void (*rtr_mgr_free_fp)(struct rtr_mgr_config *config);
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
lock_rpki_proto_list(void)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&rpki_proto_list_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
unlock_rpki_proto_list(void)
|
||||||
|
{
|
||||||
|
pthread_mutex_unlock(&rpki_proto_list_lock);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try load system shared library RTRLib
|
* Try load system shared library RTRLib
|
||||||
* Return NULL pointer if successful
|
* Return NULL pointer if successful
|
||||||
@ -80,25 +99,26 @@ rpki_load_rtrlib(void)
|
|||||||
char *err_buf = NULL;
|
char *err_buf = NULL;
|
||||||
|
|
||||||
if (rtrlib != NULL)
|
if (rtrlib != NULL)
|
||||||
return NULL; /* OK, rtrlib is loaded already */
|
return NULL; /* RTRLib is loaded already */
|
||||||
|
|
||||||
const char *rtrlib_name = RPKI_LIBRTR_DEFAULT;
|
const char *rtrlib_name = RPKI_LIBRTR_DEFAULT;
|
||||||
|
|
||||||
#ifdef LIBRTR
|
#ifdef LIBRTR
|
||||||
rtrlib_name = LIBRTR; /* use a compile variable */
|
rtrlib_name = LIBRTR; /* Use a compile variable */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rtrlib = dlopen(rtrlib_name, RTLD_LAZY);
|
rtrlib = dlopen(rtrlib_name, RTLD_LAZY);
|
||||||
if (!rtrlib)
|
if (!rtrlib)
|
||||||
{
|
{
|
||||||
/* This could be pretty frequent problem */
|
/* This would be probably often repeated problem */
|
||||||
char *help_msg = "Try recompile BIRD with CFLAGS='-DLIBRTR=\\\"/path/to/librtr.so\\\"' or see BIRD User's Guide for more information.";
|
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);
|
err_buf = mb_alloc(&root_pool, 512);
|
||||||
bsnprintf(err_buf, 512, "%s. %s", dlerror(), help_msg);
|
bsnprintf(err_buf, 512, "%s. %s", dlerror(), help_msg);
|
||||||
return err_buf;
|
return err_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
dlerror(); /* clear any existing error */
|
dlerror(); /* Clear any existing error */
|
||||||
|
|
||||||
rtr_mgr_init_fp = (struct rtr_mgr_config * (*)(
|
rtr_mgr_init_fp = (struct rtr_mgr_config * (*)(
|
||||||
struct rtr_mgr_group groups[], const unsigned int groups_len,
|
struct rtr_mgr_group groups[], const unsigned int groups_len,
|
||||||
@ -126,6 +146,10 @@ rpki_load_rtrlib(void)
|
|||||||
if ((err_buf = dlerror()) != NULL)
|
if ((err_buf = dlerror()) != NULL)
|
||||||
return err_buf;
|
return err_buf;
|
||||||
|
|
||||||
|
tr_ssh_init_fp = (int (*)(const struct tr_ssh_config *config, struct tr_socket *socket)) dlsym(rtrlib, "tr_ssh_init");
|
||||||
|
if ((err_buf = dlerror()) != NULL)
|
||||||
|
return err_buf;
|
||||||
|
|
||||||
tr_free_fp = (void (*)(struct tr_socket *)) dlsym(rtrlib, "tr_free");
|
tr_free_fp = (void (*)(struct tr_socket *)) dlsym(rtrlib, "tr_free");
|
||||||
if ((err_buf = dlerror()) != NULL)
|
if ((err_buf = dlerror()) != NULL)
|
||||||
return err_buf;
|
return err_buf;
|
||||||
@ -145,13 +169,23 @@ void
|
|||||||
rpki_init_all(void)
|
rpki_init_all(void)
|
||||||
{
|
{
|
||||||
init_list(&rpki_proto_list);
|
init_list(&rpki_proto_list);
|
||||||
|
pthread_mutex_init(&rpki_proto_list_lock, NULL);
|
||||||
rtrlib = NULL;
|
rtrlib = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
rtr_thread_status_hook(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)
|
||||||
{
|
{
|
||||||
|
/* TODO: This is weird:
|
||||||
|
* ...
|
||||||
|
* RTR_MGR_CLOSED - RTR_RESET
|
||||||
|
* RTR_MGR_CLOSED - RTR_SYNC
|
||||||
|
* RTR_MGR_CLOSED - <NULL>
|
||||||
|
* RTR_MGR_CLOSED - RTR_CONNECTING
|
||||||
|
* RTR_MGR_CLOSED - RTR_RESET
|
||||||
|
* RTR_MGR_CLOSED - RTR_SYNC
|
||||||
|
* ...
|
||||||
|
*/
|
||||||
struct rpki_proto *p = data;
|
struct rpki_proto *p = data;
|
||||||
|
|
||||||
#define RPKI_STATUS_CB_LOG_FMT "%s - %s"
|
#define RPKI_STATUS_CB_LOG_FMT "%s - %s"
|
||||||
@ -159,6 +193,7 @@ rtr_thread_status_hook(const struct rtr_mgr_group *group, enum rtr_mgr_status st
|
|||||||
if (status == RTR_MGR_ERROR)
|
if (status == RTR_MGR_ERROR)
|
||||||
{
|
{
|
||||||
RPKI_CACHE_ERROR(p, socket, RPKI_STATUS_CB_LOG_FMT, (*rtr_mgr_status_to_str_fp)(status), (*rtr_state_to_str_fp)(socket->state));
|
RPKI_CACHE_ERROR(p, socket, RPKI_STATUS_CB_LOG_FMT, (*rtr_mgr_status_to_str_fp)(status), (*rtr_state_to_str_fp)(socket->state));
|
||||||
|
// TODO: Here we should set protocol to PS_DOWN state.
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -203,6 +238,7 @@ get_rpki_proto_by_rtr_socket(const struct rtr_socket *socket)
|
|||||||
struct rpki_proto *p_not_skipped_back;
|
struct rpki_proto *p_not_skipped_back;
|
||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
|
|
||||||
|
lock_rpki_proto_list();
|
||||||
WALK_LIST(p_not_skipped_back, rpki_proto_list)
|
WALK_LIST(p_not_skipped_back, rpki_proto_list)
|
||||||
{
|
{
|
||||||
struct rpki_proto *p = SKIP_BACK(struct rpki_proto, rpki_node, p_not_skipped_back);
|
struct rpki_proto *p = SKIP_BACK(struct rpki_proto, rpki_node, p_not_skipped_back);
|
||||||
@ -212,10 +248,14 @@ get_rpki_proto_by_rtr_socket(const struct rtr_socket *socket)
|
|||||||
for(j = 0; j < p->rtr_conf->groups[i].sockets_len; j++)
|
for(j = 0; j < p->rtr_conf->groups[i].sockets_len; j++)
|
||||||
{
|
{
|
||||||
if (socket == p->rtr_conf->groups[i].sockets[j])
|
if (socket == p->rtr_conf->groups[i].sockets[j])
|
||||||
|
{
|
||||||
|
unlock_rpki_proto_list();
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
unlock_rpki_proto_list();
|
||||||
return NULL; /* FAIL */
|
return NULL; /* FAIL */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +272,11 @@ static void
|
|||||||
rtr_thread_update_hook(void *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 = get_rpki_proto_by_rtr_socket(rec.socket);
|
struct rpki_proto *p = get_rpki_proto_by_rtr_socket(rec.socket);
|
||||||
|
if (!p)
|
||||||
|
{
|
||||||
|
DBG("rtr_thread_update_hook: Cannot find matching protocol for %s\n", get_rtr_socket_ident(rec.socket));
|
||||||
|
return;
|
||||||
|
}
|
||||||
/* process only records that are the same with BIRD IP version */
|
/* process only records that are the same with BIRD IP version */
|
||||||
#ifdef IPV6
|
#ifdef IPV6
|
||||||
if (rec.prefix.ver != RTRLIB_IPV6)
|
if (rec.prefix.ver != RTRLIB_IPV6)
|
||||||
@ -252,7 +296,7 @@ rtr_thread_update_hook(void *pfx_table, const struct pfx_record rec, const bool
|
|||||||
ip_addr ip = ip4_from_u32(rec.prefix.u.addr4.addr);
|
ip_addr ip = ip4_from_u32(rec.prefix.u.addr4.addr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* TODO: Make more effective solution with thread-safe pool/queue of rpki_entry structures
|
/* TODO: Make more effective solution with thread-safe recycle-able pool/queue of rpki_entry structures
|
||||||
* without endless allocations and frees */
|
* without endless allocations and frees */
|
||||||
struct rpki_entry *e = mb_allocz(p->p.pool, sizeof(struct rpki_entry));
|
struct rpki_entry *e = mb_allocz(p->p.pool, sizeof(struct rpki_entry));
|
||||||
e->added = added;
|
e->added = added;
|
||||||
@ -289,8 +333,8 @@ struct rpki_cache *
|
|||||||
rpki_new_cache(void)
|
rpki_new_cache(void)
|
||||||
{
|
{
|
||||||
struct rpki_cache *cache = (struct rpki_cache *)cfg_allocz(sizeof(struct rpki_cache));
|
struct rpki_cache *cache = (struct rpki_cache *)cfg_allocz(sizeof(struct rpki_cache));
|
||||||
strcpy(cache->port, RPKI_PORT);
|
|
||||||
cache->preference = RPKI_DEFAULT_CACHE_PREFERENCE;
|
cache->preference = RPKI_DEFAULT_CACHE_PREFERENCE;
|
||||||
|
/* cache port will be set afterwards */
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -416,6 +460,7 @@ create_rtrlib_tcp_socket(struct rpki_cache *cache, pool *pool)
|
|||||||
{
|
{
|
||||||
struct rtr_socket *rtrlib_tcp = mb_allocz(pool, sizeof(struct rtr_socket));
|
struct rtr_socket *rtrlib_tcp = mb_allocz(pool, sizeof(struct rtr_socket));
|
||||||
rtrlib_tcp->tr_socket = mb_allocz(pool, sizeof(struct tr_socket));
|
rtrlib_tcp->tr_socket = mb_allocz(pool, sizeof(struct tr_socket));
|
||||||
|
|
||||||
struct tr_tcp_config tcp_config = {
|
struct tr_tcp_config tcp_config = {
|
||||||
.host = cache->host,
|
.host = cache->host,
|
||||||
.port = cache->port
|
.port = cache->port
|
||||||
@ -426,6 +471,33 @@ create_rtrlib_tcp_socket(struct rpki_cache *cache, pool *pool)
|
|||||||
return rtrlib_tcp;
|
return rtrlib_tcp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct rtr_socket *
|
||||||
|
create_rtrlib_ssh_socket(struct rpki_cache *cache, pool *pool)
|
||||||
|
{
|
||||||
|
struct rtr_socket *rtrlib_ssh = mb_allocz(pool, sizeof(struct rtr_socket));
|
||||||
|
rtrlib_ssh->tr_socket = mb_allocz(pool, sizeof(struct tr_socket));
|
||||||
|
struct tr_ssh_config ssh_config = {
|
||||||
|
.host = cache->host,
|
||||||
|
.port = atoi(cache->port), /* TCP transport needs port in (char *) */
|
||||||
|
.username = cache->ssh->user,
|
||||||
|
.client_privkey_path = cache->ssh->bird_private_key,
|
||||||
|
.server_hostkey_path = cache->ssh->cache_public_key,
|
||||||
|
};
|
||||||
|
|
||||||
|
(*tr_ssh_init_fp)(&ssh_config, rtrlib_ssh->tr_socket);
|
||||||
|
|
||||||
|
return rtrlib_ssh;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct rtr_socket *
|
||||||
|
create_rtrlib_socket(struct rpki_cache *cache, pool *pool)
|
||||||
|
{
|
||||||
|
if (cache->ssh)
|
||||||
|
return create_rtrlib_ssh_socket(cache, pool);
|
||||||
|
else
|
||||||
|
return create_rtrlib_tcp_socket(cache, pool);
|
||||||
|
}
|
||||||
|
|
||||||
struct rtr_mgr_group_crate {
|
struct rtr_mgr_group_crate {
|
||||||
struct rtr_mgr_group *groups;
|
struct rtr_mgr_group *groups;
|
||||||
uint groups_len;
|
uint groups_len;
|
||||||
@ -434,6 +506,9 @@ struct rtr_mgr_group_crate {
|
|||||||
static struct rtr_mgr_group_crate
|
static struct rtr_mgr_group_crate
|
||||||
group_cache_list_by_preferences(list *cache_list, pool *pool)
|
group_cache_list_by_preferences(list *cache_list, pool *pool)
|
||||||
{
|
{
|
||||||
|
/* TODO: Improve algorithm for grouping cache servers by preferences.
|
||||||
|
* At the beginning sort a list of caches by preferences... */
|
||||||
|
|
||||||
u8 completed_preference[256];
|
u8 completed_preference[256];
|
||||||
bzero(completed_preference, sizeof(completed_preference));
|
bzero(completed_preference, sizeof(completed_preference));
|
||||||
|
|
||||||
@ -460,18 +535,27 @@ group_cache_list_by_preferences(list *cache_list, pool *pool)
|
|||||||
{
|
{
|
||||||
if (cache->preference == groups[group_idx].preference)
|
if (cache->preference == groups[group_idx].preference)
|
||||||
{
|
{
|
||||||
group->sockets[socket_idx] = cache->rtr_tcp = create_rtrlib_tcp_socket(cache, pool);
|
group->sockets[socket_idx] = cache->rtrlib_sock = create_rtrlib_socket(cache, pool);
|
||||||
socket_idx++;
|
socket_idx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
group_idx++;
|
group_idx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct rtr_mgr_group_crate grouped_list = {
|
return (struct rtr_mgr_group_crate) {groups, groups_len};
|
||||||
.groups = groups,
|
}
|
||||||
.groups_len = groups_len
|
|
||||||
};
|
/*
|
||||||
return grouped_list;
|
* Return RTR_SUCCESS or RTR_ERROR
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
rpki_start_rtrlib_mgr(struct rpki_proto *p, struct rpki_config *cf)
|
||||||
|
{
|
||||||
|
struct rtr_mgr_group_crate grouped_list = group_cache_list_by_preferences(&cf->cache_list, p->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);
|
||||||
|
|
||||||
|
return (*rtr_mgr_start_fp)(p->rtr_conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -484,20 +568,23 @@ rpki_start(struct proto *P)
|
|||||||
init_list(&p->notify_list);
|
init_list(&p->notify_list);
|
||||||
pthread_mutex_init(&p->notify_lock, NULL);
|
pthread_mutex_init(&p->notify_lock, NULL);
|
||||||
|
|
||||||
|
lock_rpki_proto_list();
|
||||||
add_tail(&rpki_proto_list, &p->rpki_node);
|
add_tail(&rpki_proto_list, &p->rpki_node);
|
||||||
|
unlock_rpki_proto_list();
|
||||||
|
|
||||||
struct rtr_mgr_group_crate grouped_list = group_cache_list_by_preferences(&cf->cache_list, P->pool);
|
if (rpki_start_rtrlib_mgr(p, cf) == RTR_SUCCESS)
|
||||||
|
|
||||||
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;
|
return PS_UP;
|
||||||
|
|
||||||
|
RPKI_ERROR(p, "Cannot start RTRLib Manager");
|
||||||
|
/* TODO: Make RPKI_TRACE() debug dump of configuration */
|
||||||
|
|
||||||
|
return PS_DOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static void
|
||||||
rpki_shutdown(struct proto *P)
|
rpki_stop_and_free_rtrlib_mgr(struct rpki_proto *p)
|
||||||
{
|
{
|
||||||
struct rpki_proto *p = (struct rpki_proto *) P;
|
RPKI_TRACE(p, "Stopping RTRLib Manager");
|
||||||
|
|
||||||
(*rtr_mgr_stop_fp)(p->rtr_conf);
|
(*rtr_mgr_stop_fp)(p->rtr_conf);
|
||||||
(*rtr_mgr_free_fp)(p->rtr_conf);
|
(*rtr_mgr_free_fp)(p->rtr_conf);
|
||||||
@ -505,30 +592,123 @@ rpki_shutdown(struct proto *P)
|
|||||||
struct rpki_cache *cache;
|
struct rpki_cache *cache;
|
||||||
WALK_LIST(cache, p->cf->cache_list)
|
WALK_LIST(cache, p->cf->cache_list)
|
||||||
{
|
{
|
||||||
(*tr_free_fp)(cache->rtr_tcp->tr_socket);
|
if (cache->rtrlib_sock)
|
||||||
mb_free(cache->rtr_tcp->tr_socket);
|
{
|
||||||
mb_free(cache->rtr_tcp);
|
(*tr_free_fp)(cache->rtrlib_sock->tr_socket);
|
||||||
if (cache->ip_buf)
|
|
||||||
mb_free(cache->ip_buf);
|
mb_free(cache->rtrlib_sock->tr_socket);
|
||||||
|
mb_free(cache->rtrlib_sock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mb_free(p->rtr_sockets);
|
mb_free(p->rtr_sockets);
|
||||||
mb_free(p->rtr_groups);
|
mb_free(p->rtr_groups);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rpki_shutdown(struct proto *P)
|
||||||
|
{
|
||||||
|
struct rpki_proto *p = (struct rpki_proto *) P;
|
||||||
|
|
||||||
|
log(L_DEBUG "------------- rpki_shutdown -------------");
|
||||||
|
|
||||||
|
lock_rpki_proto_list();
|
||||||
|
rem2_node(&p->rpki_node);
|
||||||
|
unlock_rpki_proto_list();
|
||||||
|
|
||||||
|
rpki_stop_and_free_rtrlib_mgr(p);
|
||||||
|
|
||||||
pthread_mutex_destroy(&p->notify_lock);
|
pthread_mutex_destroy(&p->notify_lock);
|
||||||
|
|
||||||
return PS_DOWN;
|
return PS_DOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static struct rpki_cache *
|
||||||
rpki_reconfigure(struct proto *p, struct proto_config *c)
|
get_cache_by_host_and_port(list *cache_list, struct rpki_cache *needle)
|
||||||
{
|
{
|
||||||
struct rpki_proto *rpki = (struct rpki_proto *) p;
|
struct rpki_cache *cache;
|
||||||
struct rpki_config *new = (struct rpki_config *) c;
|
WALK_LIST(cache, *cache_list)
|
||||||
|
{
|
||||||
|
if ((strcmp(needle->host, cache->host) == 0) && (strcmp(needle->port, cache->port) == 0))
|
||||||
|
{
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
log(L_DEBUG "------------- rpki_reconfigure -------------");
|
/*
|
||||||
|
* Return 1 if need to restart rtrlib manager
|
||||||
|
* Return 0 if not need to restart rtrlib manager
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
is_required_restart_rtrlib_mgr(struct rpki_proto *p, struct rpki_config *new_cf)
|
||||||
|
{
|
||||||
|
struct rpki_config *old_cf = p->cf;
|
||||||
|
|
||||||
|
struct rpki_cache *cache;
|
||||||
|
WALK_LIST(cache, old_cf->cache_list)
|
||||||
|
{
|
||||||
|
struct rpki_cache *match = get_cache_by_host_and_port(&new_cf->cache_list, cache);
|
||||||
|
if (!match)
|
||||||
|
{
|
||||||
|
/* some cache was deleted from old configuration */
|
||||||
|
RPKI_WARN(p, "reconfiguration has no match for cache %s:%s", cache->host, cache->port);
|
||||||
|
return 1; /* TODO: maybe can be called only rtr_stop(); without manager restart */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cache->preference != match->preference || (!!cache->ssh != !!match->ssh))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
if (cache->ssh && match->ssh)
|
||||||
|
{
|
||||||
|
if (strcmp(cache->ssh->bird_private_key, match->ssh->bird_private_key) != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (strcmp(cache->ssh->cache_public_key, match->ssh->cache_public_key) != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (strcmp(cache->ssh->user, match->ssh->user) != 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WALK_LIST(cache, new_cf->cache_list)
|
||||||
|
{
|
||||||
|
struct rpki_cache *match = get_cache_by_host_and_port(&new_cf->cache_list, cache);
|
||||||
|
if (!match)
|
||||||
|
{
|
||||||
|
/* some cache was added to new configuration */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0; /* no restart required */
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rpki_reconfigure(struct proto *P, struct proto_config *c)
|
||||||
|
{
|
||||||
|
struct rpki_proto *p = (struct rpki_proto *) P;
|
||||||
|
struct rpki_config *new_cf = (struct rpki_config *) c;
|
||||||
|
|
||||||
|
RPKI_TRACE(p, "------------- rpki_reconfigure -------------");
|
||||||
|
|
||||||
|
if (is_required_restart_rtrlib_mgr(p, new_cf))
|
||||||
|
{
|
||||||
|
RPKI_TRACE(p, "Reconfiguration: Something changed, RTRLib Manager must be restarted");
|
||||||
|
if (P->proto_state == PS_UP)
|
||||||
|
rpki_stop_and_free_rtrlib_mgr(p);
|
||||||
|
|
||||||
|
if (rpki_start_rtrlib_mgr(p, new_cf) != RTR_SUCCESS)
|
||||||
|
{
|
||||||
|
RPKI_ERROR(p, "Reconfiguration failed: Cannot start RTRLib Manager");
|
||||||
|
p->cf = new_cf;
|
||||||
|
return 0; /* FAIL */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p->cf = new_cf;
|
||||||
|
return 1; /* OK */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#define RPKI_PORT "8282"
|
#define RPKI_PORT "8282"
|
||||||
|
#define RPKI_SSH_PORT "22"
|
||||||
#define RPKI_PORT_MAX_LENGTH_STR 6
|
#define RPKI_PORT_MAX_LENGTH_STR 6
|
||||||
#define RPKI_LIBRTR_DEFAULT "librtr.so"
|
#define RPKI_LIBRTR_DEFAULT "librtr.so"
|
||||||
|
|
||||||
@ -34,6 +35,7 @@
|
|||||||
if (p->p.debug) \
|
if (p->p.debug) \
|
||||||
RPKI_LOG(L_TRACE, p, msg, ## args); \
|
RPKI_LOG(L_TRACE, p, msg, ## args); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
#define RPKI_WARN(p, msg, args...) RPKI_LOG(L_WARN, p, msg, ## args);
|
||||||
#define RPKI_ERROR(p, msg, args...) RPKI_LOG(L_ERR, p, msg, ## args);
|
#define RPKI_ERROR(p, msg, args...) RPKI_LOG(L_ERR, p, msg, ## args);
|
||||||
#define RPKI_DIE(p, msg, args...) \
|
#define RPKI_DIE(p, msg, args...) \
|
||||||
do { \
|
do { \
|
||||||
@ -41,14 +43,19 @@
|
|||||||
exit(1); \
|
exit(1); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
struct rpki_ssh_config {
|
||||||
|
char *bird_private_key;
|
||||||
|
char *cache_public_key;
|
||||||
|
char *user;
|
||||||
|
};
|
||||||
|
|
||||||
struct rpki_cache {
|
struct rpki_cache {
|
||||||
node n; /* in struct rpki_config.cache_list */
|
node n; /* in struct rpki_config.cache_list */
|
||||||
char *host; /* full domain name or ip address */
|
char *host; /* full domain name or ip address */
|
||||||
char port[RPKI_PORT_MAX_LENGTH_STR]; /* the highest port is "65535" */
|
char port[RPKI_PORT_MAX_LENGTH_STR]; /* the highest port is "65535" */
|
||||||
u8 preference; /* the most prioritized are the lowest numbers, starts with 1 */
|
u8 preference; /* the most prioritized are the lowest numbers, starts with 1 */
|
||||||
struct rtr_socket *rtr_tcp;
|
struct rpki_ssh_config *ssh; /* SSH config or NULL */
|
||||||
char *ip_buf;
|
struct rtr_socket *rtrlib_sock;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rpki_config {
|
struct rpki_config {
|
||||||
@ -59,9 +66,9 @@ struct rpki_config {
|
|||||||
|
|
||||||
struct rpki_proto {
|
struct rpki_proto {
|
||||||
struct proto p;
|
struct proto p;
|
||||||
|
struct rpki_config *cf;
|
||||||
node rpki_node; /* in rpki_proto_list */
|
node rpki_node; /* in rpki_proto_list */
|
||||||
|
|
||||||
struct rpki_config *cf;
|
|
||||||
struct rtr_mgr_config *rtr_conf;
|
struct rtr_mgr_config *rtr_conf;
|
||||||
struct rtr_mgr_group *rtr_groups;
|
struct rtr_mgr_group *rtr_groups;
|
||||||
struct rtr_socket **rtr_sockets;
|
struct rtr_socket **rtr_sockets;
|
||||||
@ -75,7 +82,6 @@ struct rpki_proto {
|
|||||||
|
|
||||||
struct rpki_cache *rpki_new_cache(void);
|
struct rpki_cache *rpki_new_cache(void);
|
||||||
|
|
||||||
|
|
||||||
static inline void rpki_lock_notify(struct rpki_proto *p) { pthread_mutex_lock(&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); }
|
static inline void rpki_unlock_notify(struct rpki_proto *p) { pthread_mutex_unlock(&p->notify_lock); }
|
||||||
|
|
||||||
|
@ -50,6 +50,11 @@ struct tr_socket {
|
|||||||
const char * (*ident_fp)(void *); /* edited for mockuping */
|
const char * (*ident_fp)(void *); /* edited for mockuping */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum rtr_rtvals {
|
||||||
|
RTR_SUCCESS = 0,
|
||||||
|
RTR_ERROR = -1
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief States of the RTR socket.
|
* @brief States of the RTR socket.
|
||||||
*/
|
*/
|
||||||
@ -135,6 +140,27 @@ struct tr_tcp_config {
|
|||||||
char *bindaddr;
|
char *bindaddr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A tr_ssh_config struct holds configuration data for an tr_ssh socket.
|
||||||
|
* @param host Hostname or IP address to connect to.
|
||||||
|
* @param port Port to connect to.
|
||||||
|
* @param bindaddr Hostname or IP address to connect from. NULL for
|
||||||
|
* determination by OS.
|
||||||
|
* @param username Username for authentication.
|
||||||
|
* @param server_hostkey_path Path to public SSH key of the server or NULL to
|
||||||
|
don't verify host authenticity.
|
||||||
|
* @param client_privkey_path Path to private key of the authentication keypair
|
||||||
|
* or NULL to use ~/.ssh/id_rsa.
|
||||||
|
*/
|
||||||
|
struct tr_ssh_config {
|
||||||
|
char *host;
|
||||||
|
unsigned int port;
|
||||||
|
char *bindaddr;
|
||||||
|
char *username;
|
||||||
|
char *server_hostkey_path;
|
||||||
|
char *client_privkey_path;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Status of a rtr_mgr_group.
|
* @brief Status of a rtr_mgr_group.
|
||||||
*/
|
*/
|
||||||
|
1
rtrlib
1
rtrlib
@ -1 +0,0 @@
|
|||||||
Subproject commit ee04ff8280baba1fc5e6e41ba7bd66bf3142d81e
|
|
Loading…
Reference in New Issue
Block a user