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 #include "rtrlib/rtrlib.h"
58 #include "lib/version.h"
60 #include "bgpd/bgp_rpki_clippy.c"
62 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_CACHE
, "BGP RPKI Cache server");
63 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_CACHE_GROUP
, "BGP RPKI Cache server group");
64 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_RTRLIB
, "BGP RPKI RTRLib");
65 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_REVALIDATE
, "BGP RPKI Revalidation");
67 #define POLLING_PERIOD_DEFAULT 3600
68 #define EXPIRE_INTERVAL_DEFAULT 7200
69 #define RETRY_INTERVAL_DEFAULT 600
70 #define BGP_RPKI_CACHE_SERVER_SYNC_RETRY_TIMEOUT 3
72 static struct thread
*t_rpki_sync
;
74 #define RPKI_DEBUG(...) \
76 zlog_debug("RPKI: " __VA_ARGS__); \
79 #define RPKI_OUTPUT_STRING "Control rpki specific settings\n"
82 enum { TCP
, SSH
} type
;
83 struct tr_socket
*tr_socket
;
85 struct tr_tcp_config
*tcp_config
;
86 struct tr_ssh_config
*ssh_config
;
88 struct rtr_socket
*rtr_socket
;
92 enum return_values
{ SUCCESS
= 0, ERROR
= -1 };
94 struct rpki_for_each_record_arg
{
96 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
, json_object
*json
);
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 *server_pubkey_path
,
115 const uint8_t preference
, const char *bindaddr
);
117 static struct rtr_socket
*create_rtr_socket(struct tr_socket
*tr_socket
);
118 static struct cache
*find_cache(const uint8_t preference
);
119 static void rpki_delete_all_cache_nodes(void);
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
,
124 static bool is_synchronized(void);
125 static bool is_running(void);
126 static bool is_stopping(void);
127 static void route_match_free(void *rule
);
128 static enum route_map_cmd_result_t
route_match(void *rule
,
129 const struct prefix
*prefix
,
132 static void *route_match_compile(const char *arg
);
133 static void revalidate_bgp_node(struct bgp_dest
*dest
, afi_t afi
, safi_t safi
);
134 static void revalidate_all_routes(void);
136 static struct rtr_mgr_config
*rtr_config
;
137 static struct list
*cache_list
;
138 static bool rtr_is_running
;
139 static bool rtr_is_stopping
;
140 static bool rtr_is_synced
;
141 static _Atomic
int rtr_update_overflow
;
142 static bool rpki_debug
;
143 static unsigned int polling_period
;
144 static unsigned int expire_interval
;
145 static unsigned int retry_interval
;
146 static int rpki_sync_socket_rtr
;
147 static int rpki_sync_socket_bgpd
;
149 static struct cmd_node rpki_node
= {
152 .parent_node
= CONFIG_NODE
,
153 .prompt
= "%s(config-rpki)# ",
154 .config_write
= config_write
,
155 .node_exit
= config_on_exit
,
157 static const struct route_map_rule_cmd route_match_rpki_cmd
= {
158 "rpki", route_match
, route_match_compile
, route_match_free
};
160 static void *malloc_wrapper(size_t size
)
162 return XMALLOC(MTYPE_BGP_RPKI_RTRLIB
, size
);
165 static void *realloc_wrapper(void *ptr
, size_t size
)
167 return XREALLOC(MTYPE_BGP_RPKI_RTRLIB
, ptr
, size
);
170 static void free_wrapper(void *ptr
)
172 XFREE(MTYPE_BGP_RPKI_RTRLIB
, ptr
);
175 static void init_tr_socket(struct cache
*cache
)
177 if (cache
->type
== TCP
)
178 tr_tcp_init(cache
->tr_config
.tcp_config
,
180 #if defined(FOUND_SSH)
182 tr_ssh_init(cache
->tr_config
.ssh_config
,
187 static void free_tr_socket(struct cache
*cache
)
189 if (cache
->type
== TCP
)
190 tr_tcp_init(cache
->tr_config
.tcp_config
,
192 #if defined(FOUND_SSH)
194 tr_ssh_init(cache
->tr_config
.ssh_config
,
199 static int rpki_validate_prefix(struct peer
*peer
, struct attr
*attr
,
200 const struct prefix
*prefix
);
202 static void ipv6_addr_to_network_byte_order(const uint32_t *src
, uint32_t *dest
)
206 for (i
= 0; i
< 4; i
++)
207 dest
[i
] = htonl(src
[i
]);
210 static void ipv6_addr_to_host_byte_order(const uint32_t *src
, uint32_t *dest
)
214 for (i
= 0; i
< 4; i
++)
215 dest
[i
] = ntohl(src
[i
]);
218 static enum route_map_cmd_result_t
route_match(void *rule
,
219 const struct prefix
*prefix
,
222 int *rpki_status
= rule
;
223 struct bgp_path_info
*path
;
227 if (rpki_validate_prefix(path
->peer
, path
->attr
, prefix
)
235 static void *route_match_compile(const char *arg
)
239 rpki_status
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(int));
241 if (strcmp(arg
, "valid") == 0)
242 *rpki_status
= RPKI_VALID
;
243 else if (strcmp(arg
, "invalid") == 0)
244 *rpki_status
= RPKI_INVALID
;
246 *rpki_status
= RPKI_NOTFOUND
;
251 static void route_match_free(void *rule
)
253 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
256 static struct rtr_socket
*create_rtr_socket(struct tr_socket
*tr_socket
)
258 struct rtr_socket
*rtr_socket
=
259 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct rtr_socket
));
260 rtr_socket
->tr_socket
= tr_socket
;
264 static struct cache
*find_cache(const uint8_t preference
)
266 struct listnode
*cache_node
;
269 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
270 if (cache
->preference
== preference
)
276 static void rpki_delete_all_cache_nodes(void)
278 struct listnode
*cache_node
, *cache_next
;
281 for (ALL_LIST_ELEMENTS(cache_list
, cache_node
, cache_next
, cache
)) {
282 rtr_mgr_remove_group(rtr_config
, cache
->preference
);
283 listnode_delete(cache_list
, cache
);
287 static void print_record(const struct pfx_record
*record
, struct vty
*vty
,
290 char ip
[INET6_ADDRSTRLEN
];
291 json_object
*json_record
= NULL
;
293 lrtr_ip_addr_to_str(&record
->prefix
, ip
, sizeof(ip
));
296 vty_out(vty
, "%-40s %3u - %3u %10u\n", ip
, record
->min_len
,
297 record
->max_len
, record
->asn
);
299 json_record
= json_object_new_object();
300 json_object_string_add(json_record
, "prefix", ip
);
301 json_object_int_add(json_record
, "prefixLenMin",
303 json_object_int_add(json_record
, "prefixLenMax",
305 json_object_int_add(json_record
, "asn", record
->asn
);
306 json_object_array_add(json
, json_record
);
310 static void print_record_by_asn(const struct pfx_record
*record
, void *data
)
312 struct rpki_for_each_record_arg
*arg
= data
;
313 struct vty
*vty
= arg
->vty
;
315 if (record
->asn
== arg
->as
) {
316 (*arg
->prefix_amount
)++;
317 print_record(record
, vty
, arg
->json
);
321 static void print_record_cb(const struct pfx_record
*record
, void *data
)
323 struct rpki_for_each_record_arg
*arg
= data
;
324 struct vty
*vty
= arg
->vty
;
326 (*arg
->prefix_amount
)++;
328 print_record(record
, vty
, arg
->json
);
331 static struct rtr_mgr_group
*get_groups(void)
333 struct listnode
*cache_node
;
334 struct rtr_mgr_group
*rtr_mgr_groups
;
337 int group_count
= listcount(cache_list
);
339 if (group_count
== 0)
342 rtr_mgr_groups
= XMALLOC(MTYPE_BGP_RPKI_CACHE_GROUP
,
343 group_count
* sizeof(struct rtr_mgr_group
));
347 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
348 rtr_mgr_groups
[i
].sockets
= &cache
->rtr_socket
;
349 rtr_mgr_groups
[i
].sockets_len
= 1;
350 rtr_mgr_groups
[i
].preference
= cache
->preference
;
352 init_tr_socket(cache
);
357 return rtr_mgr_groups
;
360 inline bool is_synchronized(void)
362 return rtr_is_synced
;
365 inline bool is_running(void)
367 return rtr_is_running
;
370 inline bool is_stopping(void)
372 return rtr_is_stopping
;
375 static void pfx_record_to_prefix(struct pfx_record
*record
,
376 struct prefix
*prefix
)
378 prefix
->prefixlen
= record
->min_len
;
380 if (record
->prefix
.ver
== LRTR_IPV4
) {
381 prefix
->family
= AF_INET
;
382 prefix
->u
.prefix4
.s_addr
= htonl(record
->prefix
.u
.addr4
.addr
);
384 prefix
->family
= AF_INET6
;
385 ipv6_addr_to_network_byte_order(record
->prefix
.u
.addr6
.addr
,
386 prefix
->u
.prefix6
.s6_addr32
);
390 struct rpki_revalidate_prefix
{
392 struct prefix prefix
;
397 static void rpki_revalidate_prefix(struct thread
*thread
)
399 struct rpki_revalidate_prefix
*rrp
= THREAD_ARG(thread
);
400 struct bgp_dest
*match
, *node
;
402 match
= bgp_table_subtree_lookup(rrp
->bgp
->rib
[rrp
->afi
][rrp
->safi
],
408 if (bgp_dest_has_bgp_path_info_data(node
)) {
409 revalidate_bgp_node(node
, rrp
->afi
, rrp
->safi
);
412 node
= bgp_route_next_until(node
, match
);
415 XFREE(MTYPE_BGP_RPKI_REVALIDATE
, rrp
);
418 static void bgpd_sync_callback(struct thread
*thread
)
421 struct listnode
*node
;
422 struct prefix prefix
;
423 struct pfx_record rec
;
425 thread_add_read(bm
->master
, bgpd_sync_callback
, NULL
,
426 rpki_sync_socket_bgpd
, NULL
);
428 if (atomic_load_explicit(&rtr_update_overflow
, memory_order_seq_cst
)) {
429 while (read(rpki_sync_socket_bgpd
, &rec
,
430 sizeof(struct pfx_record
)) != -1)
433 atomic_store_explicit(&rtr_update_overflow
, 0,
434 memory_order_seq_cst
);
435 revalidate_all_routes();
440 read(rpki_sync_socket_bgpd
, &rec
, sizeof(struct pfx_record
));
441 if (retval
!= sizeof(struct pfx_record
)) {
442 RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd");
445 pfx_record_to_prefix(&rec
, &prefix
);
447 afi_t afi
= (rec
.prefix
.ver
== LRTR_IPV4
) ? AFI_IP
: AFI_IP6
;
449 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
452 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
453 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
454 struct rpki_revalidate_prefix
*rrp
;
459 rrp
= XCALLOC(MTYPE_BGP_RPKI_REVALIDATE
, sizeof(*rrp
));
461 rrp
->prefix
= prefix
;
464 thread_add_event(bm
->master
, rpki_revalidate_prefix
,
465 rrp
, 0, &bgp
->t_revalidate
[afi
][safi
]);
470 static void revalidate_bgp_node(struct bgp_dest
*bgp_dest
, afi_t afi
,
473 struct bgp_adj_in
*ain
;
475 for (ain
= bgp_dest
->adj_in
; ain
; ain
= ain
->next
) {
476 struct bgp_path_info
*path
=
477 bgp_dest_get_bgp_path_info(bgp_dest
);
478 mpls_label_t
*label
= NULL
;
479 uint32_t num_labels
= 0;
481 if (path
&& path
->extra
) {
482 label
= path
->extra
->label
;
483 num_labels
= path
->extra
->num_labels
;
485 (void)bgp_update(ain
->peer
, bgp_dest_get_prefix(bgp_dest
),
486 ain
->addpath_rx_id
, ain
->attr
, afi
, safi
,
487 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
, label
,
488 num_labels
, 1, NULL
);
493 * The act of a soft reconfig in revalidation is really expensive
494 * coupled with the fact that the download of a full rpki state
495 * from a rpki server can be expensive, let's break up the revalidation
496 * to a point in time in the future to allow other bgp events
499 struct rpki_revalidate_peer
{
505 static void bgp_rpki_revalidate_peer(struct thread
*thread
)
507 struct rpki_revalidate_peer
*rvp
= THREAD_ARG(thread
);
510 * Here's the expensive bit of gnomish deviousness
512 bgp_soft_reconfig_in(rvp
->peer
, rvp
->afi
, rvp
->safi
);
514 XFREE(MTYPE_BGP_RPKI_REVALIDATE
, rvp
);
517 static void revalidate_all_routes(void)
520 struct listnode
*node
;
522 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
524 struct listnode
*peer_listnode
;
526 for (ALL_LIST_ELEMENTS_RO(bgp
->peer
, peer_listnode
, peer
)) {
530 FOREACH_AFI_SAFI (afi
, safi
) {
531 struct rpki_revalidate_peer
*rvp
;
533 if (!bgp
->rib
[afi
][safi
])
536 if (!peer_established(peer
))
539 rvp
= XCALLOC(MTYPE_BGP_RPKI_REVALIDATE
,
546 bm
->master
, bgp_rpki_revalidate_peer
,
548 &peer
->t_revalidate_all
[afi
][safi
]);
554 static void rpki_update_cb_sync_rtr(struct pfx_table
*p
__attribute__((unused
)),
555 const struct pfx_record rec
,
556 const bool added
__attribute__((unused
)))
559 atomic_load_explicit(&rtr_update_overflow
, memory_order_seq_cst
))
563 write(rpki_sync_socket_rtr
, &rec
, sizeof(struct pfx_record
));
564 if (retval
== -1 && (errno
== EAGAIN
|| errno
== EWOULDBLOCK
))
565 atomic_store_explicit(&rtr_update_overflow
, 1,
566 memory_order_seq_cst
);
568 else if (retval
!= sizeof(struct pfx_record
))
569 RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
572 static void rpki_init_sync_socket(void)
577 RPKI_DEBUG("initializing sync socket");
578 if (socketpair(PF_LOCAL
, SOCK_DGRAM
, 0, fds
) != 0) {
579 msg
= "could not open rpki sync socketpair";
582 rpki_sync_socket_rtr
= fds
[0];
583 rpki_sync_socket_bgpd
= fds
[1];
585 if (set_nonblocking(rpki_sync_socket_rtr
) != 0) {
586 msg
= "could not set rpki_sync_socket_rtr to non blocking";
590 if (set_nonblocking(rpki_sync_socket_bgpd
) != 0) {
591 msg
= "could not set rpki_sync_socket_bgpd to non blocking";
596 thread_add_read(bm
->master
, bgpd_sync_callback
, NULL
,
597 rpki_sync_socket_bgpd
, NULL
);
602 zlog_err("RPKI: %s", msg
);
607 static int bgp_rpki_init(struct thread_master
*master
)
610 rtr_is_running
= false;
611 rtr_is_stopping
= false;
612 rtr_is_synced
= false;
614 cache_list
= list_new();
615 cache_list
->del
= (void (*)(void *)) & free_cache
;
617 polling_period
= POLLING_PERIOD_DEFAULT
;
618 expire_interval
= EXPIRE_INTERVAL_DEFAULT
;
619 retry_interval
= RETRY_INTERVAL_DEFAULT
;
620 install_cli_commands();
621 rpki_init_sync_socket();
625 static int bgp_rpki_fini(void)
628 list_delete(&cache_list
);
630 close(rpki_sync_socket_rtr
);
631 close(rpki_sync_socket_bgpd
);
636 static int bgp_rpki_module_init(void)
638 lrtr_set_alloc_functions(malloc_wrapper
, realloc_wrapper
, free_wrapper
);
640 hook_register(bgp_rpki_prefix_status
, rpki_validate_prefix
);
641 hook_register(frr_late_init
, bgp_rpki_init
);
642 hook_register(frr_early_fini
, bgp_rpki_fini
);
647 static void sync_expired(struct thread
*thread
)
649 if (!rtr_mgr_conf_in_sync(rtr_config
)) {
650 RPKI_DEBUG("rtr_mgr is not synced, retrying.");
651 thread_add_timer(bm
->master
, sync_expired
, NULL
,
652 BGP_RPKI_CACHE_SERVER_SYNC_RETRY_TIMEOUT
,
657 RPKI_DEBUG("rtr_mgr sync is done.");
659 rtr_is_synced
= true;
662 static int start(void)
666 rtr_is_stopping
= false;
667 rtr_is_synced
= false;
668 rtr_update_overflow
= 0;
670 if (list_isempty(cache_list
)) {
672 "No caches were found in config. Prefix validation is off.");
675 RPKI_DEBUG("Init rtr_mgr.");
676 int groups_len
= listcount(cache_list
);
677 struct rtr_mgr_group
*groups
= get_groups();
679 RPKI_DEBUG("Polling period: %d", polling_period
);
680 ret
= rtr_mgr_init(&rtr_config
, groups
, groups_len
, polling_period
,
681 expire_interval
, retry_interval
,
682 rpki_update_cb_sync_rtr
, NULL
, NULL
, NULL
);
683 if (ret
== RTR_ERROR
) {
684 RPKI_DEBUG("Init rtr_mgr failed.");
688 RPKI_DEBUG("Starting rtr_mgr.");
689 ret
= rtr_mgr_start(rtr_config
);
690 if (ret
== RTR_ERROR
) {
691 RPKI_DEBUG("Starting rtr_mgr failed.");
692 rtr_mgr_free(rtr_config
);
696 thread_add_timer(bm
->master
, sync_expired
, NULL
, 0, &t_rpki_sync
);
698 XFREE(MTYPE_BGP_RPKI_CACHE_GROUP
, groups
);
700 rtr_is_running
= true;
705 static void stop(void)
707 rtr_is_stopping
= true;
709 THREAD_OFF(t_rpki_sync
);
710 rtr_mgr_stop(rtr_config
);
711 rtr_mgr_free(rtr_config
);
712 rtr_is_running
= false;
716 static int reset(bool force
)
718 if (is_running() && !force
)
721 RPKI_DEBUG("Resetting RPKI Session");
726 static struct rtr_mgr_group
*get_connected_group(void)
728 if (!cache_list
|| list_isempty(cache_list
))
731 return rtr_mgr_get_first_group(rtr_config
);
734 static void print_prefix_table_by_asn(struct vty
*vty
, as_t as
,
737 unsigned int number_of_ipv4_prefixes
= 0;
738 unsigned int number_of_ipv6_prefixes
= 0;
739 struct rtr_mgr_group
*group
= get_connected_group();
740 struct rpki_for_each_record_arg arg
;
741 json_object
*json_records
= NULL
;
749 vty_out(vty
, "Cannot find a connected group.\n");
753 struct pfx_table
*pfx_table
= group
->sockets
[0]->pfx_table
;
756 vty_out(vty
, "RPKI/RTR prefix table\n");
757 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length",
760 json_records
= json_object_new_array();
761 json_object_object_add(json
, "prefixes", json_records
);
762 arg
.json
= json_records
;
765 arg
.prefix_amount
= &number_of_ipv4_prefixes
;
766 pfx_table_for_each_ipv4_record(pfx_table
, print_record_by_asn
, &arg
);
768 arg
.prefix_amount
= &number_of_ipv6_prefixes
;
769 pfx_table_for_each_ipv6_record(pfx_table
, print_record_by_asn
, &arg
);
772 vty_out(vty
, "Number of IPv4 Prefixes: %u\n",
773 number_of_ipv4_prefixes
);
774 vty_out(vty
, "Number of IPv6 Prefixes: %u\n",
775 number_of_ipv6_prefixes
);
777 json_object_int_add(json
, "ipv4PrefixCount",
778 number_of_ipv4_prefixes
);
779 json_object_int_add(json
, "ipv6PrefixCount",
780 number_of_ipv6_prefixes
);
787 static void print_prefix_table(struct vty
*vty
, json_object
*json
)
789 struct rpki_for_each_record_arg arg
;
791 unsigned int number_of_ipv4_prefixes
= 0;
792 unsigned int number_of_ipv6_prefixes
= 0;
793 struct rtr_mgr_group
*group
= get_connected_group();
794 json_object
*json_records
= NULL
;
801 vty_out(vty
, "Cannot find a connected group.\n");
805 struct pfx_table
*pfx_table
= group
->sockets
[0]->pfx_table
;
808 vty_out(vty
, "RPKI/RTR prefix table\n");
809 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length",
812 json_records
= json_object_new_array();
813 json_object_object_add(json
, "prefixes", json_records
);
814 arg
.json
= json_records
;
817 arg
.prefix_amount
= &number_of_ipv4_prefixes
;
818 pfx_table_for_each_ipv4_record(pfx_table
, print_record_cb
, &arg
);
820 arg
.prefix_amount
= &number_of_ipv6_prefixes
;
821 pfx_table_for_each_ipv6_record(pfx_table
, print_record_cb
, &arg
);
824 vty_out(vty
, "Number of IPv4 Prefixes: %u\n",
825 number_of_ipv4_prefixes
);
826 vty_out(vty
, "Number of IPv6 Prefixes: %u\n",
827 number_of_ipv6_prefixes
);
829 json_object_int_add(json
, "ipv4PrefixCount",
830 number_of_ipv4_prefixes
);
831 json_object_int_add(json
, "ipv6PrefixCount",
832 number_of_ipv6_prefixes
);
839 static int rpki_validate_prefix(struct peer
*peer
, struct attr
*attr
,
840 const struct prefix
*prefix
)
842 struct assegment
*as_segment
;
844 struct lrtr_ip_addr ip_addr_prefix
;
845 enum pfxv_state result
;
847 if (!is_synchronized())
848 return RPKI_NOT_BEING_USED
;
850 // No aspath means route comes from iBGP
851 if (!attr
->aspath
|| !attr
->aspath
->segments
) {
853 as_number
= peer
->bgp
->as
;
855 as_segment
= attr
->aspath
->segments
;
856 // Find last AsSegment
857 while (as_segment
->next
)
858 as_segment
= as_segment
->next
;
860 if (as_segment
->type
== AS_SEQUENCE
) {
862 as_number
= as_segment
->as
[as_segment
->length
- 1];
863 } else if (as_segment
->type
== AS_CONFED_SEQUENCE
864 || as_segment
->type
== AS_CONFED_SET
) {
866 as_number
= peer
->bgp
->as
;
868 // RFC says: "Take distinguished value NONE as asn"
869 // which means state is unknown
870 return RPKI_NOTFOUND
;
874 // Get the prefix in requested format
875 switch (prefix
->family
) {
877 ip_addr_prefix
.ver
= LRTR_IPV4
;
878 ip_addr_prefix
.u
.addr4
.addr
= ntohl(prefix
->u
.prefix4
.s_addr
);
882 ip_addr_prefix
.ver
= LRTR_IPV6
;
883 ipv6_addr_to_host_byte_order(prefix
->u
.prefix6
.s6_addr32
,
884 ip_addr_prefix
.u
.addr6
.addr
);
888 return RPKI_NOT_BEING_USED
;
891 // Do the actual validation
892 rtr_mgr_validate(rtr_config
, as_number
, &ip_addr_prefix
,
893 prefix
->prefixlen
, &result
);
895 // Print Debug output
897 case BGP_PFXV_STATE_VALID
:
899 "Validating Prefix %pFX from asn %u Result: VALID",
902 case BGP_PFXV_STATE_NOT_FOUND
:
904 "Validating Prefix %pFX from asn %u Result: NOT FOUND",
906 return RPKI_NOTFOUND
;
907 case BGP_PFXV_STATE_INVALID
:
909 "Validating Prefix %pFX from asn %u Result: INVALID",
914 "Validating Prefix %pFX from asn %u Result: CANNOT VALIDATE",
918 return RPKI_NOT_BEING_USED
;
921 static int add_cache(struct cache
*cache
)
923 uint8_t preference
= cache
->preference
;
924 struct rtr_mgr_group group
;
926 group
.preference
= preference
;
927 group
.sockets_len
= 1;
928 group
.sockets
= &cache
->rtr_socket
;
931 init_tr_socket(cache
);
933 if (rtr_mgr_add_group(rtr_config
, &group
) != RTR_SUCCESS
) {
934 free_tr_socket(cache
);
939 listnode_add(cache_list
, cache
);
944 static int add_tcp_cache(const char *host
, const char *port
,
945 const uint8_t preference
, const char *bindaddr
)
947 struct rtr_socket
*rtr_socket
;
948 struct tr_tcp_config
*tcp_config
=
949 XCALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_tcp_config
));
950 struct tr_socket
*tr_socket
=
951 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_socket
));
952 struct cache
*cache
=
953 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct cache
));
955 tcp_config
->host
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, host
);
956 tcp_config
->port
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, port
);
958 tcp_config
->bindaddr
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, bindaddr
);
960 tcp_config
->bindaddr
= NULL
;
962 rtr_socket
= create_rtr_socket(tr_socket
);
965 cache
->tr_socket
= tr_socket
;
966 cache
->tr_config
.tcp_config
= tcp_config
;
967 cache
->rtr_socket
= rtr_socket
;
968 cache
->preference
= preference
;
970 int ret
= add_cache(cache
);
971 if (ret
!= SUCCESS
) {
978 #if defined(FOUND_SSH)
979 static int add_ssh_cache(const char *host
, const unsigned int port
,
980 const char *username
, const char *client_privkey_path
,
981 const char *server_pubkey_path
,
982 const uint8_t preference
, const char *bindaddr
)
984 struct tr_ssh_config
*ssh_config
=
985 XCALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_ssh_config
));
986 struct cache
*cache
=
987 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct cache
));
988 struct tr_socket
*tr_socket
=
989 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_socket
));
990 struct rtr_socket
*rtr_socket
;
992 ssh_config
->port
= port
;
993 ssh_config
->host
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, host
);
995 ssh_config
->bindaddr
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, bindaddr
);
997 ssh_config
->bindaddr
= NULL
;
999 ssh_config
->username
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, username
);
1000 ssh_config
->client_privkey_path
=
1001 XSTRDUP(MTYPE_BGP_RPKI_CACHE
, client_privkey_path
);
1002 ssh_config
->server_hostkey_path
=
1003 XSTRDUP(MTYPE_BGP_RPKI_CACHE
, server_pubkey_path
);
1005 rtr_socket
= create_rtr_socket(tr_socket
);
1008 cache
->tr_socket
= tr_socket
;
1009 cache
->tr_config
.ssh_config
= ssh_config
;
1010 cache
->rtr_socket
= rtr_socket
;
1011 cache
->preference
= preference
;
1013 int ret
= add_cache(cache
);
1014 if (ret
!= SUCCESS
) {
1022 static void free_cache(struct cache
*cache
)
1024 if (cache
->type
== TCP
) {
1025 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
->host
);
1026 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
->port
);
1027 XFREE(MTYPE_BGP_RPKI_CACHE
,
1028 cache
->tr_config
.tcp_config
->bindaddr
);
1029 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
);
1031 #if defined(FOUND_SSH)
1033 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.ssh_config
->host
);
1034 XFREE(MTYPE_BGP_RPKI_CACHE
,
1035 cache
->tr_config
.ssh_config
->username
);
1036 XFREE(MTYPE_BGP_RPKI_CACHE
,
1037 cache
->tr_config
.ssh_config
->client_privkey_path
);
1038 XFREE(MTYPE_BGP_RPKI_CACHE
,
1039 cache
->tr_config
.ssh_config
->server_hostkey_path
);
1040 XFREE(MTYPE_BGP_RPKI_CACHE
,
1041 cache
->tr_config
.ssh_config
->bindaddr
);
1042 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.ssh_config
);
1045 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_socket
);
1046 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->rtr_socket
);
1047 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
);
1050 static int config_write(struct vty
*vty
)
1052 struct listnode
*cache_node
;
1053 struct cache
*cache
;
1056 vty_out(vty
, "debug rpki\n");
1058 vty_out(vty
, "!\n");
1059 vty_out(vty
, "rpki\n");
1061 if (polling_period
!= POLLING_PERIOD_DEFAULT
)
1062 vty_out(vty
, " rpki polling_period %d\n", polling_period
);
1063 if (retry_interval
!= RETRY_INTERVAL_DEFAULT
)
1064 vty_out(vty
, " rpki retry_interval %d\n", retry_interval
);
1065 if (expire_interval
!= EXPIRE_INTERVAL_DEFAULT
)
1066 vty_out(vty
, " rpki expire_interval %d\n", expire_interval
);
1068 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1069 switch (cache
->type
) {
1070 struct tr_tcp_config
*tcp_config
;
1071 #if defined(FOUND_SSH)
1072 struct tr_ssh_config
*ssh_config
;
1075 tcp_config
= cache
->tr_config
.tcp_config
;
1076 vty_out(vty
, " rpki cache %s %s ", tcp_config
->host
,
1078 if (tcp_config
->bindaddr
)
1079 vty_out(vty
, "source %s ",
1080 tcp_config
->bindaddr
);
1082 #if defined(FOUND_SSH)
1084 ssh_config
= cache
->tr_config
.ssh_config
;
1085 vty_out(vty
, " rpki cache %s %u %s %s %s ",
1086 ssh_config
->host
, ssh_config
->port
,
1087 ssh_config
->username
,
1088 ssh_config
->client_privkey_path
,
1089 ssh_config
->server_hostkey_path
!= NULL
1090 ? ssh_config
->server_hostkey_path
1092 if (ssh_config
->bindaddr
)
1093 vty_out(vty
, "source %s ",
1094 ssh_config
->bindaddr
);
1101 vty_out(vty
, "preference %hhu\n", cache
->preference
);
1103 vty_out(vty
, "exit\n");
1111 "Enable rpki and enter rpki configuration mode\n")
1113 vty
->node
= RPKI_NODE
;
1121 "Enable rpki and enter rpki configuration mode\n")
1123 rpki_delete_all_cache_nodes();
1128 DEFUN (bgp_rpki_start
,
1132 "start rpki support\n")
1134 if (listcount(cache_list
) == 0)
1136 "Could not start rpki because no caches are configured\n");
1138 if (!is_running()) {
1139 if (start() == ERROR
) {
1140 RPKI_DEBUG("RPKI failed to start");
1147 DEFUN (bgp_rpki_stop
,
1151 "start rpki support\n")
1159 DEFPY (rpki_polling_period
,
1160 rpki_polling_period_cmd
,
1161 "rpki polling_period (1-86400)$pp",
1163 "Set polling period\n"
1164 "Polling period value\n")
1166 polling_period
= pp
;
1170 DEFUN (no_rpki_polling_period
,
1171 no_rpki_polling_period_cmd
,
1172 "no rpki polling_period [(1-86400)]",
1175 "Set polling period back to default\n"
1176 "Polling period value\n")
1178 polling_period
= POLLING_PERIOD_DEFAULT
;
1182 DEFPY (rpki_expire_interval
,
1183 rpki_expire_interval_cmd
,
1184 "rpki expire_interval (600-172800)$tmp",
1186 "Set expire interval\n"
1187 "Expire interval value\n")
1189 if ((unsigned int)tmp
>= polling_period
) {
1190 expire_interval
= tmp
;
1194 vty_out(vty
, "%% Expiry interval must be polling period or larger\n");
1195 return CMD_WARNING_CONFIG_FAILED
;
1198 DEFUN (no_rpki_expire_interval
,
1199 no_rpki_expire_interval_cmd
,
1200 "no rpki expire_interval [(600-172800)]",
1203 "Set expire interval back to default\n"
1204 "Expire interval value\n")
1206 expire_interval
= polling_period
* 2;
1210 DEFPY (rpki_retry_interval
,
1211 rpki_retry_interval_cmd
,
1212 "rpki retry_interval (1-7200)$tmp",
1214 "Set retry interval\n"
1215 "retry interval value\n")
1217 retry_interval
= tmp
;
1221 DEFUN (no_rpki_retry_interval
,
1222 no_rpki_retry_interval_cmd
,
1223 "no rpki retry_interval [(1-7200)]",
1226 "Set retry interval back to default\n"
1227 "retry interval value\n")
1229 retry_interval
= RETRY_INTERVAL_DEFAULT
;
1233 DEFPY(rpki_cache
, rpki_cache_cmd
,
1234 "rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY [SERVER_PUBKEY]> [source <A.B.C.D>$bindaddr] preference (1-255)",
1236 "Install a cache server to current group\n"
1237 "IP address of cache server\n"
1238 "Hostname of cache server\n"
1242 "Path to own SSH private key\n"
1243 "Path to Public key of cache server\n"
1244 "Configure source IP address of RPKI connection\n"
1245 "Define a Source IP Address\n"
1246 "Preference of the cache server\n"
1247 "Preference value\n")
1250 struct listnode
*cache_node
;
1251 struct cache
*current_cache
;
1253 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, current_cache
)) {
1254 if (current_cache
->preference
== preference
) {
1256 "Cache with preference %ld is already configured\n",
1263 // use ssh connection
1265 #if defined(FOUND_SSH)
1267 add_ssh_cache(cache
, sshport
, ssh_uname
, ssh_privkey
,
1268 server_pubkey
, preference
, bindaddr_str
);
1270 return_value
= SUCCESS
;
1272 "ssh sockets are not supported. Please recompile rtrlib and frr with ssh support. If you want to use it\n");
1274 } else { // use tcp connection
1276 add_tcp_cache(cache
, tcpport
, preference
, bindaddr_str
);
1279 if (return_value
== ERROR
) {
1280 vty_out(vty
, "Could not create new rpki cache\n");
1287 DEFPY (no_rpki_cache
,
1289 "no rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY [SERVER_PUBKEY]> [source <A.B.C.D>$bindaddr] preference (1-255)",
1292 "Install a cache server to current group\n"
1293 "IP address of cache server\n"
1294 "Hostname of cache server\n"
1298 "Path to own SSH private key\n"
1299 "Path to Public key of cache server\n"
1300 "Configure source IP address of RPKI connection\n"
1301 "Define a Source IP Address\n"
1302 "Preference of the cache server\n"
1303 "Preference value\n")
1305 struct cache
*cache_p
= find_cache(preference
);
1308 vty_out(vty
, "Could not find cache with preference %ld\n",
1313 if (is_running() && listcount(cache_list
) == 1) {
1315 } else if (is_running()) {
1316 if (rtr_mgr_remove_group(rtr_config
, preference
) == RTR_ERROR
) {
1318 "Could not remove cache with preference %ld\n",
1324 listnode_delete(cache_list
, cache_p
);
1325 free_cache(cache_p
);
1330 DEFPY (show_rpki_prefix_table
,
1331 show_rpki_prefix_table_cmd
,
1332 "show rpki prefix-table [json$uj]",
1335 "Show validated prefixes which were received from RPKI Cache\n"
1338 struct json_object
*json
= NULL
;
1340 if (!is_synchronized()) {
1342 vty_out(vty
, "No connection to RPKI cache server.\n");
1347 json
= json_object_new_object();
1349 print_prefix_table(vty
, json
);
1353 DEFPY (show_rpki_as_number
,
1354 show_rpki_as_number_cmd
,
1355 "show rpki as-number (1-4294967295)$by_asn [json$uj]",
1358 "Lookup by ASN in prefix table\n"
1362 struct json_object
*json
= NULL
;
1364 if (!is_synchronized()) {
1366 vty_out(vty
, "No Connection to RPKI cache server.\n");
1371 json
= json_object_new_object();
1373 print_prefix_table_by_asn(vty
, by_asn
, json
);
1377 DEFPY (show_rpki_prefix
,
1378 show_rpki_prefix_cmd
,
1379 "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn] [json$uj]",
1382 "Lookup IP prefix and optionally ASN in prefix table\n"
1388 json_object
*json
= NULL
;
1389 json_object
*json_records
= NULL
;
1391 if (!is_synchronized()) {
1393 vty_out(vty
, "No Connection to RPKI cache server.\n");
1397 struct lrtr_ip_addr addr
;
1398 char addr_str
[INET6_ADDRSTRLEN
];
1399 size_t addr_len
= strchr(prefix_str
, '/') - prefix_str
;
1401 memset(addr_str
, 0, sizeof(addr_str
));
1402 memcpy(addr_str
, prefix_str
, addr_len
);
1404 if (lrtr_ip_str_to_addr(addr_str
, &addr
) != 0) {
1406 vty_out(vty
, "Invalid IP prefix\n");
1410 struct pfx_record
*matches
= NULL
;
1411 unsigned int match_count
= 0;
1412 enum pfxv_state result
;
1414 if (pfx_table_validate_r(rtr_config
->pfx_table
, &matches
, &match_count
,
1415 asn
, &addr
, prefix
->prefixlen
, &result
)
1418 vty_out(vty
, "Prefix lookup failed\n");
1423 json
= json_object_new_object();
1426 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length",
1429 json_records
= json_object_new_array();
1430 json_object_object_add(json
, "prefixes", json_records
);
1433 for (size_t i
= 0; i
< match_count
; ++i
) {
1434 const struct pfx_record
*record
= &matches
[i
];
1436 if (record
->max_len
>= prefix
->prefixlen
1437 && ((asn
!= 0 && (uint32_t)asn
== record
->asn
)
1439 print_record(&matches
[i
], vty
, json_records
);
1444 vty_json(vty
, json
);
1449 DEFPY (show_rpki_cache_server
,
1450 show_rpki_cache_server_cmd
,
1451 "show rpki cache-server [json$uj]",
1454 "Show configured cache server\n"
1457 struct json_object
*json
= NULL
;
1458 struct json_object
*json_server
= NULL
;
1459 struct json_object
*json_servers
= NULL
;
1460 struct listnode
*cache_node
;
1461 struct cache
*cache
;
1464 json
= json_object_new_object();
1465 json_servers
= json_object_new_array();
1466 json_object_object_add(json
, "servers", json_servers
);
1469 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1470 if (cache
->type
== TCP
) {
1473 "host: %s port: %s, preference: %hhu\n",
1474 cache
->tr_config
.tcp_config
->host
,
1475 cache
->tr_config
.tcp_config
->port
,
1478 json_server
= json_object_new_object();
1479 json_object_string_add(json_server
, "mode",
1481 json_object_string_add(
1482 json_server
, "host",
1483 cache
->tr_config
.tcp_config
->host
);
1484 json_object_string_add(
1485 json_server
, "port",
1486 cache
->tr_config
.tcp_config
->port
);
1487 json_object_int_add(json_server
, "preference",
1489 json_object_array_add(json_servers
,
1493 #if defined(FOUND_SSH)
1494 } else if (cache
->type
== SSH
) {
1497 "host: %s port: %d username: %s server_hostkey_path: %s client_privkey_path: %s, preference: %hhu\n",
1498 cache
->tr_config
.ssh_config
->host
,
1499 cache
->tr_config
.ssh_config
->port
,
1500 cache
->tr_config
.ssh_config
->username
,
1501 cache
->tr_config
.ssh_config
1502 ->server_hostkey_path
,
1503 cache
->tr_config
.ssh_config
1504 ->client_privkey_path
,
1507 json_server
= json_object_new_object();
1508 json_object_string_add(json_server
, "mode",
1510 json_object_string_add(
1511 json_server
, "host",
1512 cache
->tr_config
.ssh_config
->host
);
1513 json_object_int_add(
1514 json_server
, "port",
1515 cache
->tr_config
.ssh_config
->port
);
1516 json_object_string_add(
1517 json_server
, "username",
1518 cache
->tr_config
.ssh_config
->username
);
1519 json_object_string_add(
1520 json_server
, "serverHostkeyPath",
1521 cache
->tr_config
.ssh_config
1522 ->server_hostkey_path
);
1523 json_object_string_add(
1524 json_server
, "clientPrivkeyPath",
1525 cache
->tr_config
.ssh_config
1526 ->client_privkey_path
);
1527 json_object_int_add(json_server
, "preference",
1529 json_object_array_add(json_servers
,
1537 vty_json(vty
, json
);
1542 DEFPY (show_rpki_cache_connection
,
1543 show_rpki_cache_connection_cmd
,
1544 "show rpki cache-connection [json$uj]",
1547 "Show to which RPKI Cache Servers we have a connection\n"
1550 struct json_object
*json
= NULL
;
1551 struct json_object
*json_conn
= NULL
;
1552 struct json_object
*json_conns
= NULL
;
1553 struct listnode
*cache_node
;
1554 struct cache
*cache
;
1555 struct rtr_mgr_group
*group
;
1558 json
= json_object_new_object();
1560 if (!is_synchronized()) {
1562 vty_out(vty
, "No connection to RPKI cache server.\n");
1564 vty_json(vty
, json
);
1569 group
= get_connected_group();
1572 vty_out(vty
, "Cannot find a connected group.\n");
1574 vty_json(vty
, json
);
1580 vty_out(vty
, "Connected to group %d\n", group
->preference
);
1582 json_conns
= json_object_new_array();
1583 json_object_int_add(json
, "connectedGroup", group
->preference
);
1584 json_object_object_add(json
, "connections", json_conns
);
1587 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1588 struct tr_tcp_config
*tcp_config
;
1589 #if defined(FOUND_SSH)
1590 struct tr_ssh_config
*ssh_config
;
1592 switch (cache
->type
) {
1594 tcp_config
= cache
->tr_config
.tcp_config
;
1598 "rpki tcp cache %s %s pref %hhu%s\n",
1599 tcp_config
->host
, tcp_config
->port
,
1601 cache
->rtr_socket
->state
==
1606 json_conn
= json_object_new_object();
1607 json_object_string_add(json_conn
, "mode",
1609 json_object_string_add(json_conn
, "host",
1611 json_object_string_add(json_conn
, "port",
1613 json_object_int_add(json_conn
, "preference",
1615 json_object_string_add(
1617 cache
->rtr_socket
->state
==
1621 json_object_array_add(json_conns
, json_conn
);
1624 #if defined(FOUND_SSH)
1626 ssh_config
= cache
->tr_config
.ssh_config
;
1630 "rpki ssh cache %s %u pref %hhu%s\n",
1631 ssh_config
->host
, ssh_config
->port
,
1633 cache
->rtr_socket
->state
==
1638 json_conn
= json_object_new_object();
1639 json_object_string_add(json_conn
, "mode",
1641 json_object_string_add(json_conn
, "host",
1643 json_object_int_add(json_conn
, "port",
1645 json_object_int_add(json_conn
, "preference",
1647 json_object_string_add(
1649 cache
->rtr_socket
->state
==
1653 json_object_array_add(json_conns
, json_conn
);
1663 vty_json(vty
, json
);
1668 static int config_on_exit(struct vty
*vty
)
1680 return reset(true) == SUCCESS
? CMD_SUCCESS
: CMD_WARNING
;
1687 "Enable debugging for rpki\n")
1693 DEFUN (no_debug_rpki
,
1698 "Disable debugging for rpki\n")
1704 DEFUN_YANG (match_rpki
,
1706 "match rpki <valid|invalid|notfound>",
1711 "Prefix not found\n")
1714 "./match-condition[condition='frr-bgp-route-map:rpki']";
1715 char xpath_value
[XPATH_MAXLEN
];
1717 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
1718 snprintf(xpath_value
, sizeof(xpath_value
),
1719 "%s/rmap-match-condition/frr-bgp-route-map:rpki", xpath
);
1720 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, argv
[2]->arg
);
1722 return nb_cli_apply_changes(vty
, NULL
);
1725 DEFUN_YANG (no_match_rpki
,
1727 "no match rpki <valid|invalid|notfound>",
1733 "Prefix not found\n")
1736 "./match-condition[condition='frr-bgp-route-map:rpki']";
1738 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
1739 return nb_cli_apply_changes(vty
, NULL
);
1742 static void install_cli_commands(void)
1744 // TODO: make config write work
1745 install_node(&rpki_node
);
1746 install_default(RPKI_NODE
);
1747 install_element(CONFIG_NODE
, &rpki_cmd
);
1748 install_element(ENABLE_NODE
, &rpki_cmd
);
1749 install_element(CONFIG_NODE
, &no_rpki_cmd
);
1752 install_element(ENABLE_NODE
, &bgp_rpki_start_cmd
);
1753 install_element(ENABLE_NODE
, &bgp_rpki_stop_cmd
);
1755 /* Install rpki reset command */
1756 install_element(ENABLE_NODE
, &rpki_reset_cmd
);
1757 install_element(RPKI_NODE
, &rpki_reset_cmd
);
1759 /* Install rpki polling period commands */
1760 install_element(RPKI_NODE
, &rpki_polling_period_cmd
);
1761 install_element(RPKI_NODE
, &no_rpki_polling_period_cmd
);
1763 /* Install rpki expire interval commands */
1764 install_element(RPKI_NODE
, &rpki_expire_interval_cmd
);
1765 install_element(RPKI_NODE
, &no_rpki_expire_interval_cmd
);
1767 /* Install rpki retry interval commands */
1768 install_element(RPKI_NODE
, &rpki_retry_interval_cmd
);
1769 install_element(RPKI_NODE
, &no_rpki_retry_interval_cmd
);
1771 /* Install rpki cache commands */
1772 install_element(RPKI_NODE
, &rpki_cache_cmd
);
1773 install_element(RPKI_NODE
, &no_rpki_cache_cmd
);
1775 /* Install show commands */
1776 install_element(VIEW_NODE
, &show_rpki_prefix_table_cmd
);
1777 install_element(VIEW_NODE
, &show_rpki_cache_connection_cmd
);
1778 install_element(VIEW_NODE
, &show_rpki_cache_server_cmd
);
1779 install_element(VIEW_NODE
, &show_rpki_prefix_cmd
);
1780 install_element(VIEW_NODE
, &show_rpki_as_number_cmd
);
1782 /* Install debug commands */
1783 install_element(CONFIG_NODE
, &debug_rpki_cmd
);
1784 install_element(ENABLE_NODE
, &debug_rpki_cmd
);
1785 install_element(CONFIG_NODE
, &no_debug_rpki_cmd
);
1786 install_element(ENABLE_NODE
, &no_debug_rpki_cmd
);
1788 /* Install route match */
1789 route_map_install_match(&route_match_rpki_cmd
);
1790 install_element(RMAP_NODE
, &match_rpki_cmd
);
1791 install_element(RMAP_NODE
, &no_match_rpki_cmd
);
1794 FRR_MODULE_SETUP(.name
= "bgpd_rpki", .version
= "0.3.6",
1795 .description
= "Enable RPKI support for FRR.",
1796 .init
= bgp_rpki_module_init
,