3 * Copyright (C) 2013 Michael Mester (m.mester@fu-berlin.de), for FU Berlin
4 * Copyright (C) 2014-2017 Andreas Reuter (andreas.reuter@fu-berlin.de), for FU
6 * Copyright (C) 2016-2017 Colin Sames (colin.sames@haw-hamburg.de), for HAW
8 * Copyright (C) 2017-2018 Marcel Röthke (marcel.roethke@haw-hamburg.de),
11 * This file is part of FRRouting.
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the Free
15 * Software Foundation; either version 2 of the License, or (at your option)
18 * This program is distributed in the hope that it will be useful, but WITHOUT
19 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
23 * You should have received a copy of the GNU General Public License along
24 * with this program; see the file COPYING; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 /* If rtrlib compiled with ssh support, don`t fail build */
29 #define LIBSSH_LEGACY_0_4
43 #include "bgpd/bgpd.h"
44 #include "bgpd/bgp_table.h"
45 #include "bgp_advertise.h"
46 #include "bgpd/bgp_debug.h"
47 #include "bgpd/bgp_attr.h"
48 #include "bgpd/bgp_aspath.h"
49 #include "bgpd/bgp_route.h"
50 #include "bgpd/bgp_rpki.h"
51 #include "northbound_cli.h"
53 #include "lib/network.h"
54 #include "lib/thread.h"
55 #ifndef VTYSH_EXTRACT_PL
56 #include "rtrlib/rtrlib.h"
60 #include "lib/version.h"
62 #ifndef VTYSH_EXTRACT_PL
63 #include "bgpd/bgp_rpki_clippy.c"
66 static struct thread
*t_rpki
;
68 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_CACHE
, "BGP RPKI Cache server");
69 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_CACHE_GROUP
, "BGP RPKI Cache server group");
71 #define POLLING_PERIOD_DEFAULT 3600
72 #define EXPIRE_INTERVAL_DEFAULT 7200
73 #define RETRY_INTERVAL_DEFAULT 600
75 #define RPKI_DEBUG(...) \
77 zlog_debug("RPKI: " __VA_ARGS__); \
80 #define RPKI_OUTPUT_STRING "Control rpki specific settings\n"
83 enum { TCP
, SSH
} type
;
84 struct tr_socket
*tr_socket
;
86 struct tr_tcp_config
*tcp_config
;
87 struct tr_ssh_config
*ssh_config
;
89 struct rtr_socket
*rtr_socket
;
93 enum return_values
{ SUCCESS
= 0, ERROR
= -1 };
95 struct rpki_for_each_record_arg
{
97 unsigned int *prefix_amount
;
101 static int start(void);
102 static void stop(void);
103 static int reset(bool force
);
104 static struct rtr_mgr_group
*get_connected_group(void);
105 static void print_prefix_table(struct vty
*vty
);
106 static void install_cli_commands(void);
107 static int config_write(struct vty
*vty
);
108 static int config_on_exit(struct vty
*vty
);
109 static void free_cache(struct cache
*cache
);
110 static struct rtr_mgr_group
*get_groups(void);
111 #if defined(FOUND_SSH)
112 static int add_ssh_cache(const char *host
, const unsigned int port
,
113 const char *username
, const char *client_privkey_path
,
114 const char *client_pubkey_path
,
115 const char *server_pubkey_path
,
116 const uint8_t preference
, const char *bindaddr
);
118 static struct rtr_socket
*create_rtr_socket(struct tr_socket
*tr_socket
);
119 static struct cache
*find_cache(const uint8_t preference
);
120 static int add_tcp_cache(const char *host
, const char *port
,
121 const uint8_t preference
, const char *bindaddr
);
122 static void print_record(const struct pfx_record
*record
, struct vty
*vty
);
123 static int is_synchronized(void);
124 static int is_running(void);
125 static void route_match_free(void *rule
);
126 static enum route_map_cmd_result_t
route_match(void *rule
,
127 const struct prefix
*prefix
,
130 static void *route_match_compile(const char *arg
);
131 static void revalidate_bgp_node(struct bgp_dest
*dest
, afi_t afi
, safi_t safi
);
132 static void revalidate_all_routes(void);
134 static struct rtr_mgr_config
*rtr_config
;
135 static struct list
*cache_list
;
136 static int rtr_is_running
;
137 static int rtr_is_stopping
;
138 static _Atomic
int rtr_update_overflow
;
139 static int rpki_debug
;
140 static unsigned int polling_period
;
141 static unsigned int expire_interval
;
142 static unsigned int retry_interval
;
143 static int rpki_sync_socket_rtr
;
144 static int rpki_sync_socket_bgpd
;
146 static struct cmd_node rpki_node
= {
149 .parent_node
= CONFIG_NODE
,
150 .prompt
= "%s(config-rpki)# ",
151 .config_write
= config_write
,
152 .node_exit
= config_on_exit
,
154 static const struct route_map_rule_cmd route_match_rpki_cmd
= {
155 "rpki", route_match
, route_match_compile
, route_match_free
};
157 static void *malloc_wrapper(size_t size
)
159 return XMALLOC(MTYPE_BGP_RPKI_CACHE
, size
);
162 static void *realloc_wrapper(void *ptr
, size_t size
)
164 return XREALLOC(MTYPE_BGP_RPKI_CACHE
, ptr
, size
);
167 static void free_wrapper(void *ptr
)
169 XFREE(MTYPE_BGP_RPKI_CACHE
, ptr
);
172 static void init_tr_socket(struct cache
*cache
)
174 if (cache
->type
== TCP
)
175 tr_tcp_init(cache
->tr_config
.tcp_config
,
177 #if defined(FOUND_SSH)
179 tr_ssh_init(cache
->tr_config
.ssh_config
,
184 static void free_tr_socket(struct cache
*cache
)
186 if (cache
->type
== TCP
)
187 tr_tcp_init(cache
->tr_config
.tcp_config
,
189 #if defined(FOUND_SSH)
191 tr_ssh_init(cache
->tr_config
.ssh_config
,
196 static int rpki_validate_prefix(struct peer
*peer
, struct attr
*attr
,
197 const struct prefix
*prefix
);
199 static void ipv6_addr_to_network_byte_order(const uint32_t *src
, uint32_t *dest
)
203 for (i
= 0; i
< 4; i
++)
204 dest
[i
] = htonl(src
[i
]);
207 static void ipv6_addr_to_host_byte_order(const uint32_t *src
, uint32_t *dest
)
211 for (i
= 0; i
< 4; i
++)
212 dest
[i
] = ntohl(src
[i
]);
215 static enum route_map_cmd_result_t
route_match(void *rule
,
216 const struct prefix
*prefix
,
219 int *rpki_status
= rule
;
220 struct bgp_path_info
*path
;
224 if (rpki_validate_prefix(path
->peer
, path
->attr
, prefix
)
232 static void *route_match_compile(const char *arg
)
236 rpki_status
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(int));
238 if (strcmp(arg
, "valid") == 0)
239 *rpki_status
= RPKI_VALID
;
240 else if (strcmp(arg
, "invalid") == 0)
241 *rpki_status
= RPKI_INVALID
;
243 *rpki_status
= RPKI_NOTFOUND
;
248 static void route_match_free(void *rule
)
250 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
253 static struct rtr_socket
*create_rtr_socket(struct tr_socket
*tr_socket
)
255 struct rtr_socket
*rtr_socket
=
256 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct rtr_socket
));
257 rtr_socket
->tr_socket
= tr_socket
;
261 static struct cache
*find_cache(const uint8_t preference
)
263 struct listnode
*cache_node
;
266 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
267 if (cache
->preference
== preference
)
273 static void print_record(const struct pfx_record
*record
, struct vty
*vty
)
275 char ip
[INET6_ADDRSTRLEN
];
277 lrtr_ip_addr_to_str(&record
->prefix
, ip
, sizeof(ip
));
278 vty_out(vty
, "%-40s %3u - %3u %10u\n", ip
, record
->min_len
,
279 record
->max_len
, record
->asn
);
282 static void print_record_by_asn(const struct pfx_record
*record
, void *data
)
284 struct rpki_for_each_record_arg
*arg
= data
;
285 struct vty
*vty
= arg
->vty
;
287 if (record
->asn
== arg
->as
) {
288 (*arg
->prefix_amount
)++;
289 print_record(record
, vty
);
293 static void print_record_cb(const struct pfx_record
*record
, void *data
)
295 struct rpki_for_each_record_arg
*arg
= data
;
296 struct vty
*vty
= arg
->vty
;
298 (*arg
->prefix_amount
)++;
300 print_record(record
, vty
);
303 static struct rtr_mgr_group
*get_groups(void)
305 struct listnode
*cache_node
;
306 struct rtr_mgr_group
*rtr_mgr_groups
;
309 int group_count
= listcount(cache_list
);
311 if (group_count
== 0)
314 rtr_mgr_groups
= XMALLOC(MTYPE_BGP_RPKI_CACHE_GROUP
,
315 group_count
* sizeof(struct rtr_mgr_group
));
319 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
320 rtr_mgr_groups
[i
].sockets
= &cache
->rtr_socket
;
321 rtr_mgr_groups
[i
].sockets_len
= 1;
322 rtr_mgr_groups
[i
].preference
= cache
->preference
;
324 init_tr_socket(cache
);
329 return rtr_mgr_groups
;
332 inline int is_synchronized(void)
334 return rtr_is_running
&& rtr_mgr_conf_in_sync(rtr_config
);
337 inline int is_running(void)
339 return rtr_is_running
;
342 static struct prefix
*pfx_record_to_prefix(struct pfx_record
*record
)
344 struct prefix
*prefix
= prefix_new();
346 prefix
->prefixlen
= record
->min_len
;
348 if (record
->prefix
.ver
== LRTR_IPV4
) {
349 prefix
->family
= AF_INET
;
350 prefix
->u
.prefix4
.s_addr
= htonl(record
->prefix
.u
.addr4
.addr
);
352 prefix
->family
= AF_INET6
;
353 ipv6_addr_to_network_byte_order(record
->prefix
.u
.addr6
.addr
,
354 prefix
->u
.prefix6
.s6_addr32
);
360 static int bgpd_sync_callback(struct thread
*thread
)
363 struct listnode
*node
;
364 struct prefix
*prefix
;
365 struct pfx_record rec
;
367 int socket
= THREAD_FD(thread
);
369 thread_add_read(bm
->master
, bgpd_sync_callback
, NULL
, socket
, &t_rpki
);
371 if (atomic_load_explicit(&rtr_update_overflow
, memory_order_seq_cst
)) {
372 while (read(socket
, &rec
, sizeof(rec
) != -1))
375 atomic_store_explicit(&rtr_update_overflow
, 0,
376 memory_order_seq_cst
);
377 revalidate_all_routes();
381 retval
= read(socket
, &rec
, sizeof(rec
));
382 if (retval
!= sizeof(rec
)) {
383 RPKI_DEBUG("Could not read from socket");
387 /* RTR-Server crashed/terminated, let's handle and switch
388 * to the second available RTR-Server according to preference.
390 if (rec
.socket
&& rec
.socket
->state
== RTR_ERROR_FATAL
) {
395 prefix
= pfx_record_to_prefix(&rec
);
397 afi_t afi
= (rec
.prefix
.ver
== LRTR_IPV4
) ? AFI_IP
: AFI_IP6
;
399 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
402 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
403 if (!bgp
->rib
[afi
][safi
])
406 struct bgp_dest
*match
;
407 struct bgp_dest
*node
;
409 match
= bgp_table_subtree_lookup(bgp
->rib
[afi
][safi
],
414 if (bgp_dest_has_bgp_path_info_data(node
)) {
415 revalidate_bgp_node(node
, afi
, safi
);
418 node
= bgp_route_next_until(node
, match
);
423 prefix_free(&prefix
);
427 static void revalidate_bgp_node(struct bgp_dest
*bgp_dest
, afi_t afi
,
430 struct bgp_adj_in
*ain
;
432 for (ain
= bgp_dest
->adj_in
; ain
; ain
= ain
->next
) {
433 struct bgp_path_info
*path
=
434 bgp_dest_get_bgp_path_info(bgp_dest
);
435 mpls_label_t
*label
= NULL
;
436 uint32_t num_labels
= 0;
438 if (path
&& path
->extra
) {
439 label
= path
->extra
->label
;
440 num_labels
= path
->extra
->num_labels
;
442 (void)bgp_update(ain
->peer
, bgp_dest_get_prefix(bgp_dest
),
443 ain
->addpath_rx_id
, ain
->attr
, afi
, safi
,
444 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
, label
,
445 num_labels
, 1, NULL
);
449 static void revalidate_all_routes(void)
452 struct listnode
*node
;
456 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
458 struct listnode
*peer_listnode
;
460 for (ALL_LIST_ELEMENTS_RO(bgp
->peer
, peer_listnode
, peer
)) {
461 FOREACH_AFI_SAFI (afi
, safi
) {
462 if (!peer
->afc_nego
[afi
][safi
])
465 if (!peer
->bgp
->rib
[afi
][safi
])
468 bgp_soft_reconfig_in(peer
, afi
, safi
);
474 static void rpki_connection_status_cb(const struct rtr_mgr_group
*group
475 __attribute__((unused
)),
476 enum rtr_mgr_status status
,
477 const struct rtr_socket
*socket
478 __attribute__((unused
)),
479 void *data
__attribute__((unused
)))
481 struct pfx_record rec
= {0};
484 if (rtr_is_stopping
||
485 atomic_load_explicit(&rtr_update_overflow
, memory_order_seq_cst
))
488 if (status
== RTR_MGR_ERROR
)
491 retval
= write(rpki_sync_socket_rtr
, &rec
, sizeof(rec
));
492 if (retval
== -1 && (errno
== EAGAIN
|| errno
== EWOULDBLOCK
))
493 atomic_store_explicit(&rtr_update_overflow
, 1,
494 memory_order_seq_cst
);
496 else if (retval
!= sizeof(rec
))
497 RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
500 static void rpki_update_cb_sync_rtr(struct pfx_table
*p
__attribute__((unused
)),
501 const struct pfx_record rec
,
502 const bool added
__attribute__((unused
)))
505 || atomic_load_explicit(&rtr_update_overflow
, memory_order_seq_cst
))
509 write(rpki_sync_socket_rtr
, &rec
, sizeof(struct pfx_record
));
510 if (retval
== -1 && (errno
== EAGAIN
|| errno
== EWOULDBLOCK
))
511 atomic_store_explicit(&rtr_update_overflow
, 1,
512 memory_order_seq_cst
);
514 else if (retval
!= sizeof(struct pfx_record
))
515 RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
518 static void rpki_init_sync_socket(void)
523 RPKI_DEBUG("initializing sync socket");
524 if (socketpair(PF_LOCAL
, SOCK_DGRAM
, 0, fds
) != 0) {
525 msg
= "could not open rpki sync socketpair";
528 rpki_sync_socket_rtr
= fds
[0];
529 rpki_sync_socket_bgpd
= fds
[1];
531 if (set_nonblocking(rpki_sync_socket_rtr
) != 0) {
532 msg
= "could not set rpki_sync_socket_rtr to non blocking";
536 if (set_nonblocking(rpki_sync_socket_bgpd
) != 0) {
537 msg
= "could not set rpki_sync_socket_bgpd to non blocking";
541 thread_add_read(bm
->master
, bgpd_sync_callback
, NULL
,
542 rpki_sync_socket_bgpd
, &t_rpki
);
547 zlog_err("RPKI: %s", msg
);
552 static int bgp_rpki_init(struct thread_master
*master
)
558 cache_list
= list_new();
559 cache_list
->del
= (void (*)(void *)) & free_cache
;
561 polling_period
= POLLING_PERIOD_DEFAULT
;
562 expire_interval
= EXPIRE_INTERVAL_DEFAULT
;
563 retry_interval
= RETRY_INTERVAL_DEFAULT
;
564 install_cli_commands();
565 rpki_init_sync_socket();
569 static int bgp_rpki_fini(void)
572 list_delete(&cache_list
);
574 close(rpki_sync_socket_rtr
);
575 close(rpki_sync_socket_bgpd
);
580 static int bgp_rpki_module_init(void)
582 lrtr_set_alloc_functions(malloc_wrapper
, realloc_wrapper
, free_wrapper
);
584 hook_register(bgp_rpki_prefix_status
, rpki_validate_prefix
);
585 hook_register(frr_late_init
, bgp_rpki_init
);
586 hook_register(frr_early_fini
, &bgp_rpki_fini
);
591 static int start(void)
596 rtr_update_overflow
= 0;
598 if (list_isempty(cache_list
)) {
600 "No caches were found in config. Prefix validation is off.");
603 RPKI_DEBUG("Init rtr_mgr.");
604 int groups_len
= listcount(cache_list
);
605 struct rtr_mgr_group
*groups
= get_groups();
607 RPKI_DEBUG("Polling period: %d", polling_period
);
608 ret
= rtr_mgr_init(&rtr_config
, groups
, groups_len
, polling_period
,
609 expire_interval
, retry_interval
,
610 rpki_update_cb_sync_rtr
, NULL
,
611 rpki_connection_status_cb
, NULL
);
612 if (ret
== RTR_ERROR
) {
613 RPKI_DEBUG("Init rtr_mgr failed.");
617 RPKI_DEBUG("Starting rtr_mgr.");
618 ret
= rtr_mgr_start(rtr_config
);
619 if (ret
== RTR_ERROR
) {
620 RPKI_DEBUG("Starting rtr_mgr failed.");
621 rtr_mgr_free(rtr_config
);
626 XFREE(MTYPE_BGP_RPKI_CACHE_GROUP
, groups
);
631 static void stop(void)
634 if (rtr_is_running
) {
635 rtr_mgr_stop(rtr_config
);
636 rtr_mgr_free(rtr_config
);
641 static int reset(bool force
)
643 if (rtr_is_running
&& !force
)
646 RPKI_DEBUG("Resetting RPKI Session");
651 static struct rtr_mgr_group
*get_connected_group(void)
653 if (!cache_list
|| list_isempty(cache_list
))
656 return rtr_mgr_get_first_group(rtr_config
);
659 static void print_prefix_table_by_asn(struct vty
*vty
, as_t as
)
661 unsigned int number_of_ipv4_prefixes
= 0;
662 unsigned int number_of_ipv6_prefixes
= 0;
663 struct rtr_mgr_group
*group
= get_connected_group();
664 struct rpki_for_each_record_arg arg
;
670 vty_out(vty
, "Cannot find a connected group.\n");
674 struct pfx_table
*pfx_table
= group
->sockets
[0]->pfx_table
;
676 vty_out(vty
, "RPKI/RTR prefix table\n");
677 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
679 arg
.prefix_amount
= &number_of_ipv4_prefixes
;
680 pfx_table_for_each_ipv4_record(pfx_table
, print_record_by_asn
, &arg
);
682 arg
.prefix_amount
= &number_of_ipv6_prefixes
;
683 pfx_table_for_each_ipv6_record(pfx_table
, print_record_by_asn
, &arg
);
685 vty_out(vty
, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes
);
686 vty_out(vty
, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes
);
689 static void print_prefix_table(struct vty
*vty
)
691 struct rpki_for_each_record_arg arg
;
693 unsigned int number_of_ipv4_prefixes
= 0;
694 unsigned int number_of_ipv6_prefixes
= 0;
695 struct rtr_mgr_group
*group
= get_connected_group();
702 struct pfx_table
*pfx_table
= group
->sockets
[0]->pfx_table
;
704 vty_out(vty
, "RPKI/RTR prefix table\n");
705 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
707 arg
.prefix_amount
= &number_of_ipv4_prefixes
;
708 pfx_table_for_each_ipv4_record(pfx_table
, print_record_cb
, &arg
);
710 arg
.prefix_amount
= &number_of_ipv6_prefixes
;
711 pfx_table_for_each_ipv6_record(pfx_table
, print_record_cb
, &arg
);
713 vty_out(vty
, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes
);
714 vty_out(vty
, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes
);
717 static int rpki_validate_prefix(struct peer
*peer
, struct attr
*attr
,
718 const struct prefix
*prefix
)
720 struct assegment
*as_segment
;
722 struct lrtr_ip_addr ip_addr_prefix
;
723 enum pfxv_state result
;
725 if (!is_synchronized())
728 // No aspath means route comes from iBGP
729 if (!attr
->aspath
|| !attr
->aspath
->segments
) {
731 as_number
= peer
->bgp
->as
;
733 as_segment
= attr
->aspath
->segments
;
734 // Find last AsSegment
735 while (as_segment
->next
)
736 as_segment
= as_segment
->next
;
738 if (as_segment
->type
== AS_SEQUENCE
) {
740 as_number
= as_segment
->as
[as_segment
->length
- 1];
741 } else if (as_segment
->type
== AS_CONFED_SEQUENCE
742 || as_segment
->type
== AS_CONFED_SET
) {
744 as_number
= peer
->bgp
->as
;
746 // RFC says: "Take distinguished value NONE as asn"
747 // which means state is unknown
748 return RPKI_NOTFOUND
;
752 // Get the prefix in requested format
753 switch (prefix
->family
) {
755 ip_addr_prefix
.ver
= LRTR_IPV4
;
756 ip_addr_prefix
.u
.addr4
.addr
= ntohl(prefix
->u
.prefix4
.s_addr
);
760 ip_addr_prefix
.ver
= LRTR_IPV6
;
761 ipv6_addr_to_host_byte_order(prefix
->u
.prefix6
.s6_addr32
,
762 ip_addr_prefix
.u
.addr6
.addr
);
769 // Do the actual validation
770 rtr_mgr_validate(rtr_config
, as_number
, &ip_addr_prefix
,
771 prefix
->prefixlen
, &result
);
773 // Print Debug output
775 case BGP_PFXV_STATE_VALID
:
777 "Validating Prefix %pFX from asn %u Result: VALID",
780 case BGP_PFXV_STATE_NOT_FOUND
:
782 "Validating Prefix %pFX from asn %u Result: NOT FOUND",
784 return RPKI_NOTFOUND
;
785 case BGP_PFXV_STATE_INVALID
:
787 "Validating Prefix %pFX from asn %u Result: INVALID",
792 "Validating Prefix %pFX from asn %u Result: CANNOT VALIDATE",
799 static int add_cache(struct cache
*cache
)
801 uint8_t preference
= cache
->preference
;
802 struct rtr_mgr_group group
;
804 group
.preference
= preference
;
805 group
.sockets_len
= 1;
806 group
.sockets
= &cache
->rtr_socket
;
808 if (rtr_is_running
) {
809 init_tr_socket(cache
);
811 if (rtr_mgr_add_group(rtr_config
, &group
) != RTR_SUCCESS
) {
812 free_tr_socket(cache
);
817 listnode_add(cache_list
, cache
);
822 static int add_tcp_cache(const char *host
, const char *port
,
823 const uint8_t preference
, const char *bindaddr
)
825 struct rtr_socket
*rtr_socket
;
826 struct tr_tcp_config
*tcp_config
=
827 XCALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_tcp_config
));
828 struct tr_socket
*tr_socket
=
829 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_socket
));
830 struct cache
*cache
=
831 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct cache
));
833 tcp_config
->host
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, host
);
834 tcp_config
->port
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, port
);
836 tcp_config
->bindaddr
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, bindaddr
);
838 tcp_config
->bindaddr
= NULL
;
840 rtr_socket
= create_rtr_socket(tr_socket
);
843 cache
->tr_socket
= tr_socket
;
844 cache
->tr_config
.tcp_config
= tcp_config
;
845 cache
->rtr_socket
= rtr_socket
;
846 cache
->preference
= preference
;
848 int ret
= add_cache(cache
);
849 if (ret
!= SUCCESS
) {
856 #if defined(FOUND_SSH)
857 static int add_ssh_cache(const char *host
, const unsigned int port
,
858 const char *username
, const char *client_privkey_path
,
859 const char *client_pubkey_path
,
860 const char *server_pubkey_path
,
861 const uint8_t preference
, const char *bindaddr
)
863 struct tr_ssh_config
*ssh_config
=
864 XCALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_ssh_config
));
865 struct cache
*cache
=
866 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct cache
));
867 struct tr_socket
*tr_socket
=
868 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_socket
));
869 struct rtr_socket
*rtr_socket
;
871 ssh_config
->port
= port
;
872 ssh_config
->host
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, host
);
874 ssh_config
->bindaddr
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, bindaddr
);
876 ssh_config
->bindaddr
= NULL
;
878 ssh_config
->username
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, username
);
879 ssh_config
->client_privkey_path
=
880 XSTRDUP(MTYPE_BGP_RPKI_CACHE
, client_privkey_path
);
881 ssh_config
->server_hostkey_path
=
882 XSTRDUP(MTYPE_BGP_RPKI_CACHE
, server_pubkey_path
);
884 rtr_socket
= create_rtr_socket(tr_socket
);
887 cache
->tr_socket
= tr_socket
;
888 cache
->tr_config
.ssh_config
= ssh_config
;
889 cache
->rtr_socket
= rtr_socket
;
890 cache
->preference
= preference
;
892 int ret
= add_cache(cache
);
893 if (ret
!= SUCCESS
) {
901 static void free_cache(struct cache
*cache
)
903 if (cache
->type
== TCP
) {
904 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
->host
);
905 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
->port
);
906 if (cache
->tr_config
.tcp_config
->bindaddr
)
907 XFREE(MTYPE_BGP_RPKI_CACHE
,
908 cache
->tr_config
.tcp_config
->bindaddr
);
909 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
);
911 #if defined(FOUND_SSH)
913 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.ssh_config
->host
);
914 XFREE(MTYPE_BGP_RPKI_CACHE
,
915 cache
->tr_config
.ssh_config
->username
);
916 XFREE(MTYPE_BGP_RPKI_CACHE
,
917 cache
->tr_config
.ssh_config
->client_privkey_path
);
918 XFREE(MTYPE_BGP_RPKI_CACHE
,
919 cache
->tr_config
.ssh_config
->server_hostkey_path
);
920 if (cache
->tr_config
.ssh_config
->bindaddr
)
921 XFREE(MTYPE_BGP_RPKI_CACHE
,
922 cache
->tr_config
.ssh_config
->bindaddr
);
923 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.ssh_config
);
926 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_socket
);
927 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->rtr_socket
);
928 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
);
931 static int config_write(struct vty
*vty
)
933 struct listnode
*cache_node
;
936 if (!listcount(cache_list
))
940 vty_out(vty
, "debug rpki\n");
943 vty_out(vty
, "rpki\n");
944 vty_out(vty
, " rpki polling_period %d\n", polling_period
);
946 if (retry_interval
!= RETRY_INTERVAL_DEFAULT
)
947 vty_out(vty
, " rpki retry_interval %d\n", retry_interval
);
948 if (expire_interval
!= EXPIRE_INTERVAL_DEFAULT
)
949 vty_out(vty
, " rpki expire_interval %d\n", expire_interval
);
951 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
952 switch (cache
->type
) {
953 struct tr_tcp_config
*tcp_config
;
954 #if defined(FOUND_SSH)
955 struct tr_ssh_config
*ssh_config
;
958 tcp_config
= cache
->tr_config
.tcp_config
;
959 vty_out(vty
, " rpki cache %s %s ", tcp_config
->host
,
961 if (tcp_config
->bindaddr
)
962 vty_out(vty
, "source %s ",
963 tcp_config
->bindaddr
);
965 #if defined(FOUND_SSH)
967 ssh_config
= cache
->tr_config
.ssh_config
;
968 vty_out(vty
, " rpki cache %s %u %s %s %s ",
969 ssh_config
->host
, ssh_config
->port
,
970 ssh_config
->username
,
971 ssh_config
->client_privkey_path
,
972 ssh_config
->server_hostkey_path
!= NULL
973 ? ssh_config
->server_hostkey_path
975 if (ssh_config
->bindaddr
)
976 vty_out(vty
, "source %s ",
977 ssh_config
->bindaddr
);
984 vty_out(vty
, "preference %hhu\n", cache
->preference
);
986 vty_out(vty
, "exit\n");
994 "Enable rpki and enter rpki configuration mode\n")
996 vty
->node
= RPKI_NODE
;
1000 DEFUN (bgp_rpki_start
,
1004 "start rpki support\n")
1006 if (listcount(cache_list
) == 0)
1008 "Could not start rpki because no caches are configured\n");
1010 if (!is_running()) {
1011 if (start() == ERROR
) {
1012 RPKI_DEBUG("RPKI failed to start");
1019 DEFUN (bgp_rpki_stop
,
1023 "start rpki support\n")
1031 DEFPY (rpki_polling_period
,
1032 rpki_polling_period_cmd
,
1033 "rpki polling_period (1-86400)$pp",
1035 "Set polling period\n"
1036 "Polling period value\n")
1038 polling_period
= pp
;
1042 DEFUN (no_rpki_polling_period
,
1043 no_rpki_polling_period_cmd
,
1044 "no rpki polling_period",
1047 "Set polling period back to default\n")
1049 polling_period
= POLLING_PERIOD_DEFAULT
;
1053 DEFPY (rpki_expire_interval
,
1054 rpki_expire_interval_cmd
,
1055 "rpki expire_interval (600-172800)$tmp",
1057 "Set expire interval\n"
1058 "Expire interval value\n")
1060 if ((unsigned int)tmp
>= polling_period
) {
1061 expire_interval
= tmp
;
1065 vty_out(vty
, "%% Expiry interval must be polling period or larger\n");
1066 return CMD_WARNING_CONFIG_FAILED
;
1069 DEFUN (no_rpki_expire_interval
,
1070 no_rpki_expire_interval_cmd
,
1071 "no rpki expire_interval",
1074 "Set expire interval back to default\n")
1076 expire_interval
= polling_period
* 2;
1080 DEFPY (rpki_retry_interval
,
1081 rpki_retry_interval_cmd
,
1082 "rpki retry_interval (1-7200)$tmp",
1084 "Set retry interval\n"
1085 "retry interval value\n")
1087 retry_interval
= tmp
;
1091 DEFUN (no_rpki_retry_interval
,
1092 no_rpki_retry_interval_cmd
,
1093 "no rpki retry_interval",
1096 "Set retry interval back to default\n")
1098 retry_interval
= RETRY_INTERVAL_DEFAULT
;
1102 DEFPY(rpki_cache
, rpki_cache_cmd
,
1103 "rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY SSH_PUBKEY [SERVER_PUBKEY]> [source <A.B.C.D>$bindaddr] preference (1-255)",
1105 "Install a cache server to current group\n"
1106 "IP address of cache server\n Hostname of cache server\n"
1110 "Path to own SSH private key\n"
1111 "Path to own SSH public key\n"
1112 "Path to Public key of cache server\n"
1113 "Configure source IP address of RPKI connection\n"
1114 "Define a Source IP Address\n"
1115 "Preference of the cache server\n"
1116 "Preference value\n")
1119 struct listnode
*cache_node
;
1120 struct cache
*current_cache
;
1122 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, current_cache
)) {
1123 if (current_cache
->preference
== preference
) {
1125 "Cache with preference %ld is already configured\n",
1132 // use ssh connection
1134 #if defined(FOUND_SSH)
1135 return_value
= add_ssh_cache(
1136 cache
, sshport
, ssh_uname
, ssh_privkey
, ssh_pubkey
,
1137 server_pubkey
, preference
, bindaddr_str
);
1139 return_value
= SUCCESS
;
1141 "ssh sockets are not supported. Please recompile rtrlib and frr with ssh support. If you want to use it\n");
1143 } else { // use tcp connection
1145 add_tcp_cache(cache
, tcpport
, preference
, bindaddr_str
);
1148 if (return_value
== ERROR
) {
1149 vty_out(vty
, "Could not create new rpki cache\n");
1156 DEFPY (no_rpki_cache
,
1158 "no rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport> preference (1-255)$preference",
1161 "Remove a cache server\n"
1162 "IP address of cache server\n Hostname of cache server\n"
1165 "Preference of the cache server\n"
1166 "Preference value\n")
1168 struct cache
*cache_p
= find_cache(preference
);
1171 vty_out(vty
, "Could not find cache %ld\n", preference
);
1175 if (rtr_is_running
&& listcount(cache_list
) == 1) {
1177 } else if (rtr_is_running
) {
1178 if (rtr_mgr_remove_group(rtr_config
, preference
) == RTR_ERROR
) {
1179 vty_out(vty
, "Could not remove cache %ld", preference
);
1186 listnode_delete(cache_list
, cache_p
);
1187 free_cache(cache_p
);
1192 DEFUN (show_rpki_prefix_table
,
1193 show_rpki_prefix_table_cmd
,
1194 "show rpki prefix-table",
1197 "Show validated prefixes which were received from RPKI Cache\n")
1199 struct listnode
*cache_node
;
1200 struct cache
*cache
;
1202 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1203 vty_out(vty
, "host: %s port: %s\n",
1204 cache
->tr_config
.tcp_config
->host
,
1205 cache
->tr_config
.tcp_config
->port
);
1207 if (is_synchronized())
1208 print_prefix_table(vty
);
1210 vty_out(vty
, "No connection to RPKI cache server.\n");
1215 DEFPY (show_rpki_as_number
, show_rpki_as_number_cmd
,
1216 "show rpki as-number (1-4294967295)$by_asn",
1217 SHOW_STR RPKI_OUTPUT_STRING
1218 "Lookup by ASN in prefix table\n"
1221 if (!is_synchronized()) {
1222 vty_out(vty
, "No Connection to RPKI cache server.\n");
1226 print_prefix_table_by_asn(vty
, by_asn
);
1230 DEFPY (show_rpki_prefix
,
1231 show_rpki_prefix_cmd
,
1232 "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn]",
1235 "Lookup IP prefix and optionally ASN in prefix table\n"
1241 if (!is_synchronized()) {
1242 vty_out(vty
, "No Connection to RPKI cache server.\n");
1246 struct lrtr_ip_addr addr
;
1247 char addr_str
[INET6_ADDRSTRLEN
];
1248 size_t addr_len
= strchr(prefix_str
, '/') - prefix_str
;
1250 memset(addr_str
, 0, sizeof(addr_str
));
1251 memcpy(addr_str
, prefix_str
, addr_len
);
1253 if (lrtr_ip_str_to_addr(addr_str
, &addr
) != 0) {
1254 vty_out(vty
, "Invalid IP prefix\n");
1258 struct pfx_record
*matches
= NULL
;
1259 unsigned int match_count
= 0;
1260 enum pfxv_state result
;
1262 if (pfx_table_validate_r(rtr_config
->pfx_table
, &matches
, &match_count
,
1263 asn
, &addr
, prefix
->prefixlen
, &result
)
1265 vty_out(vty
, "Prefix lookup failed");
1269 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
1270 for (size_t i
= 0; i
< match_count
; ++i
) {
1271 const struct pfx_record
*record
= &matches
[i
];
1273 if (record
->max_len
>= prefix
->prefixlen
1274 && ((asn
!= 0 && (uint32_t)asn
== record
->asn
)
1276 print_record(&matches
[i
], vty
);
1283 DEFUN (show_rpki_cache_server
,
1284 show_rpki_cache_server_cmd
,
1285 "show rpki cache-server",
1288 "SHOW configured cache server\n")
1290 struct listnode
*cache_node
;
1291 struct cache
*cache
;
1293 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1294 if (cache
->type
== TCP
) {
1295 vty_out(vty
, "host: %s port: %s\n",
1296 cache
->tr_config
.tcp_config
->host
,
1297 cache
->tr_config
.tcp_config
->port
);
1299 #if defined(FOUND_SSH)
1300 } else if (cache
->type
== SSH
) {
1302 "host: %s port: %d username: %s server_hostkey_path: %s client_privkey_path: %s\n",
1303 cache
->tr_config
.ssh_config
->host
,
1304 cache
->tr_config
.ssh_config
->port
,
1305 cache
->tr_config
.ssh_config
->username
,
1306 cache
->tr_config
.ssh_config
1307 ->server_hostkey_path
,
1308 cache
->tr_config
.ssh_config
1309 ->client_privkey_path
);
1317 DEFUN (show_rpki_cache_connection
,
1318 show_rpki_cache_connection_cmd
,
1319 "show rpki cache-connection",
1322 "Show to which RPKI Cache Servers we have a connection\n")
1324 if (!is_synchronized()) {
1325 vty_out(vty
, "No connection to RPKI cache server.\n");
1330 struct listnode
*cache_node
;
1331 struct cache
*cache
;
1332 struct rtr_mgr_group
*group
= get_connected_group();
1335 vty_out(vty
, "Cannot find a connected group.\n");
1338 vty_out(vty
, "Connected to group %d\n", group
->preference
);
1339 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1340 if (cache
->preference
== group
->preference
) {
1341 struct tr_tcp_config
*tcp_config
;
1342 #if defined(FOUND_SSH)
1343 struct tr_ssh_config
*ssh_config
;
1346 switch (cache
->type
) {
1348 tcp_config
= cache
->tr_config
.tcp_config
;
1349 vty_out(vty
, "rpki tcp cache %s %s pref %hhu\n",
1350 tcp_config
->host
, tcp_config
->port
,
1354 #if defined(FOUND_SSH)
1356 ssh_config
= cache
->tr_config
.ssh_config
;
1357 vty_out(vty
, "rpki ssh cache %s %u pref %hhu\n",
1358 ssh_config
->host
, ssh_config
->port
,
1372 static int config_on_exit(struct vty
*vty
)
1384 return reset(true) == SUCCESS
? CMD_SUCCESS
: CMD_WARNING
;
1391 "Enable debugging for rpki\n")
1397 DEFUN (no_debug_rpki
,
1402 "Disable debugging for rpki\n")
1408 DEFUN_YANG (match_rpki
,
1410 "match rpki <valid|invalid|notfound>",
1415 "Prefix not found\n")
1418 "./match-condition[condition='frr-bgp-route-map:rpki']";
1419 char xpath_value
[XPATH_MAXLEN
];
1421 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
1422 snprintf(xpath_value
, sizeof(xpath_value
),
1423 "%s/rmap-match-condition/frr-bgp-route-map:rpki", xpath
);
1424 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, argv
[2]->arg
);
1426 return nb_cli_apply_changes(vty
, NULL
);
1429 DEFUN_YANG (no_match_rpki
,
1431 "no match rpki <valid|invalid|notfound>",
1437 "Prefix not found\n")
1440 "./match-condition[condition='frr-bgp-route-map:rpki']";
1442 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
1443 return nb_cli_apply_changes(vty
, NULL
);
1446 static void install_cli_commands(void)
1448 // TODO: make config write work
1449 install_node(&rpki_node
);
1450 install_default(RPKI_NODE
);
1451 install_element(CONFIG_NODE
, &rpki_cmd
);
1452 install_element(ENABLE_NODE
, &rpki_cmd
);
1454 install_element(ENABLE_NODE
, &bgp_rpki_start_cmd
);
1455 install_element(ENABLE_NODE
, &bgp_rpki_stop_cmd
);
1457 /* Install rpki reset command */
1458 install_element(RPKI_NODE
, &rpki_reset_cmd
);
1460 /* Install rpki polling period commands */
1461 install_element(RPKI_NODE
, &rpki_polling_period_cmd
);
1462 install_element(RPKI_NODE
, &no_rpki_polling_period_cmd
);
1464 /* Install rpki expire interval commands */
1465 install_element(RPKI_NODE
, &rpki_expire_interval_cmd
);
1466 install_element(RPKI_NODE
, &no_rpki_expire_interval_cmd
);
1468 /* Install rpki retry interval commands */
1469 install_element(RPKI_NODE
, &rpki_retry_interval_cmd
);
1470 install_element(RPKI_NODE
, &no_rpki_retry_interval_cmd
);
1472 /* Install rpki cache commands */
1473 install_element(RPKI_NODE
, &rpki_cache_cmd
);
1474 install_element(RPKI_NODE
, &no_rpki_cache_cmd
);
1476 /* Install show commands */
1477 install_element(VIEW_NODE
, &show_rpki_prefix_table_cmd
);
1478 install_element(VIEW_NODE
, &show_rpki_cache_connection_cmd
);
1479 install_element(VIEW_NODE
, &show_rpki_cache_server_cmd
);
1480 install_element(VIEW_NODE
, &show_rpki_prefix_cmd
);
1481 install_element(VIEW_NODE
, &show_rpki_as_number_cmd
);
1483 /* Install debug commands */
1484 install_element(CONFIG_NODE
, &debug_rpki_cmd
);
1485 install_element(ENABLE_NODE
, &debug_rpki_cmd
);
1486 install_element(CONFIG_NODE
, &no_debug_rpki_cmd
);
1487 install_element(ENABLE_NODE
, &no_debug_rpki_cmd
);
1489 /* Install route match */
1490 route_map_install_match(&route_match_rpki_cmd
);
1491 install_element(RMAP_NODE
, &match_rpki_cmd
);
1492 install_element(RMAP_NODE
, &no_match_rpki_cmd
);
1495 FRR_MODULE_SETUP(.name
= "bgpd_rpki", .version
= "0.3.6",
1496 .description
= "Enable RPKI support for FRR.",
1497 .init
= bgp_rpki_module_init
,