Commit 46610354 authored by Pavel Tvrdík's avatar Pavel Tvrdík Committed by Pavel Tvrdik
Browse files

RPKI protocol with one cache server per protocol

The RPKI protocol (RFC 6810) using the RTRLib
(http://rpki.realmv6.org/) that is integrated inside
the BIRD's code.

Implemeted transports are:
 - unprotected transport over TCP
 - secure transport over SSHv2

Example configuration of bird.conf:
  ...
  roa4 table r4;
  roa6 table r6;

  protocol rpki {
    debug all;

    # Import both IPv4 and IPv6 ROAs
    roa4 { table r4; };
    roa6 { table r6; };

    # Set cache server (validator) address,
    # overwrite default port 323
    remote "rpki-validator.realmv6.org" port 8282;

    # Overwrite default time intervals
    retry   10;         # Default 600 seconds
    refresh 60;         # Default 3600 seconds
    expire 600;         # Default 7200 seconds
  }

  protocol rpki {
    debug all;

    # Import only IPv4 routes
    roa4 { table r4; };

    # Set cache server address to localhost,
    # use default ports tcp => 323 or ssh => 22
    remote 127.0.0.1;

    # Use SSH transport instead of unprotected transport over TCP
    ssh encryption {
      bird private key "/home/birdgeek/.ssh/id_rsa";
      remote public key "/home/birdgeek/.ssh/known_hosts";
      user "birdgeek";
    };
  }
  ...
parent dc9f0826
......@@ -10,6 +10,7 @@ CPPFLAGS=-I$(objdir) -I$(srcdir) @CPPFLAGS@
CFLAGS=$(CPPFLAGS) @CFLAGS@
LDFLAGS=@LDFLAGS@
LIBS=@LIBS@
DAEMON_LIBS=@DAEMON_LIBS@
CLIENT_LIBS=@CLIENT_LIBS@
CC=@CC@
M4=@M4@
......@@ -55,6 +56,8 @@ all: daemon cli
daemon: $(daemon)
cli: $(client)
$(daemon): LIBS += $(DAEMON_LIBS)
# Include directories
dirs := client conf doc filter lib nest $(addprefix proto/,$(protocols)) @sysdep_dirs@
......
......@@ -168,7 +168,7 @@ fi
AC_SUBST(iproutedir)
# all_protocols="$proto_bfd bgp ospf pipe radv rip static"
all_protocols="$proto_bfd ospf pipe radv rip static"
all_protocols="$proto_bfd ospf pipe radv rip rpki static"
all_protocols=`echo $all_protocols | sed 's/ /,/g'`
......@@ -226,6 +226,10 @@ if test "$enable_debug" = yes ; then
fi
fi
DAEMON_LIBS=
AC_CHECK_LIB(dl, dlopen, DAEMON_LIBS="-ldl")
AC_SUBST(DAEMON_LIBS)
CLIENT=birdcl
CLIENT_LIBS=
if test "$enable_client" = yes ; then
......
......@@ -464,7 +464,7 @@ protocol rip {
Create a new ROA (Route Origin Authorization) table. ROA tables can be
used to validate route origination of BGP routes. A ROA table contains
ROA entries, each consist of a network prefix, a max prefix length and
an AS number. A ROA entry specifies prefixes which could be originated
an AS (Autonomous System) number. A ROA entry specifies prefixes which could be originated
by that AS number. ROA tables could be filled with data from RPKI (RFC
6480) or from public databases like Whois. ROA tables are examined by
<cf/roa_check()/ operator in filters.
......@@ -3494,6 +3494,136 @@ protocol rip {
}
</code>
<sect>RPKI
<p>The Resource Public Key Infrastructure (RPKI) to Router Protocol (RFC 6810)
is a protocol for receiving Route Origin Authorizations (ROAs) from trusted
caches (RPKI validators). ROAs are documents used to link a set of prefixes
with an origin ASN.
The ROAs could be
In BIRD, it is implemented only receiving prefix origin data from a trusted cache.
RPKI-based origin validation uses some of the RPKI data to allow a router
to version ... FIXME! srify that the autonomous system announcing an IP address prefix is in fact
authorized to do so. This is not crypto checked so can be violated. But it
should prevent the vast majority of accidental 'hijackings' on the internet
It is possible to configure only one remote cache server per protocol yet.
<code>
protocol rpki [&lt;name&gt;] {
remote &lt;ip&gt; | "&lt;domain&gt;" [port &lt;num&gt;];
port &lt;num&gt;;
retry &lt;num&gt;;
refresh &lt;num&gt;;
expire &lt;num&gt;;
ssh encryption {
bird private key "&lt;/path/to/id_rsa&gt;";
remote public key "&lt;/path/to/known_host&gt;";
user "&lt;name&gt;";
};
}
</code>
<sect1>RPKI protocol options
<descrip>
<tag>roa table <m/name/</tag>
Specifies the roa table into which will import the routes from cache.
This option is required.
<tag>remote <m/ip/ | "<m/hostname/" [port &lt;num&gt;]</tag>
Specifies a destination address of the cache server.
Can be specified by an IP address or by full domain name.
Only one cache can be specified per protocol.
<tag>port <m/num/</tag>
Specifies the port number.
The default port number is 323 for transport without any encryption
and 22 for transport with SSH encryption.
<tag>retry <m/num/</tag>
Time period in seconds between a failed query and the next attempt.
Default: 600 seconds
<tag>refresh <m/num/</tag>
Time period in seconds.
Tells how long to wait before next attempting to poll the cache, using
a Serial Query or Reset Query PDU. Must be lower than 1 hour.
Default: 3600 seconds
<tag>expire <m/num/</tag>
Time period in seconds.
Received records are deleted if the client was unable to refresh data
for this time period.
Default: 7200 seconds
<tag>ssh encryption { <m/ssh encryption options.../ }</tag>
This enables a SSH encryption.
Default: off
</descrip>
<sect1>SSH encryption options in RPKI protocol
<descrip>
<tag>bird private key "<m///path/to/id_rsa"</tag>
A path to the BIRD's private SSH key for authentication.
It can be a <cf/id_rsa/ file.
<tag>remote public key "<m///path/to/known_host"</tag>
A path to the cache's public SSH key for verification identity
of the cache server. It could be a <cf/known_host/ file.
<tag>user "<m/name/"</tag>
A SSH user name for authentication. This option is a required.
</descrip>
<sect1>Examples:
<p>Typical RPKI configuration with BGP origin validation
<code>
roa4 table r4;
roa6 table r6;
protocol rpki {
debug all;
roa4 { table r4; };
roa6 { table r6; };
remote "rpki-validator.realmv6.org";
}
filter peer_in {
if (roa_check(r4, net, bgp_path.last) = ROA_INVALID ||
roa_check(r6, net, bgp_path.last) = ROA_INVALID) then
{
print "ROA check failed for ", net, " ASN ", bgp_path.last;
reject;
}
accept;
}
protocol bgp my_peer {
local as 65000;
neighbor 192.0.2.1 as 65001;
import filter peer_in;
}
</code>
<p>A configuration using SSHv2 transport encryption:
<code>
roa4 table r4;
roa6 table r6;
protocol rpki {
debug all;
roa4 { table r4; };
roa6 { table r6; };
remote 127.0.0.1 port 2345;
ssh encryption {
bird private key "/home/birdgeek/.ssh/id_rsa";
remote public key "/home/birdgeek/.ssh/known_hosts";
user "birdgeek";
};
}
</code>
<sect>Static
......
......@@ -1277,11 +1277,15 @@ interpret(struct f_inst *what)
}
struct rtable *table = ((struct f_inst_roa_check *) what)->rtc->table;
if (!table || table->addr_type != (v1.val.net->type == NET_IP4 ? NET_ROA4 : NET_ROA6))
if (!table || (table->addr_type != NET_ROA4 && table->addr_type != NET_ROA6))
runtime("Missing ROA table");
res.type = T_ENUM_ROA;
res.val.i = net_roa_check(table, v1.val.net, as);
if (table->addr_type != (v1.val.net->type == NET_IP4 ? NET_ROA4 : NET_ROA6))
res.val.i = ROA_UNKNOWN; /* Prefix and table type mismatch */
else
res.val.i = net_roa_check(table, v1.val.net, as);
break;
......
......@@ -2,6 +2,6 @@ src := bitops.c checksum.c ip.c lists.c md5.c net.c patmatch.c printf.c sha1.c s
obj := $(src-o-files)
$(all-client)
src := bitops.c checksum.c event.c idm.c ip.c lists.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c tbf.c xmalloc.c
src := bitops.c checksum.c event.c idm.c ip.c libssh.c lists.c md5.c mempool.c net.c patmatch.c printf.c resource.c sha1.c sha256.c sha512.c slab.c slists.c tbf.c xmalloc.c
obj := $(src-o-files)
$(all-daemon)
/*
* BIRD -- Mockup of SSH Library for loading LibSSH using dlopen
*
* (c) 2015 CZ.NIC
*
* This file was part of SSH Library: http://www.libssh.org/
* (c) 2003-2009 by Aris Adamantiadis (SSH Library)
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#include <dlfcn.h>
#include "nest/bird.h"
#include "lib/libssh.h"
#define FILENAME_OF_SHARED_OBJECT_LIBSSH "libssh.so"
ssh_session (*ssh_new)(void);
void (*ssh_set_blocking)(ssh_session session, int blocking);
int (*ssh_options_set)(ssh_session session, enum ssh_options_e type, const void *value);
int (*ssh_connect)(ssh_session session);
socket_t (*ssh_get_fd)(ssh_session session);
int (*ssh_is_server_known)(ssh_session session);
int (*ssh_userauth_publickey_auto)(ssh_session session, const char *username, const char *passphrase);
const char * (*ssh_get_error)(void *error);
int (*ssh_get_error_code)(void *error);
void (*ssh_disconnect)(ssh_session session);
void (*ssh_free)(ssh_session session);
ssh_channel (*ssh_channel_new)(ssh_session session);
int (*ssh_channel_is_open)(ssh_channel channel);
int (*ssh_channel_close)(ssh_channel channel);
void (*ssh_channel_free)(ssh_channel channel);
int (*ssh_channel_open_session)(ssh_channel channel);
int (*ssh_channel_request_subsystem)(ssh_channel channel, const char *subsystem);
int (*ssh_channel_read_nonblocking)(ssh_channel channel, void *dest, uint32_t count, int is_stderr);
int (*ssh_channel_is_eof)(ssh_channel channel);
int (*ssh_channel_select)(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct timeval * timeout);
int (*ssh_channel_write)(ssh_channel channel, const void *data, uint32_t len);
static void *libssh;
/*
* @return NULL if success
* @return string with error if failed
*/
const char *
load_libssh(void)
{
char *err_buf;
libssh = dlopen(FILENAME_OF_SHARED_OBJECT_LIBSSH, RTLD_LAZY);
if (!libssh)
{
/* This would be probably often repeated problem */
char *help_msg = "You have to install libssh library.";
err_buf = mb_alloc(&root_pool, 512); /* FIXME: free memory */
bsnprintf(err_buf, 512, "%s. %s", dlerror(), help_msg);
return err_buf;
}
dlerror(); /* Clear any existing error */
ssh_new = (ssh_session (*)(void)) dlsym(libssh, "ssh_new");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_set_blocking = (void (*)(ssh_session, int)) dlsym(libssh, "ssh_set_blocking");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_options_set = (int (*)(ssh_session, enum ssh_options_e, const void *)) dlsym(libssh, "ssh_options_set");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_connect = (int (*)(ssh_session)) dlsym(libssh, "ssh_connect");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_get_fd = (socket_t (*)(ssh_session)) dlsym(libssh, "ssh_get_fd");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_is_server_known = (int (*)(ssh_session)) dlsym(libssh, "ssh_is_server_known");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_userauth_publickey_auto = (int (*)(ssh_session, const char *, const char *)) dlsym(libssh, "ssh_userauth_publickey_auto");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_get_error = (const char * (*)(void *)) dlsym(libssh, "ssh_get_error");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_get_error_code = (int (*)(void *)) dlsym(libssh, "ssh_get_error_code");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_disconnect = (void (*)(ssh_session)) dlsym(libssh, "ssh_disconnect");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_free = (void (*)(ssh_session)) dlsym(libssh, "ssh_free");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_channel_new = (ssh_channel (*)(ssh_session)) dlsym(libssh, "ssh_channel_new");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_channel_is_open = (int (*)(ssh_channel)) dlsym(libssh, "ssh_channel_is_open");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_channel_close = (int (*)(ssh_channel)) dlsym(libssh, "ssh_channel_close");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_channel_free = (void (*)(ssh_channel)) dlsym(libssh, "ssh_channel_free");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_channel_open_session = (int (*)(ssh_channel)) dlsym(libssh, "ssh_channel_open_session");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_channel_request_subsystem = (int (*)(ssh_channel, const char *)) dlsym(libssh, "ssh_channel_request_subsystem");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_channel_read_nonblocking = (int (*)(ssh_channel, void *, uint32_t, int)) dlsym(libssh, "ssh_channel_read_nonblocking");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_channel_is_eof = (int (*)(ssh_channel)) dlsym(libssh, "ssh_channel_is_eof");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_channel_select = (int (*)(ssh_channel *, ssh_channel *, ssh_channel *, struct timeval *)) dlsym(libssh, "ssh_channel_select");
if ((err_buf = dlerror()) != NULL)
return err_buf;
ssh_channel_write = (int (*)(ssh_channel, const void *, uint32_t)) dlsym(libssh, "ssh_channel_write");
if ((err_buf = dlerror()) != NULL)
return err_buf;
return NULL;
}
/*
* BIRD -- Mockup headers of SSH Library for loading LibSSH using dlopen
*
* (c) 2015 CZ.NIC
*
* This file was part of SSH Library: http://www.libssh.org/
* (c) 2003-2009 by Aris Adamantiadis (SSH Library)
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_LIBSSH_H_
#define _BIRD_LIBSSH_H_
#include <unistd.h>
#include <inttypes.h>
typedef struct ssh_session_struct* ssh_session;
typedef struct ssh_channel_struct* ssh_channel;
/* Error return codes */
#define SSH_OK 0 /* No error */
#define SSH_ERROR -1 /* Error of some kind */
#define SSH_AGAIN -2 /* The nonblocking call must be repeated */
#define SSH_EOF -127 /* We have already a eof */
enum ssh_server_known_e {
SSH_SERVER_ERROR=-1,
SSH_SERVER_NOT_KNOWN=0,
SSH_SERVER_KNOWN_OK,
SSH_SERVER_KNOWN_CHANGED,
SSH_SERVER_FOUND_OTHER,
SSH_SERVER_FILE_NOT_FOUND
};
enum ssh_auth_e {
SSH_AUTH_SUCCESS=0,
SSH_AUTH_DENIED,
SSH_AUTH_PARTIAL,
SSH_AUTH_INFO,
SSH_AUTH_AGAIN,
SSH_AUTH_ERROR=-1
};
enum ssh_error_types_e {
SSH_NO_ERROR=0,
SSH_REQUEST_DENIED,
SSH_FATAL,
SSH_EINTR
};
enum ssh_options_e {
SSH_OPTIONS_HOST,
SSH_OPTIONS_PORT,
SSH_OPTIONS_PORT_STR,
SSH_OPTIONS_FD,
SSH_OPTIONS_USER,
SSH_OPTIONS_SSH_DIR,
SSH_OPTIONS_IDENTITY,
SSH_OPTIONS_ADD_IDENTITY,
SSH_OPTIONS_KNOWNHOSTS,
SSH_OPTIONS_TIMEOUT,
SSH_OPTIONS_TIMEOUT_USEC,
SSH_OPTIONS_SSH1,
SSH_OPTIONS_SSH2,
SSH_OPTIONS_LOG_VERBOSITY,
SSH_OPTIONS_LOG_VERBOSITY_STR,
SSH_OPTIONS_CIPHERS_C_S,
SSH_OPTIONS_CIPHERS_S_C,
SSH_OPTIONS_COMPRESSION_C_S,
SSH_OPTIONS_COMPRESSION_S_C,
SSH_OPTIONS_PROXYCOMMAND,
SSH_OPTIONS_BINDADDR,
SSH_OPTIONS_STRICTHOSTKEYCHECK,
SSH_OPTIONS_COMPRESSION,
SSH_OPTIONS_COMPRESSION_LEVEL,
SSH_OPTIONS_KEY_EXCHANGE,
SSH_OPTIONS_HOSTKEYS,
SSH_OPTIONS_GSSAPI_SERVER_IDENTITY,
SSH_OPTIONS_GSSAPI_CLIENT_IDENTITY,
SSH_OPTIONS_GSSAPI_DELEGATE_CREDENTIALS,
SSH_OPTIONS_HMAC_C_S,
SSH_OPTIONS_HMAC_S_C,
};
enum {
/** No logging at all
*/
SSH_LOG_NOLOG=0,
/** Only warnings
*/
SSH_LOG_WARNING,
/** High level protocol information
*/
SSH_LOG_PROTOCOL,
/** Lower level protocol infomations, packet level
*/
SSH_LOG_PACKET,
/** Every function path
*/
SSH_LOG_FUNCTIONS
};
#ifndef socket_t
typedef int socket_t;
#endif
extern ssh_session (*ssh_new)(void);
extern void (*ssh_set_blocking)(ssh_session session, int blocking);
extern int (*ssh_options_set)(ssh_session session, enum ssh_options_e type, const void *value);
extern int (*ssh_connect)(ssh_session session);
extern socket_t (*ssh_get_fd)(ssh_session session);
extern int (*ssh_is_server_known)(ssh_session session);
extern int (*ssh_userauth_publickey_auto)(ssh_session session, const char *username, const char *passphrase);
extern const char * (*ssh_get_error)(void *error);
extern int (*ssh_get_error_code)(void *error);
extern void (*ssh_disconnect)(ssh_session session);
extern void (*ssh_free)(ssh_session session);
extern ssh_channel (*ssh_channel_new)(ssh_session session);
extern int (*ssh_channel_is_open)(ssh_channel channel);
extern int (*ssh_channel_close)(ssh_channel channel);
extern void (*ssh_channel_free)(ssh_channel channel);
extern int (*ssh_channel_open_session)(ssh_channel channel);
extern int (*ssh_channel_request_subsystem)(ssh_channel channel, const char *subsystem);
extern int (*ssh_channel_read_nonblocking)(ssh_channel channel, void *dest, uint32_t count, int is_stderr);
extern int (*ssh_channel_is_eof)(ssh_channel channel);
extern int (*ssh_channel_select)(ssh_channel *readchans, ssh_channel *writechans, ssh_channel *exceptchans, struct timeval * timeout);
extern int (*ssh_channel_write)(ssh_channel channel, const void *data, uint32_t len);
const char *load_libssh(void);
#endif /* _BIRD_LIBSSH_H_ */
......@@ -8,7 +8,9 @@ const char * const net_label[] = {
[NET_IP4] = "ipv4",
[NET_IP6] = "ipv6",
[NET_VPN4] = "vpn4",
[NET_VPN6] = "vpn6"
[NET_VPN6] = "vpn6",
[NET_ROA4] = "roa4",
[NET_ROA6] = "roa6",
};
const u16 net_addr_length[] = {
......
......@@ -25,6 +25,8 @@
#define NB_IP6 (1 << NET_IP6)
#define NB_VPN4 (1 << NET_VPN4)
#define NB_VPN6 (1 << NET_VPN6)
#define NB_ROA4 (1 << NET_ROA4)
#define NB_ROA6 (1 << NET_ROA6)
#define NB_IP (NB_IP4 | NB_IP6)
#define NB_ANY 0xffffffff
......
......@@ -31,7 +31,7 @@
struct pool {
resource r;
list inside;
char *name;
const char *name;
};
static void pool_dump(resource *);
......@@ -61,7 +61,7 @@ static int indent;
* parent pool.
*/
pool *
rp_new(pool *p, char *name)
rp_new(pool *p, const char *name)
{
pool *z = ralloc(p, &pool_class);
z->name = name;
......
......@@ -37,7 +37,7 @@ struct resclass {
typedef struct pool pool;
void resource_init(void);
pool *rp_new(pool *, char *); /* Create new pool */
pool *rp_new(pool *, const char *); /* Create new pool */
void rfree(void *); /* Free single resource */
void rdump(void *); /* Dump to debug output */
size_t rmemsize(void *res); /* Return size of memory used by the resource */
......
......@@ -12,6 +12,24 @@
#include <errno.h>
#include "lib/resource.h"
#include "lib/libssh.h"
struct ssh_sock {
const char *username; /* (Required) SSH user name */
const char *server_hostkey_path; /* (Optional) Filepath to the SSH public key of remote side, can be knownhost file */
const char *client_privkey_path; /* (Optional) Filepath to the SSH private key of BIRD */
const char *subsystem; /* (Optional) Name of SSH subsytem */
ssh_session session; /* Internal */
ssh_channel channel; /* Internal */
int state; /* Internal */
#define SK_SSH_CONNECT 0 /* Start state */
#define SK_SSH_SERVER_KNOWN 1 /* Internal */
#define SK_SSH_USERAUTH 2 /* Internal */
#define SK_SSH_CHANNEL 3 /* Internal */
#define SK_SSH_SESSION 4 /* Internal */
#define SK_SSH_SUBSYSTEM 5 /* Internal */
#define SK_SSH_ESTABLISHED 6 /* Final state */
};
typedef struct birdsock {
resource r;
......@@ -19,6 +37,7 @@ typedef struct birdsock {
int type; /* Socket type */
void *data; /* User data */
ip_addr saddr, daddr; /* IPA_NONE = unspecified */
const char *host; /* Alternative to daddr, NULL = unspecified */
uint sport, dport; /* 0 = unspecified (for IP: protocol type) */
int tos; /* TOS / traffic class, -1 = default */
int priority; /* Local socket priority, -1 = default */
......@@ -51,7 +70,8 @@ typedef struct birdsock {
node n;
void *rbuf_alloc, *tbuf_alloc;
char *password; /* Password for MD5 authentication */
char *err; /* Error message */
const char *err; /* Error message */
struct ssh_sock *ssh; /* Used in SK_SSH */
} sock;
sock *sock_new(pool *); /* Allocate new socket */
......@@ -115,6 +135,8 @@ extern int sk_priority_control; /* Suggested priority for control traffic, shou
#define SK_MAGIC 7 /* Internal use by sysdep code */
#define SK_UNIX_PASSIVE 8
#define SK_UNIX 9
#define SK_SSH_ACTIVE 10 /* - - * * - ? - DA = host */
#define SK_SSH 11
/* Socket families */
......
......@@ -39,12 +39,10 @@ static int graceful_restart_state;
static u32 graceful_restart_locks;
static char *p_states[] = { "DOWN", "START", "UP", "STOP" };
static char *cs_states[] = {
[CS_DOWN] = "DOWN",
[CS_START] = "START",
[CS_UP] = "UP",
[CS_FLUSHING] = "FLUSHING"
};
#if defined(LOCAL_DEBUG) || defined(GLOBAL_DEBUG)
static char *cs_states[] = { "DOWN", "START", "UP", "FLUSHING" };
#endif
extern struct protocol proto_unix_iface;
......@@ -1263,6 +1261,9 @@ protos_build(void)
proto_build(&proto_bfd);
bfd_init_all();
#endif
#ifdef CONFIG_RPKI
proto_build(&proto_rpki);
#endif
proto_pool = rp_new(&root_pool, "Protocols");
proto_shutdown_timer = tm_new(proto_pool);
......
......@@ -81,7 +81,7 @@ void protos_dump_all(void);
extern struct protocol
proto_device, proto_radv, proto_rip, proto_static,
proto_ospf, proto_pipe, proto_bgp, proto_bfd;
proto_ospf, proto_pipe, proto_bgp, proto_bfd, proto_rpki;