Commit cb064f84 authored by Pavel Tvrdik's avatar Pavel Tvrdik
Browse files

RPKI: Accept and save BGPsec Router Keys from RPKI

Adds support for receiving Router Key PDUs, saving it to disk. The path
save repository is configurable by ./configure or BIRD's configuration file.
parent 46610354
......@@ -108,6 +108,7 @@ $(objdir)/sysdep/paths.h: Makefile
echo >$@ "/* Generated by Makefile, don't edit manually! */"
echo >>$@ "#define PATH_CONFIG_FILE \"@CONFIG_FILE@\""
echo >>$@ "#define PATH_CONTROL_SOCKET \"@CONTROL_SOCKET@\""
echo >>$@ "#define PATH_RPKI_STATE_DIR \"@RPKI_STATE_DIR@\""
if test -n "@iproutedir@" ; then echo >>$@ "#define PATH_IPROUTE_DIR \"@iproutedir@\"" ; fi
# Finally include the computed dependencies
......
......@@ -104,6 +104,7 @@ config_alloc(byte *name)
c->tf_route = c->tf_proto = (struct timeformat){"%T", "%F", 20*3600};
c->tf_base = c->tf_log = (struct timeformat){"%F %T", NULL, 0};
c->gr_wait = DEFAULT_GR_WAIT;
c->rpki_state_dir = PATH_RPKI_STATE_DIR;
return c;
}
......
......@@ -31,6 +31,7 @@ struct config {
ip_addr listen_bgp_addr; /* Listening BGP socket should use this address */
unsigned listen_bgp_port; /* Listening BGP socket should use this port (0 is default) */
u32 listen_bgp_flags; /* Listening BGP socket should use these flags */
const char *rpki_state_dir; /* File path to save Router Keys for RPKI */
unsigned proto_default_debug; /* Default protocol debug mask */
unsigned proto_default_mrtdump; /* Default protocol mrtdump mask */
struct timeformat tf_route; /* Time format for 'show route' */
......
......@@ -39,12 +39,15 @@ AC_SUBST(runtimedir)
if test "$enable_debug" = yes ; then
CONFIG_FILE="bird.conf"
CONTROL_SOCKET="bird.ctl"
RPKI_STATE_DIR="rpki"
else
CONFIG_FILE="\$(sysconfdir)/bird.conf"
CONTROL_SOCKET="$runtimedir/bird.ctl"
RPKI_STATE_DIR="\$(localstatedir)/rpki"
fi
AC_SUBST(CONFIG_FILE)
AC_SUBST(CONTROL_SOCKET)
AC_SUBST(RPKI_STATE_DIR)
AC_SEARCH_LIBS(clock_gettime, [c rt posix4], ,
AC_MSG_ERROR([[Function clock_gettime not available.]]))
......
......@@ -457,7 +457,10 @@ password_item_params:
| ID expr ';' password_item_params { this_p_item->id = $2; if ($2 <= 0) cf_error("Password ID has to be greated than zero."); }
;
/* Overwrite RPKI State Dir for BGPSEC Router Keys */
CF_ADDTO(conf, rpki_state_dir)
rpki_state_dir: RPKI STATE DIR text ';' { new_config->rpki_state_dir = $4; }
/* Core commands */
CF_CLI_HELP(SHOW, ..., [[Show status information]])
......
......@@ -24,7 +24,7 @@ rpki_check_unused_hostname(void)
CF_DECLS
CF_KEYWORDS(RPKI, REMOTE, BIRD, PRIVATE, PUBLIC, KEY, SSH, ENCRYPTION, USER,
RETRY, REFRESH, EXPIRE)
RETRY, REFRESH, EXPIRE, STATE, DIR)
CF_GRAMMAR
......
......@@ -11,6 +11,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#undef LOCAL_DEBUG
......@@ -142,6 +143,17 @@ struct pdu_error {
uint8_t rest[];
};
struct pdu_router_key {
uint8_t ver;
uint8_t type;
uint8_t flags;
uint8_t zero;
uint32_t len;
uint8_t ski[RPKI_SKI_SIZE];
uint32_t asn;
uint8_t spki[RPKI_SPKI_SIZE];
};
struct pdu_reset_query {
uint8_t ver;
uint8_t type;
......@@ -328,6 +340,12 @@ rpki_pdu_body_to_host_byte_order(void *pdu)
}
case ROUTER_KEY:
{
struct pdu_router_key *rk = pdu;
rk->asn = ntohl(rk->asn);
break;
}
case SERIAL_QUERY:
case RESET_QUERY:
case CACHE_RESPONSE:
......@@ -373,6 +391,16 @@ rpki_log_packet(struct rpki_cache *cache, const void *pdu, const size_t len, con
break;
}
case ROUTER_KEY:
{
const struct pdu_router_key *rk = pdu;
bsnprintf(detail, sizeof(detail), "(AS%u %02x", rk->asn, rk->ski[0]);
for (const u8 *x = &rk->ski[1]; x < &rk->ski[RPKI_SKI_SIZE]; x++)
bsnprintf(detail+strlen(detail), sizeof(detail)-strlen(detail), ":%02x", *x);
bsnprintf(detail+strlen(detail), sizeof(detail)-strlen(detail), ")");
break;
}
default:
*detail = '\0';
}
......@@ -741,6 +769,43 @@ rpki_handle_prefix_pdu(struct rpki_cache *cache, const void *pdu)
return RPKI_SUCCESS;
}
static void
rpki_handle_router_key_pdu(struct rpki_cache *cache, const struct pdu_router_key *pdu)
{
char file_name[4096]; /* PATH_MAX? */
char ski_hex[41];
const char *state_dir = config->rpki_state_dir;
int i;
int fd = -1;
for (i = 0; i < 20; i++)
bsnprintf(ski_hex + i*2, sizeof(ski_hex) - i*2, "%02X", pdu->ski[i]);
/* Check buffer size */
size_t req_size = strlen(state_dir) + 2*sizeof(pdu->ski) + 2 + strlen(RPKI_ROUTER_KEY_EXT);
if (req_size >= sizeof(file_name))
{
CACHE_TRACE(D_EVENTS, cache, "Buffer too small for %s/%u.%s" RPKI_ROUTER_KEY_EXT, state_dir, pdu->asn, ski_hex);
return;
}
bsnprintf(file_name, sizeof(file_name), "%s/%u.%s" RPKI_ROUTER_KEY_EXT, state_dir, pdu->asn, ski_hex);
fd = open(file_name, O_WRONLY|O_CREAT, 0664);
if (fd < 0)
{
CACHE_TRACE(D_EVENTS, cache, "Cannot open file %s for write router key", file_name);
return;
}
if (write(fd, pdu->spki, RPKI_SPKI_SIZE) < 0)
CACHE_TRACE(D_EVENTS, cache, "Cannot write into %s", file_name);
else
CACHE_TRACE(D_EVENTS, cache, "Wrote router key into file %s", file_name);
close(fd);
}
static uint
rpki_check_interval(struct rpki_cache *cache, const char *(check_fn)(uint), uint interval)
{
......@@ -837,6 +902,10 @@ rpki_rx_packet(struct rpki_cache *cache, void *pdu, uint len)
rpki_handle_prefix_pdu(cache, pdu);
break;
case ROUTER_KEY:
rpki_handle_router_key_pdu(cache, pdu);
break;
case END_OF_DATA:
rpki_handle_end_of_data_pdu(cache, pdu);
break;
......@@ -853,7 +922,6 @@ rpki_rx_packet(struct rpki_cache *cache, void *pdu, uint len)
rpki_handle_error_pdu(cache, pdu);
break;
case ROUTER_KEY:
default:
CACHE_TRACE(D_PACKETS, cache, "Received unsupported type of RPKI PDU: %u", type);
};
......
......@@ -32,6 +32,10 @@
#define RPKI_MIN_VERSION 0
#define RPKI_MAX_VERSION 1
#define RPKI_SKI_SIZE 20
#define RPKI_SPKI_SIZE 91
#define RPKI_ROUTER_KEY_EXT ".key"
/*
* Used in parsing of configuration file
*/
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment