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 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_CACHE
, "BGP RPKI Cache server");
67 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_CACHE_GROUP
, "BGP RPKI Cache server group");
68 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_RTRLIB
, "BGP RPKI RTRLib");
70 #define POLLING_PERIOD_DEFAULT 3600
71 #define EXPIRE_INTERVAL_DEFAULT 7200
72 #define RETRY_INTERVAL_DEFAULT 600
73 #define BGP_RPKI_CACHE_SERVER_SYNC_RETRY_TIMEOUT 3
75 static struct thread
*t_rpki_sync
;
77 #define RPKI_DEBUG(...) \
79 zlog_debug("RPKI: " __VA_ARGS__); \
82 #define RPKI_OUTPUT_STRING "Control rpki specific settings\n"
85 enum { TCP
, SSH
} type
;
86 struct tr_socket
*tr_socket
;
88 struct tr_tcp_config
*tcp_config
;
89 struct tr_ssh_config
*ssh_config
;
91 struct rtr_socket
*rtr_socket
;
95 enum return_values
{ SUCCESS
= 0, ERROR
= -1 };
97 struct rpki_for_each_record_arg
{
99 unsigned int *prefix_amount
;
103 static int start(void);
104 static void stop(void);
105 static int reset(bool force
);
106 static struct rtr_mgr_group
*get_connected_group(void);
107 static void print_prefix_table(struct vty
*vty
);
108 static void install_cli_commands(void);
109 static int config_write(struct vty
*vty
);
110 static int config_on_exit(struct vty
*vty
);
111 static void free_cache(struct cache
*cache
);
112 static struct rtr_mgr_group
*get_groups(void);
113 #if defined(FOUND_SSH)
114 static int add_ssh_cache(const char *host
, const unsigned int port
,
115 const char *username
, const char *client_privkey_path
,
116 const char *client_pubkey_path
,
117 const char *server_pubkey_path
,
118 const uint8_t preference
, const char *bindaddr
);
120 static struct rtr_socket
*create_rtr_socket(struct tr_socket
*tr_socket
);
121 static struct cache
*find_cache(const uint8_t preference
);
122 static int add_tcp_cache(const char *host
, const char *port
,
123 const uint8_t preference
, const char *bindaddr
);
124 static void print_record(const struct pfx_record
*record
, struct vty
*vty
);
125 static bool is_synchronized(void);
126 static bool is_running(void);
127 static bool is_stopping(void);
128 static void route_match_free(void *rule
);
129 static enum route_map_cmd_result_t
route_match(void *rule
,
130 const struct prefix
*prefix
,
133 static void *route_match_compile(const char *arg
);
134 static void revalidate_bgp_node(struct bgp_dest
*dest
, afi_t afi
, safi_t safi
);
135 static void revalidate_all_routes(void);
137 static struct rtr_mgr_config
*rtr_config
;
138 static struct list
*cache_list
;
139 static bool rtr_is_running
;
140 static bool rtr_is_stopping
;
141 static bool rtr_is_synced
;
142 static _Atomic
int rtr_update_overflow
;
143 static bool rpki_debug
;
144 static unsigned int polling_period
;
145 static unsigned int expire_interval
;
146 static unsigned int retry_interval
;
147 static int rpki_sync_socket_rtr
;
148 static int rpki_sync_socket_bgpd
;
150 static struct cmd_node rpki_node
= {
153 .parent_node
= CONFIG_NODE
,
154 .prompt
= "%s(config-rpki)# ",
155 .config_write
= config_write
,
156 .node_exit
= config_on_exit
,
158 static const struct route_map_rule_cmd route_match_rpki_cmd
= {
159 "rpki", route_match
, route_match_compile
, route_match_free
};
161 static void *malloc_wrapper(size_t size
)
163 return XMALLOC(MTYPE_BGP_RPKI_RTRLIB
, size
);
166 static void *realloc_wrapper(void *ptr
, size_t size
)
168 return XREALLOC(MTYPE_BGP_RPKI_RTRLIB
, ptr
, size
);
171 static void free_wrapper(void *ptr
)
173 XFREE(MTYPE_BGP_RPKI_RTRLIB
, ptr
);
176 static void init_tr_socket(struct cache
*cache
)
178 if (cache
->type
== TCP
)
179 tr_tcp_init(cache
->tr_config
.tcp_config
,
181 #if defined(FOUND_SSH)
183 tr_ssh_init(cache
->tr_config
.ssh_config
,
188 static void free_tr_socket(struct cache
*cache
)
190 if (cache
->type
== TCP
)
191 tr_tcp_init(cache
->tr_config
.tcp_config
,
193 #if defined(FOUND_SSH)
195 tr_ssh_init(cache
->tr_config
.ssh_config
,
200 static int rpki_validate_prefix(struct peer
*peer
, struct attr
*attr
,
201 const struct prefix
*prefix
);
203 static void ipv6_addr_to_network_byte_order(const uint32_t *src
, uint32_t *dest
)
207 for (i
= 0; i
< 4; i
++)
208 dest
[i
] = htonl(src
[i
]);
211 static void ipv6_addr_to_host_byte_order(const uint32_t *src
, uint32_t *dest
)
215 for (i
= 0; i
< 4; i
++)
216 dest
[i
] = ntohl(src
[i
]);
219 static enum route_map_cmd_result_t
route_match(void *rule
,
220 const struct prefix
*prefix
,
223 int *rpki_status
= rule
;
224 struct bgp_path_info
*path
;
228 if (rpki_validate_prefix(path
->peer
, path
->attr
, prefix
)
236 static void *route_match_compile(const char *arg
)
240 rpki_status
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(int));
242 if (strcmp(arg
, "valid") == 0)
243 *rpki_status
= RPKI_VALID
;
244 else if (strcmp(arg
, "invalid") == 0)
245 *rpki_status
= RPKI_INVALID
;
247 *rpki_status
= RPKI_NOTFOUND
;
252 static void route_match_free(void *rule
)
254 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
257 static struct rtr_socket
*create_rtr_socket(struct tr_socket
*tr_socket
)
259 struct rtr_socket
*rtr_socket
=
260 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct rtr_socket
));
261 rtr_socket
->tr_socket
= tr_socket
;
265 static struct cache
*find_cache(const uint8_t preference
)
267 struct listnode
*cache_node
;
270 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
271 if (cache
->preference
== preference
)
277 static void print_record(const struct pfx_record
*record
, struct vty
*vty
)
279 char ip
[INET6_ADDRSTRLEN
];
281 lrtr_ip_addr_to_str(&record
->prefix
, ip
, sizeof(ip
));
282 vty_out(vty
, "%-40s %3u - %3u %10u\n", ip
, record
->min_len
,
283 record
->max_len
, record
->asn
);
286 static void print_record_by_asn(const struct pfx_record
*record
, void *data
)
288 struct rpki_for_each_record_arg
*arg
= data
;
289 struct vty
*vty
= arg
->vty
;
291 if (record
->asn
== arg
->as
) {
292 (*arg
->prefix_amount
)++;
293 print_record(record
, vty
);
297 static void print_record_cb(const struct pfx_record
*record
, void *data
)
299 struct rpki_for_each_record_arg
*arg
= data
;
300 struct vty
*vty
= arg
->vty
;
302 (*arg
->prefix_amount
)++;
304 print_record(record
, vty
);
307 static struct rtr_mgr_group
*get_groups(void)
309 struct listnode
*cache_node
;
310 struct rtr_mgr_group
*rtr_mgr_groups
;
313 int group_count
= listcount(cache_list
);
315 if (group_count
== 0)
318 rtr_mgr_groups
= XMALLOC(MTYPE_BGP_RPKI_CACHE_GROUP
,
319 group_count
* sizeof(struct rtr_mgr_group
));
323 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
324 rtr_mgr_groups
[i
].sockets
= &cache
->rtr_socket
;
325 rtr_mgr_groups
[i
].sockets_len
= 1;
326 rtr_mgr_groups
[i
].preference
= cache
->preference
;
328 init_tr_socket(cache
);
333 return rtr_mgr_groups
;
336 inline bool is_synchronized(void)
338 return rtr_is_synced
;
341 inline bool is_running(void)
343 return rtr_is_running
;
346 inline bool is_stopping(void)
348 return rtr_is_stopping
;
351 static struct prefix
*pfx_record_to_prefix(struct pfx_record
*record
)
353 struct prefix
*prefix
= prefix_new();
355 prefix
->prefixlen
= record
->min_len
;
357 if (record
->prefix
.ver
== LRTR_IPV4
) {
358 prefix
->family
= AF_INET
;
359 prefix
->u
.prefix4
.s_addr
= htonl(record
->prefix
.u
.addr4
.addr
);
361 prefix
->family
= AF_INET6
;
362 ipv6_addr_to_network_byte_order(record
->prefix
.u
.addr6
.addr
,
363 prefix
->u
.prefix6
.s6_addr32
);
369 static void bgpd_sync_callback(struct thread
*thread
)
372 struct listnode
*node
;
373 struct prefix
*prefix
;
374 struct pfx_record rec
;
376 thread_add_read(bm
->master
, bgpd_sync_callback
, NULL
,
377 rpki_sync_socket_bgpd
, NULL
);
379 if (atomic_load_explicit(&rtr_update_overflow
, memory_order_seq_cst
)) {
380 while (read(rpki_sync_socket_bgpd
, &rec
,
381 sizeof(struct pfx_record
)) != -1)
384 atomic_store_explicit(&rtr_update_overflow
, 0,
385 memory_order_seq_cst
);
386 revalidate_all_routes();
391 read(rpki_sync_socket_bgpd
, &rec
, sizeof(struct pfx_record
));
392 if (retval
!= sizeof(struct pfx_record
)) {
393 RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd");
396 prefix
= pfx_record_to_prefix(&rec
);
398 afi_t afi
= (rec
.prefix
.ver
== LRTR_IPV4
) ? AFI_IP
: AFI_IP6
;
400 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
403 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
404 if (!bgp
->rib
[afi
][safi
])
407 struct bgp_dest
*match
;
408 struct bgp_dest
*node
;
410 match
= bgp_table_subtree_lookup(bgp
->rib
[afi
][safi
],
415 if (bgp_dest_has_bgp_path_info_data(node
)) {
416 revalidate_bgp_node(node
, afi
, safi
);
419 node
= bgp_route_next_until(node
, match
);
424 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
;
454 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
456 struct listnode
*peer_listnode
;
458 for (ALL_LIST_ELEMENTS_RO(bgp
->peer
, peer_listnode
, peer
)) {
460 for (size_t i
= 0; i
< 2; i
++) {
462 afi_t afi
= (i
== 0) ? AFI_IP
: AFI_IP6
;
464 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
;
466 if (!peer
->bgp
->rib
[afi
][safi
])
469 bgp_soft_reconfig_in(peer
, afi
, safi
);
476 static void rpki_update_cb_sync_rtr(struct pfx_table
*p
__attribute__((unused
)),
477 const struct pfx_record rec
,
478 const bool added
__attribute__((unused
)))
481 atomic_load_explicit(&rtr_update_overflow
, memory_order_seq_cst
))
485 write(rpki_sync_socket_rtr
, &rec
, sizeof(struct pfx_record
));
486 if (retval
== -1 && (errno
== EAGAIN
|| errno
== EWOULDBLOCK
))
487 atomic_store_explicit(&rtr_update_overflow
, 1,
488 memory_order_seq_cst
);
490 else if (retval
!= sizeof(struct pfx_record
))
491 RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
494 static void rpki_init_sync_socket(void)
499 RPKI_DEBUG("initializing sync socket");
500 if (socketpair(PF_LOCAL
, SOCK_DGRAM
, 0, fds
) != 0) {
501 msg
= "could not open rpki sync socketpair";
504 rpki_sync_socket_rtr
= fds
[0];
505 rpki_sync_socket_bgpd
= fds
[1];
507 if (set_nonblocking(rpki_sync_socket_rtr
) != 0) {
508 msg
= "could not set rpki_sync_socket_rtr to non blocking";
512 if (set_nonblocking(rpki_sync_socket_bgpd
) != 0) {
513 msg
= "could not set rpki_sync_socket_bgpd to non blocking";
518 thread_add_read(bm
->master
, bgpd_sync_callback
, NULL
,
519 rpki_sync_socket_bgpd
, NULL
);
524 zlog_err("RPKI: %s", msg
);
529 static int bgp_rpki_init(struct thread_master
*master
)
532 rtr_is_running
= false;
533 rtr_is_stopping
= false;
534 rtr_is_synced
= false;
536 cache_list
= list_new();
537 cache_list
->del
= (void (*)(void *)) & free_cache
;
539 polling_period
= POLLING_PERIOD_DEFAULT
;
540 expire_interval
= EXPIRE_INTERVAL_DEFAULT
;
541 retry_interval
= RETRY_INTERVAL_DEFAULT
;
542 install_cli_commands();
543 rpki_init_sync_socket();
547 static int bgp_rpki_fini(void)
550 list_delete(&cache_list
);
552 close(rpki_sync_socket_rtr
);
553 close(rpki_sync_socket_bgpd
);
558 static int bgp_rpki_module_init(void)
560 lrtr_set_alloc_functions(malloc_wrapper
, realloc_wrapper
, free_wrapper
);
562 hook_register(bgp_rpki_prefix_status
, rpki_validate_prefix
);
563 hook_register(frr_late_init
, bgp_rpki_init
);
564 hook_register(frr_early_fini
, &bgp_rpki_fini
);
569 static void sync_expired(struct thread
*thread
)
571 if (!rtr_mgr_conf_in_sync(rtr_config
)) {
572 RPKI_DEBUG("rtr_mgr is not synced, retrying.");
573 thread_add_timer(bm
->master
, sync_expired
, NULL
,
574 BGP_RPKI_CACHE_SERVER_SYNC_RETRY_TIMEOUT
,
579 RPKI_DEBUG("rtr_mgr sync is done.");
581 rtr_is_synced
= true;
584 static int start(void)
588 rtr_is_stopping
= false;
589 rtr_is_synced
= false;
590 rtr_update_overflow
= 0;
592 if (list_isempty(cache_list
)) {
594 "No caches were found in config. Prefix validation is off.");
597 RPKI_DEBUG("Init rtr_mgr.");
598 int groups_len
= listcount(cache_list
);
599 struct rtr_mgr_group
*groups
= get_groups();
601 RPKI_DEBUG("Polling period: %d", polling_period
);
602 ret
= rtr_mgr_init(&rtr_config
, groups
, groups_len
, polling_period
,
603 expire_interval
, retry_interval
,
604 rpki_update_cb_sync_rtr
, NULL
, NULL
, NULL
);
605 if (ret
== RTR_ERROR
) {
606 RPKI_DEBUG("Init rtr_mgr failed.");
610 RPKI_DEBUG("Starting rtr_mgr.");
611 ret
= rtr_mgr_start(rtr_config
);
612 if (ret
== RTR_ERROR
) {
613 RPKI_DEBUG("Starting rtr_mgr failed.");
614 rtr_mgr_free(rtr_config
);
618 thread_add_timer(bm
->master
, sync_expired
, NULL
, 0, &t_rpki_sync
);
620 XFREE(MTYPE_BGP_RPKI_CACHE_GROUP
, groups
);
622 rtr_is_running
= true;
627 static void stop(void)
629 rtr_is_stopping
= true;
631 THREAD_OFF(t_rpki_sync
);
632 rtr_mgr_stop(rtr_config
);
633 rtr_mgr_free(rtr_config
);
634 rtr_is_running
= false;
638 static int reset(bool force
)
640 if (is_running() && !force
)
643 RPKI_DEBUG("Resetting RPKI Session");
648 static struct rtr_mgr_group
*get_connected_group(void)
650 if (!cache_list
|| list_isempty(cache_list
))
653 return rtr_mgr_get_first_group(rtr_config
);
656 static void print_prefix_table_by_asn(struct vty
*vty
, as_t as
)
658 unsigned int number_of_ipv4_prefixes
= 0;
659 unsigned int number_of_ipv6_prefixes
= 0;
660 struct rtr_mgr_group
*group
= get_connected_group();
661 struct rpki_for_each_record_arg arg
;
667 vty_out(vty
, "Cannot find a connected group.\n");
671 struct pfx_table
*pfx_table
= group
->sockets
[0]->pfx_table
;
673 vty_out(vty
, "RPKI/RTR prefix table\n");
674 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
676 arg
.prefix_amount
= &number_of_ipv4_prefixes
;
677 pfx_table_for_each_ipv4_record(pfx_table
, print_record_by_asn
, &arg
);
679 arg
.prefix_amount
= &number_of_ipv6_prefixes
;
680 pfx_table_for_each_ipv6_record(pfx_table
, print_record_by_asn
, &arg
);
682 vty_out(vty
, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes
);
683 vty_out(vty
, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes
);
686 static void print_prefix_table(struct vty
*vty
)
688 struct rpki_for_each_record_arg arg
;
690 unsigned int number_of_ipv4_prefixes
= 0;
691 unsigned int number_of_ipv6_prefixes
= 0;
692 struct rtr_mgr_group
*group
= get_connected_group();
699 struct pfx_table
*pfx_table
= group
->sockets
[0]->pfx_table
;
701 vty_out(vty
, "RPKI/RTR prefix table\n");
702 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
704 arg
.prefix_amount
= &number_of_ipv4_prefixes
;
705 pfx_table_for_each_ipv4_record(pfx_table
, print_record_cb
, &arg
);
707 arg
.prefix_amount
= &number_of_ipv6_prefixes
;
708 pfx_table_for_each_ipv6_record(pfx_table
, print_record_cb
, &arg
);
710 vty_out(vty
, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes
);
711 vty_out(vty
, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes
);
714 static int rpki_validate_prefix(struct peer
*peer
, struct attr
*attr
,
715 const struct prefix
*prefix
)
717 struct assegment
*as_segment
;
719 struct lrtr_ip_addr ip_addr_prefix
;
720 enum pfxv_state result
;
722 if (!is_synchronized())
723 return RPKI_NOT_BEING_USED
;
725 // No aspath means route comes from iBGP
726 if (!attr
->aspath
|| !attr
->aspath
->segments
) {
728 as_number
= peer
->bgp
->as
;
730 as_segment
= attr
->aspath
->segments
;
731 // Find last AsSegment
732 while (as_segment
->next
)
733 as_segment
= as_segment
->next
;
735 if (as_segment
->type
== AS_SEQUENCE
) {
737 as_number
= as_segment
->as
[as_segment
->length
- 1];
738 } else if (as_segment
->type
== AS_CONFED_SEQUENCE
739 || as_segment
->type
== AS_CONFED_SET
) {
741 as_number
= peer
->bgp
->as
;
743 // RFC says: "Take distinguished value NONE as asn"
744 // which means state is unknown
745 return RPKI_NOTFOUND
;
749 // Get the prefix in requested format
750 switch (prefix
->family
) {
752 ip_addr_prefix
.ver
= LRTR_IPV4
;
753 ip_addr_prefix
.u
.addr4
.addr
= ntohl(prefix
->u
.prefix4
.s_addr
);
757 ip_addr_prefix
.ver
= LRTR_IPV6
;
758 ipv6_addr_to_host_byte_order(prefix
->u
.prefix6
.s6_addr32
,
759 ip_addr_prefix
.u
.addr6
.addr
);
763 return RPKI_NOT_BEING_USED
;
766 // Do the actual validation
767 rtr_mgr_validate(rtr_config
, as_number
, &ip_addr_prefix
,
768 prefix
->prefixlen
, &result
);
770 // Print Debug output
772 case BGP_PFXV_STATE_VALID
:
774 "Validating Prefix %pFX from asn %u Result: VALID",
777 case BGP_PFXV_STATE_NOT_FOUND
:
779 "Validating Prefix %pFX from asn %u Result: NOT FOUND",
781 return RPKI_NOTFOUND
;
782 case BGP_PFXV_STATE_INVALID
:
784 "Validating Prefix %pFX from asn %u Result: INVALID",
789 "Validating Prefix %pFX from asn %u Result: CANNOT VALIDATE",
793 return RPKI_NOT_BEING_USED
;
796 static int add_cache(struct cache
*cache
)
798 uint8_t preference
= cache
->preference
;
799 struct rtr_mgr_group group
;
801 group
.preference
= preference
;
802 group
.sockets_len
= 1;
803 group
.sockets
= &cache
->rtr_socket
;
806 init_tr_socket(cache
);
808 if (rtr_mgr_add_group(rtr_config
, &group
) != RTR_SUCCESS
) {
809 free_tr_socket(cache
);
814 listnode_add(cache_list
, cache
);
819 static int add_tcp_cache(const char *host
, const char *port
,
820 const uint8_t preference
, const char *bindaddr
)
822 struct rtr_socket
*rtr_socket
;
823 struct tr_tcp_config
*tcp_config
=
824 XCALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_tcp_config
));
825 struct tr_socket
*tr_socket
=
826 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_socket
));
827 struct cache
*cache
=
828 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct cache
));
830 tcp_config
->host
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, host
);
831 tcp_config
->port
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, port
);
833 tcp_config
->bindaddr
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, bindaddr
);
835 tcp_config
->bindaddr
= NULL
;
837 rtr_socket
= create_rtr_socket(tr_socket
);
840 cache
->tr_socket
= tr_socket
;
841 cache
->tr_config
.tcp_config
= tcp_config
;
842 cache
->rtr_socket
= rtr_socket
;
843 cache
->preference
= preference
;
845 int ret
= add_cache(cache
);
846 if (ret
!= SUCCESS
) {
853 #if defined(FOUND_SSH)
854 static int add_ssh_cache(const char *host
, const unsigned int port
,
855 const char *username
, const char *client_privkey_path
,
856 const char *client_pubkey_path
,
857 const char *server_pubkey_path
,
858 const uint8_t preference
, const char *bindaddr
)
860 struct tr_ssh_config
*ssh_config
=
861 XCALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_ssh_config
));
862 struct cache
*cache
=
863 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct cache
));
864 struct tr_socket
*tr_socket
=
865 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_socket
));
866 struct rtr_socket
*rtr_socket
;
868 ssh_config
->port
= port
;
869 ssh_config
->host
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, host
);
871 ssh_config
->bindaddr
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, bindaddr
);
873 ssh_config
->bindaddr
= NULL
;
875 ssh_config
->username
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, username
);
876 ssh_config
->client_privkey_path
=
877 XSTRDUP(MTYPE_BGP_RPKI_CACHE
, client_privkey_path
);
878 ssh_config
->server_hostkey_path
=
879 XSTRDUP(MTYPE_BGP_RPKI_CACHE
, server_pubkey_path
);
881 rtr_socket
= create_rtr_socket(tr_socket
);
884 cache
->tr_socket
= tr_socket
;
885 cache
->tr_config
.ssh_config
= ssh_config
;
886 cache
->rtr_socket
= rtr_socket
;
887 cache
->preference
= preference
;
889 int ret
= add_cache(cache
);
890 if (ret
!= SUCCESS
) {
898 static void free_cache(struct cache
*cache
)
900 if (cache
->type
== TCP
) {
901 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
->host
);
902 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
->port
);
903 XFREE(MTYPE_BGP_RPKI_CACHE
,
904 cache
->tr_config
.tcp_config
->bindaddr
);
905 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
);
907 #if defined(FOUND_SSH)
909 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.ssh_config
->host
);
910 XFREE(MTYPE_BGP_RPKI_CACHE
,
911 cache
->tr_config
.ssh_config
->username
);
912 XFREE(MTYPE_BGP_RPKI_CACHE
,
913 cache
->tr_config
.ssh_config
->client_privkey_path
);
914 XFREE(MTYPE_BGP_RPKI_CACHE
,
915 cache
->tr_config
.ssh_config
->server_hostkey_path
);
916 XFREE(MTYPE_BGP_RPKI_CACHE
,
917 cache
->tr_config
.ssh_config
->bindaddr
);
918 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.ssh_config
);
921 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_socket
);
922 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->rtr_socket
);
923 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
);
926 static int config_write(struct vty
*vty
)
928 struct listnode
*cache_node
;
931 if (!listcount(cache_list
))
935 vty_out(vty
, "debug rpki\n");
938 vty_out(vty
, "rpki\n");
939 vty_out(vty
, " rpki polling_period %d\n", polling_period
);
941 if (retry_interval
!= RETRY_INTERVAL_DEFAULT
)
942 vty_out(vty
, " rpki retry_interval %d\n", retry_interval
);
943 if (expire_interval
!= EXPIRE_INTERVAL_DEFAULT
)
944 vty_out(vty
, " rpki expire_interval %d\n", expire_interval
);
946 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
947 switch (cache
->type
) {
948 struct tr_tcp_config
*tcp_config
;
949 #if defined(FOUND_SSH)
950 struct tr_ssh_config
*ssh_config
;
953 tcp_config
= cache
->tr_config
.tcp_config
;
954 vty_out(vty
, " rpki cache %s %s ", tcp_config
->host
,
956 if (tcp_config
->bindaddr
)
957 vty_out(vty
, "source %s ",
958 tcp_config
->bindaddr
);
960 #if defined(FOUND_SSH)
962 ssh_config
= cache
->tr_config
.ssh_config
;
963 vty_out(vty
, " rpki cache %s %u %s %s %s ",
964 ssh_config
->host
, ssh_config
->port
,
965 ssh_config
->username
,
966 ssh_config
->client_privkey_path
,
967 ssh_config
->server_hostkey_path
!= NULL
968 ? ssh_config
->server_hostkey_path
970 if (ssh_config
->bindaddr
)
971 vty_out(vty
, "source %s ",
972 ssh_config
->bindaddr
);
979 vty_out(vty
, "preference %hhu\n", cache
->preference
);
981 vty_out(vty
, "exit\n");
989 "Enable rpki and enter rpki configuration mode\n")
991 vty
->node
= RPKI_NODE
;
995 DEFUN (bgp_rpki_start
,
999 "start rpki support\n")
1001 if (listcount(cache_list
) == 0)
1003 "Could not start rpki because no caches are configured\n");
1005 if (!is_running()) {
1006 if (start() == ERROR
) {
1007 RPKI_DEBUG("RPKI failed to start");
1014 DEFUN (bgp_rpki_stop
,
1018 "start rpki support\n")
1026 DEFPY (rpki_polling_period
,
1027 rpki_polling_period_cmd
,
1028 "rpki polling_period (1-86400)$pp",
1030 "Set polling period\n"
1031 "Polling period value\n")
1033 polling_period
= pp
;
1037 DEFUN (no_rpki_polling_period
,
1038 no_rpki_polling_period_cmd
,
1039 "no rpki polling_period [(1-86400)]",
1042 "Set polling period back to default\n"
1043 "Polling period value\n")
1045 polling_period
= POLLING_PERIOD_DEFAULT
;
1049 DEFPY (rpki_expire_interval
,
1050 rpki_expire_interval_cmd
,
1051 "rpki expire_interval (600-172800)$tmp",
1053 "Set expire interval\n"
1054 "Expire interval value\n")
1056 if ((unsigned int)tmp
>= polling_period
) {
1057 expire_interval
= tmp
;
1061 vty_out(vty
, "%% Expiry interval must be polling period or larger\n");
1062 return CMD_WARNING_CONFIG_FAILED
;
1065 DEFUN (no_rpki_expire_interval
,
1066 no_rpki_expire_interval_cmd
,
1067 "no rpki expire_interval [(600-172800)]",
1070 "Set expire interval back to default\n"
1071 "Expire interval value\n")
1073 expire_interval
= polling_period
* 2;
1077 DEFPY (rpki_retry_interval
,
1078 rpki_retry_interval_cmd
,
1079 "rpki retry_interval (1-7200)$tmp",
1081 "Set retry interval\n"
1082 "retry interval value\n")
1084 retry_interval
= tmp
;
1088 DEFUN (no_rpki_retry_interval
,
1089 no_rpki_retry_interval_cmd
,
1090 "no rpki retry_interval [(1-7200)]",
1093 "Set retry interval back to default\n"
1094 "retry interval value\n")
1096 retry_interval
= RETRY_INTERVAL_DEFAULT
;
1100 DEFPY(rpki_cache
, rpki_cache_cmd
,
1101 "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)",
1103 "Install a cache server to current group\n"
1104 "IP address of cache server\n Hostname of cache server\n"
1108 "Path to own SSH private key\n"
1109 "Path to own SSH public key\n"
1110 "Path to Public key of cache server\n"
1111 "Configure source IP address of RPKI connection\n"
1112 "Define a Source IP Address\n"
1113 "Preference of the cache server\n"
1114 "Preference value\n")
1117 struct listnode
*cache_node
;
1118 struct cache
*current_cache
;
1120 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, current_cache
)) {
1121 if (current_cache
->preference
== preference
) {
1123 "Cache with preference %ld is already configured\n",
1130 // use ssh connection
1132 #if defined(FOUND_SSH)
1133 return_value
= add_ssh_cache(
1134 cache
, sshport
, ssh_uname
, ssh_privkey
, ssh_pubkey
,
1135 server_pubkey
, preference
, bindaddr_str
);
1137 return_value
= SUCCESS
;
1139 "ssh sockets are not supported. Please recompile rtrlib and frr with ssh support. If you want to use it\n");
1141 } else { // use tcp connection
1143 add_tcp_cache(cache
, tcpport
, preference
, bindaddr_str
);
1146 if (return_value
== ERROR
) {
1147 vty_out(vty
, "Could not create new rpki cache\n");
1154 DEFPY (no_rpki_cache
,
1156 "no rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport> preference (1-255)$preference",
1159 "Remove a cache server\n"
1160 "IP address of cache server\n Hostname of cache server\n"
1163 "Preference of the cache server\n"
1164 "Preference value\n")
1166 struct cache
*cache_p
= find_cache(preference
);
1169 vty_out(vty
, "Could not find cache %ld\n", preference
);
1173 if (is_running() && listcount(cache_list
) == 1) {
1175 } else if (is_running()) {
1176 if (rtr_mgr_remove_group(rtr_config
, preference
) == RTR_ERROR
) {
1177 vty_out(vty
, "Could not remove cache %ld", preference
);
1184 listnode_delete(cache_list
, cache_p
);
1185 free_cache(cache_p
);
1190 DEFUN (show_rpki_prefix_table
,
1191 show_rpki_prefix_table_cmd
,
1192 "show rpki prefix-table",
1195 "Show validated prefixes which were received from RPKI Cache\n")
1197 struct listnode
*cache_node
;
1198 struct cache
*cache
;
1200 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1201 vty_out(vty
, "host: %s port: %s\n",
1202 cache
->tr_config
.tcp_config
->host
,
1203 cache
->tr_config
.tcp_config
->port
);
1205 if (is_synchronized())
1206 print_prefix_table(vty
);
1208 vty_out(vty
, "No connection to RPKI cache server.\n");
1213 DEFPY (show_rpki_as_number
, show_rpki_as_number_cmd
,
1214 "show rpki as-number (1-4294967295)$by_asn",
1215 SHOW_STR RPKI_OUTPUT_STRING
1216 "Lookup by ASN in prefix table\n"
1219 if (!is_synchronized()) {
1220 vty_out(vty
, "No Connection to RPKI cache server.\n");
1224 print_prefix_table_by_asn(vty
, by_asn
);
1228 DEFPY (show_rpki_prefix
,
1229 show_rpki_prefix_cmd
,
1230 "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn]",
1233 "Lookup IP prefix and optionally ASN in prefix table\n"
1239 if (!is_synchronized()) {
1240 vty_out(vty
, "No Connection to RPKI cache server.\n");
1244 struct lrtr_ip_addr addr
;
1245 char addr_str
[INET6_ADDRSTRLEN
];
1246 size_t addr_len
= strchr(prefix_str
, '/') - prefix_str
;
1248 memset(addr_str
, 0, sizeof(addr_str
));
1249 memcpy(addr_str
, prefix_str
, addr_len
);
1251 if (lrtr_ip_str_to_addr(addr_str
, &addr
) != 0) {
1252 vty_out(vty
, "Invalid IP prefix\n");
1256 struct pfx_record
*matches
= NULL
;
1257 unsigned int match_count
= 0;
1258 enum pfxv_state result
;
1260 if (pfx_table_validate_r(rtr_config
->pfx_table
, &matches
, &match_count
,
1261 asn
, &addr
, prefix
->prefixlen
, &result
)
1263 vty_out(vty
, "Prefix lookup failed\n");
1267 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
1268 for (size_t i
= 0; i
< match_count
; ++i
) {
1269 const struct pfx_record
*record
= &matches
[i
];
1271 if (record
->max_len
>= prefix
->prefixlen
1272 && ((asn
!= 0 && (uint32_t)asn
== record
->asn
)
1274 print_record(&matches
[i
], vty
);
1281 DEFPY (show_rpki_cache_server
,
1282 show_rpki_cache_server_cmd
,
1283 "show rpki cache-server [json$uj]",
1286 "Show configured cache server\n"
1289 struct json_object
*json
= NULL
;
1290 struct json_object
*json_server
= NULL
;
1291 struct json_object
*json_servers
= NULL
;
1292 struct listnode
*cache_node
;
1293 struct cache
*cache
;
1296 json
= json_object_new_object();
1297 json_servers
= json_object_new_array();
1298 json_object_object_add(json
, "servers", json_servers
);
1301 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1302 if (cache
->type
== TCP
) {
1304 vty_out(vty
, "host: %s port: %s\n",
1305 cache
->tr_config
.tcp_config
->host
,
1306 cache
->tr_config
.tcp_config
->port
);
1308 json_server
= json_object_new_object();
1309 json_object_string_add(json_server
, "mode",
1311 json_object_string_add(
1312 json_server
, "host",
1313 cache
->tr_config
.tcp_config
->host
);
1314 json_object_string_add(
1315 json_server
, "port",
1316 cache
->tr_config
.tcp_config
->port
);
1317 json_object_array_add(json_servers
,
1321 #if defined(FOUND_SSH)
1322 } else if (cache
->type
== SSH
) {
1325 "host: %s port: %d username: %s server_hostkey_path: %s client_privkey_path: %s\n",
1326 cache
->tr_config
.ssh_config
->host
,
1327 cache
->tr_config
.ssh_config
->port
,
1328 cache
->tr_config
.ssh_config
->username
,
1329 cache
->tr_config
.ssh_config
1330 ->server_hostkey_path
,
1331 cache
->tr_config
.ssh_config
1332 ->client_privkey_path
);
1334 json_server
= json_object_new_object();
1335 json_object_string_add(json_server
, "mode",
1337 json_object_string_add(
1338 json_server
, "host",
1339 cache
->tr_config
.ssh_config
->host
);
1340 json_object_int_add(
1341 json_server
, "port",
1342 cache
->tr_config
.ssh_config
->port
);
1343 json_object_string_add(
1344 json_server
, "username",
1345 cache
->tr_config
.ssh_config
->username
);
1346 json_object_string_add(
1347 json_server
, "serverHostkeyPath",
1348 cache
->tr_config
.ssh_config
1349 ->server_hostkey_path
);
1350 json_object_string_add(
1351 json_server
, "clientPrivkeyPath",
1352 cache
->tr_config
.ssh_config
1353 ->client_privkey_path
);
1354 json_object_array_add(json_servers
,
1362 vty_json(vty
, json
);
1367 DEFPY (show_rpki_cache_connection
,
1368 show_rpki_cache_connection_cmd
,
1369 "show rpki cache-connection [json$uj]",
1372 "Show to which RPKI Cache Servers we have a connection\n"
1375 struct json_object
*json
= NULL
;
1376 struct json_object
*json_conn
= NULL
;
1377 struct json_object
*json_conns
= NULL
;
1378 struct listnode
*cache_node
;
1379 struct cache
*cache
;
1380 struct rtr_mgr_group
*group
;
1383 json
= json_object_new_object();
1385 if (!is_synchronized()) {
1387 vty_out(vty
, "No connection to RPKI cache server.\n");
1389 vty_json(vty
, json
);
1394 group
= get_connected_group();
1397 vty_out(vty
, "Cannot find a connected group.\n");
1399 vty_json(vty
, json
);
1405 vty_out(vty
, "Connected to group %d\n", group
->preference
);
1407 json_conns
= json_object_new_array();
1408 json_object_int_add(json
, "connectedGroup", group
->preference
);
1409 json_object_object_add(json
, "connections", json_conns
);
1412 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1413 struct tr_tcp_config
*tcp_config
;
1414 #if defined(FOUND_SSH)
1415 struct tr_ssh_config
*ssh_config
;
1417 switch (cache
->type
) {
1419 tcp_config
= cache
->tr_config
.tcp_config
;
1423 "rpki tcp cache %s %s pref %hhu%s\n",
1424 tcp_config
->host
, tcp_config
->port
,
1426 cache
->rtr_socket
->state
==
1431 json_conn
= json_object_new_object();
1432 json_object_string_add(json_conn
, "mode",
1434 json_object_string_add(json_conn
, "host",
1436 json_object_string_add(json_conn
, "port",
1438 json_object_int_add(json_conn
, "preference",
1440 json_object_string_add(
1442 cache
->rtr_socket
->state
==
1446 json_object_array_add(json_conns
, json_conn
);
1449 #if defined(FOUND_SSH)
1451 ssh_config
= cache
->tr_config
.ssh_config
;
1455 "rpki ssh cache %s %u pref %hhu%s\n",
1456 ssh_config
->host
, ssh_config
->port
,
1458 cache
->rtr_socket
->state
==
1463 json_conn
= json_object_new_object();
1464 json_object_string_add(json_conn
, "mode",
1466 json_object_string_add(json_conn
, "host",
1468 json_object_int_add(json_conn
, "port",
1470 json_object_int_add(json_conn
, "preference",
1472 json_object_string_add(
1474 cache
->rtr_socket
->state
==
1478 json_object_array_add(json_conns
, json_conn
);
1488 vty_json(vty
, json
);
1493 static int config_on_exit(struct vty
*vty
)
1505 return reset(true) == SUCCESS
? CMD_SUCCESS
: CMD_WARNING
;
1512 "Enable debugging for rpki\n")
1518 DEFUN (no_debug_rpki
,
1523 "Disable debugging for rpki\n")
1529 DEFUN_YANG (match_rpki
,
1531 "match rpki <valid|invalid|notfound>",
1536 "Prefix not found\n")
1539 "./match-condition[condition='frr-bgp-route-map:rpki']";
1540 char xpath_value
[XPATH_MAXLEN
];
1542 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
1543 snprintf(xpath_value
, sizeof(xpath_value
),
1544 "%s/rmap-match-condition/frr-bgp-route-map:rpki", xpath
);
1545 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, argv
[2]->arg
);
1547 return nb_cli_apply_changes(vty
, NULL
);
1550 DEFUN_YANG (no_match_rpki
,
1552 "no match rpki <valid|invalid|notfound>",
1558 "Prefix not found\n")
1561 "./match-condition[condition='frr-bgp-route-map:rpki']";
1563 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
1564 return nb_cli_apply_changes(vty
, NULL
);
1567 static void install_cli_commands(void)
1569 // TODO: make config write work
1570 install_node(&rpki_node
);
1571 install_default(RPKI_NODE
);
1572 install_element(CONFIG_NODE
, &rpki_cmd
);
1573 install_element(ENABLE_NODE
, &rpki_cmd
);
1575 install_element(ENABLE_NODE
, &bgp_rpki_start_cmd
);
1576 install_element(ENABLE_NODE
, &bgp_rpki_stop_cmd
);
1578 /* Install rpki reset command */
1579 install_element(ENABLE_NODE
, &rpki_reset_cmd
);
1580 install_element(RPKI_NODE
, &rpki_reset_cmd
);
1582 /* Install rpki polling period commands */
1583 install_element(RPKI_NODE
, &rpki_polling_period_cmd
);
1584 install_element(RPKI_NODE
, &no_rpki_polling_period_cmd
);
1586 /* Install rpki expire interval commands */
1587 install_element(RPKI_NODE
, &rpki_expire_interval_cmd
);
1588 install_element(RPKI_NODE
, &no_rpki_expire_interval_cmd
);
1590 /* Install rpki retry interval commands */
1591 install_element(RPKI_NODE
, &rpki_retry_interval_cmd
);
1592 install_element(RPKI_NODE
, &no_rpki_retry_interval_cmd
);
1594 /* Install rpki cache commands */
1595 install_element(RPKI_NODE
, &rpki_cache_cmd
);
1596 install_element(RPKI_NODE
, &no_rpki_cache_cmd
);
1598 /* Install show commands */
1599 install_element(VIEW_NODE
, &show_rpki_prefix_table_cmd
);
1600 install_element(VIEW_NODE
, &show_rpki_cache_connection_cmd
);
1601 install_element(VIEW_NODE
, &show_rpki_cache_server_cmd
);
1602 install_element(VIEW_NODE
, &show_rpki_prefix_cmd
);
1603 install_element(VIEW_NODE
, &show_rpki_as_number_cmd
);
1605 /* Install debug commands */
1606 install_element(CONFIG_NODE
, &debug_rpki_cmd
);
1607 install_element(ENABLE_NODE
, &debug_rpki_cmd
);
1608 install_element(CONFIG_NODE
, &no_debug_rpki_cmd
);
1609 install_element(ENABLE_NODE
, &no_debug_rpki_cmd
);
1611 /* Install route match */
1612 route_map_install_match(&route_match_rpki_cmd
);
1613 install_element(RMAP_NODE
, &match_rpki_cmd
);
1614 install_element(RMAP_NODE
, &no_match_rpki_cmd
);
1617 FRR_MODULE_SETUP(.name
= "bgpd_rpki", .version
= "0.3.6",
1618 .description
= "Enable RPKI support for FRR.",
1619 .init
= bgp_rpki_module_init
,