1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2013 Michael Mester (m.mester@fu-berlin.de), for FU Berlin
5 * Copyright (C) 2014-2017 Andreas Reuter (andreas.reuter@fu-berlin.de), for FU
7 * Copyright (C) 2016-2017 Colin Sames (colin.sames@haw-hamburg.de), for HAW
9 * Copyright (C) 2017-2018 Marcel Röthke (marcel.roethke@haw-hamburg.de),
13 /* If rtrlib compiled with ssh support, don`t fail build */
14 #define LIBSSH_LEGACY_0_4
28 #include "bgpd/bgpd.h"
29 #include "bgpd/bgp_table.h"
30 #include "bgp_advertise.h"
31 #include "bgpd/bgp_debug.h"
32 #include "bgpd/bgp_attr.h"
33 #include "bgpd/bgp_aspath.h"
34 #include "bgpd/bgp_route.h"
35 #include "bgpd/bgp_rpki.h"
36 #include "northbound_cli.h"
38 #include "lib/network.h"
39 #include "rtrlib/rtrlib.h"
42 #include "lib/version.h"
44 #include "bgpd/bgp_rpki_clippy.c"
46 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_CACHE
, "BGP RPKI Cache server");
47 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_CACHE_GROUP
, "BGP RPKI Cache server group");
48 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_RTRLIB
, "BGP RPKI RTRLib");
49 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_REVALIDATE
, "BGP RPKI Revalidation");
51 #define POLLING_PERIOD_DEFAULT 3600
52 #define EXPIRE_INTERVAL_DEFAULT 7200
53 #define RETRY_INTERVAL_DEFAULT 600
54 #define BGP_RPKI_CACHE_SERVER_SYNC_RETRY_TIMEOUT 3
56 static struct event
*t_rpki_sync
;
58 #define RPKI_DEBUG(...) \
60 zlog_debug("RPKI: " __VA_ARGS__); \
63 #define RPKI_OUTPUT_STRING "Control rpki specific settings\n"
66 enum { TCP
, SSH
} type
;
67 struct tr_socket
*tr_socket
;
69 struct tr_tcp_config
*tcp_config
;
70 struct tr_ssh_config
*ssh_config
;
72 struct rtr_socket
*rtr_socket
;
76 enum return_values
{ SUCCESS
= 0, ERROR
= -1 };
78 struct rpki_for_each_record_arg
{
80 unsigned int *prefix_amount
;
83 enum asnotation_mode asnotation
;
86 static int start(void);
87 static void stop(void);
88 static int reset(bool force
);
89 static struct rtr_mgr_group
*get_connected_group(void);
90 static void print_prefix_table(struct vty
*vty
, json_object
*json
);
91 static void install_cli_commands(void);
92 static int config_write(struct vty
*vty
);
93 static int config_on_exit(struct vty
*vty
);
94 static void free_cache(struct cache
*cache
);
95 static struct rtr_mgr_group
*get_groups(void);
96 #if defined(FOUND_SSH)
97 static int add_ssh_cache(const char *host
, const unsigned int port
,
98 const char *username
, const char *client_privkey_path
,
99 const char *server_pubkey_path
,
100 const uint8_t preference
, const char *bindaddr
);
102 static struct rtr_socket
*create_rtr_socket(struct tr_socket
*tr_socket
);
103 static struct cache
*find_cache(const uint8_t preference
);
104 static void rpki_delete_all_cache_nodes(void);
105 static int add_tcp_cache(const char *host
, const char *port
,
106 const uint8_t preference
, const char *bindaddr
);
107 static void print_record(const struct pfx_record
*record
, struct vty
*vty
,
108 json_object
*json
, enum asnotation_mode asnotation
);
109 static bool is_synchronized(void);
110 static bool is_running(void);
111 static bool is_stopping(void);
112 static void route_match_free(void *rule
);
113 static enum route_map_cmd_result_t
route_match(void *rule
,
114 const struct prefix
*prefix
,
117 static void *route_match_compile(const char *arg
);
118 static void revalidate_bgp_node(struct bgp_dest
*dest
, afi_t afi
, safi_t safi
);
119 static void revalidate_all_routes(void);
121 static struct rtr_mgr_config
*rtr_config
;
122 static struct list
*cache_list
;
123 static bool rtr_is_running
;
124 static bool rtr_is_stopping
;
125 static bool rtr_is_synced
;
126 static _Atomic
int rtr_update_overflow
;
127 static bool rpki_debug
;
128 static unsigned int polling_period
;
129 static unsigned int expire_interval
;
130 static unsigned int retry_interval
;
131 static int rpki_sync_socket_rtr
;
132 static int rpki_sync_socket_bgpd
;
134 static struct cmd_node rpki_node
= {
137 .parent_node
= CONFIG_NODE
,
138 .prompt
= "%s(config-rpki)# ",
139 .config_write
= config_write
,
140 .node_exit
= config_on_exit
,
142 static const struct route_map_rule_cmd route_match_rpki_cmd
= {
143 "rpki", route_match
, route_match_compile
, route_match_free
};
145 static void *malloc_wrapper(size_t size
)
147 return XMALLOC(MTYPE_BGP_RPKI_RTRLIB
, size
);
150 static void *realloc_wrapper(void *ptr
, size_t size
)
152 return XREALLOC(MTYPE_BGP_RPKI_RTRLIB
, ptr
, size
);
155 static void free_wrapper(void *ptr
)
157 XFREE(MTYPE_BGP_RPKI_RTRLIB
, ptr
);
160 static void init_tr_socket(struct cache
*cache
)
162 if (cache
->type
== TCP
)
163 tr_tcp_init(cache
->tr_config
.tcp_config
,
165 #if defined(FOUND_SSH)
167 tr_ssh_init(cache
->tr_config
.ssh_config
,
172 static void free_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 int rpki_validate_prefix(struct peer
*peer
, struct attr
*attr
,
185 const struct prefix
*prefix
);
187 static void ipv6_addr_to_network_byte_order(const uint32_t *src
, uint32_t *dest
)
191 for (i
= 0; i
< 4; i
++)
192 dest
[i
] = htonl(src
[i
]);
195 static void ipv6_addr_to_host_byte_order(const uint32_t *src
, uint32_t *dest
)
199 for (i
= 0; i
< 4; i
++)
200 dest
[i
] = ntohl(src
[i
]);
203 static enum route_map_cmd_result_t
route_match(void *rule
,
204 const struct prefix
*prefix
,
207 int *rpki_status
= rule
;
208 struct bgp_path_info
*path
;
212 if (rpki_validate_prefix(path
->peer
, path
->attr
, prefix
)
220 static void *route_match_compile(const char *arg
)
224 rpki_status
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(int));
226 if (strcmp(arg
, "valid") == 0)
227 *rpki_status
= RPKI_VALID
;
228 else if (strcmp(arg
, "invalid") == 0)
229 *rpki_status
= RPKI_INVALID
;
231 *rpki_status
= RPKI_NOTFOUND
;
236 static void route_match_free(void *rule
)
238 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
241 static struct rtr_socket
*create_rtr_socket(struct tr_socket
*tr_socket
)
243 struct rtr_socket
*rtr_socket
=
244 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct rtr_socket
));
245 rtr_socket
->tr_socket
= tr_socket
;
249 static struct cache
*find_cache(const uint8_t preference
)
251 struct listnode
*cache_node
;
254 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
255 if (cache
->preference
== preference
)
261 static void rpki_delete_all_cache_nodes(void)
263 struct listnode
*cache_node
, *cache_next
;
266 for (ALL_LIST_ELEMENTS(cache_list
, cache_node
, cache_next
, cache
)) {
267 rtr_mgr_remove_group(rtr_config
, cache
->preference
);
268 listnode_delete(cache_list
, cache
);
272 static void print_record(const struct pfx_record
*record
, struct vty
*vty
,
273 json_object
*json
, enum asnotation_mode asnotation
)
275 char ip
[INET6_ADDRSTRLEN
];
276 json_object
*json_record
= NULL
;
278 lrtr_ip_addr_to_str(&record
->prefix
, ip
, sizeof(ip
));
281 vty_out(vty
, "%-40s %3u - %3u ", ip
, record
->min_len
,
283 vty_out(vty
, ASN_FORMAT(asnotation
), (as_t
*)&record
->asn
);
286 json_record
= json_object_new_object();
287 json_object_string_add(json_record
, "prefix", ip
);
288 json_object_int_add(json_record
, "prefixLenMin",
290 json_object_int_add(json_record
, "prefixLenMax",
292 asn_asn2json(json_record
, "asn", record
->asn
, asnotation
);
293 json_object_array_add(json
, json_record
);
297 static void print_record_by_asn(const struct pfx_record
*record
, void *data
)
299 struct rpki_for_each_record_arg
*arg
= data
;
300 struct vty
*vty
= arg
->vty
;
302 if (record
->asn
== arg
->as
) {
303 (*arg
->prefix_amount
)++;
304 print_record(record
, vty
, arg
->json
, arg
->asnotation
);
308 static void print_record_cb(const struct pfx_record
*record
, void *data
)
310 struct rpki_for_each_record_arg
*arg
= data
;
311 struct vty
*vty
= arg
->vty
;
313 (*arg
->prefix_amount
)++;
315 print_record(record
, vty
, arg
->json
, arg
->asnotation
);
318 static struct rtr_mgr_group
*get_groups(void)
320 struct listnode
*cache_node
;
321 struct rtr_mgr_group
*rtr_mgr_groups
;
324 int group_count
= listcount(cache_list
);
326 if (group_count
== 0)
329 rtr_mgr_groups
= XMALLOC(MTYPE_BGP_RPKI_CACHE_GROUP
,
330 group_count
* sizeof(struct rtr_mgr_group
));
334 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
335 rtr_mgr_groups
[i
].sockets
= &cache
->rtr_socket
;
336 rtr_mgr_groups
[i
].sockets_len
= 1;
337 rtr_mgr_groups
[i
].preference
= cache
->preference
;
339 init_tr_socket(cache
);
344 return rtr_mgr_groups
;
347 inline bool is_synchronized(void)
349 return rtr_is_synced
;
352 inline bool is_running(void)
354 return rtr_is_running
;
357 inline bool is_stopping(void)
359 return rtr_is_stopping
;
362 static void pfx_record_to_prefix(struct pfx_record
*record
,
363 struct prefix
*prefix
)
365 prefix
->prefixlen
= record
->min_len
;
367 if (record
->prefix
.ver
== LRTR_IPV4
) {
368 prefix
->family
= AF_INET
;
369 prefix
->u
.prefix4
.s_addr
= htonl(record
->prefix
.u
.addr4
.addr
);
371 prefix
->family
= AF_INET6
;
372 ipv6_addr_to_network_byte_order(record
->prefix
.u
.addr6
.addr
,
373 prefix
->u
.prefix6
.s6_addr32
);
377 struct rpki_revalidate_prefix
{
379 struct prefix prefix
;
384 static void rpki_revalidate_prefix(struct event
*thread
)
386 struct rpki_revalidate_prefix
*rrp
= EVENT_ARG(thread
);
387 struct bgp_dest
*match
, *node
;
389 match
= bgp_table_subtree_lookup(rrp
->bgp
->rib
[rrp
->afi
][rrp
->safi
],
395 if (bgp_dest_has_bgp_path_info_data(node
)) {
396 revalidate_bgp_node(node
, rrp
->afi
, rrp
->safi
);
399 node
= bgp_route_next_until(node
, match
);
402 XFREE(MTYPE_BGP_RPKI_REVALIDATE
, rrp
);
405 static void bgpd_sync_callback(struct event
*thread
)
408 struct listnode
*node
;
409 struct prefix prefix
;
410 struct pfx_record rec
;
412 event_add_read(bm
->master
, bgpd_sync_callback
, NULL
,
413 rpki_sync_socket_bgpd
, NULL
);
415 if (atomic_load_explicit(&rtr_update_overflow
, memory_order_seq_cst
)) {
416 while (read(rpki_sync_socket_bgpd
, &rec
,
417 sizeof(struct pfx_record
)) != -1)
420 atomic_store_explicit(&rtr_update_overflow
, 0,
421 memory_order_seq_cst
);
422 revalidate_all_routes();
427 read(rpki_sync_socket_bgpd
, &rec
, sizeof(struct pfx_record
));
428 if (retval
!= sizeof(struct pfx_record
)) {
429 RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd");
432 pfx_record_to_prefix(&rec
, &prefix
);
434 afi_t afi
= (rec
.prefix
.ver
== LRTR_IPV4
) ? AFI_IP
: AFI_IP6
;
436 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
439 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
440 struct bgp_table
*table
= bgp
->rib
[afi
][safi
];
441 struct rpki_revalidate_prefix
*rrp
;
446 rrp
= XCALLOC(MTYPE_BGP_RPKI_REVALIDATE
, sizeof(*rrp
));
448 rrp
->prefix
= prefix
;
451 event_add_event(bm
->master
, rpki_revalidate_prefix
, rrp
,
452 0, &bgp
->t_revalidate
[afi
][safi
]);
457 static void revalidate_bgp_node(struct bgp_dest
*bgp_dest
, afi_t afi
,
460 struct bgp_adj_in
*ain
;
462 for (ain
= bgp_dest
->adj_in
; ain
; ain
= ain
->next
) {
463 struct bgp_path_info
*path
=
464 bgp_dest_get_bgp_path_info(bgp_dest
);
465 mpls_label_t
*label
= NULL
;
466 uint32_t num_labels
= 0;
468 if (path
&& path
->extra
) {
469 label
= path
->extra
->label
;
470 num_labels
= path
->extra
->num_labels
;
472 (void)bgp_update(ain
->peer
, bgp_dest_get_prefix(bgp_dest
),
473 ain
->addpath_rx_id
, ain
->attr
, afi
, safi
,
474 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
, label
,
475 num_labels
, 1, NULL
);
480 * The act of a soft reconfig in revalidation is really expensive
481 * coupled with the fact that the download of a full rpki state
482 * from a rpki server can be expensive, let's break up the revalidation
483 * to a point in time in the future to allow other bgp events
486 struct rpki_revalidate_peer
{
492 static void bgp_rpki_revalidate_peer(struct event
*thread
)
494 struct rpki_revalidate_peer
*rvp
= EVENT_ARG(thread
);
497 * Here's the expensive bit of gnomish deviousness
499 bgp_soft_reconfig_in(rvp
->peer
, rvp
->afi
, rvp
->safi
);
501 XFREE(MTYPE_BGP_RPKI_REVALIDATE
, rvp
);
504 static void revalidate_all_routes(void)
507 struct listnode
*node
;
509 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
511 struct listnode
*peer_listnode
;
513 for (ALL_LIST_ELEMENTS_RO(bgp
->peer
, peer_listnode
, peer
)) {
517 FOREACH_AFI_SAFI (afi
, safi
) {
518 struct rpki_revalidate_peer
*rvp
;
520 if (!bgp
->rib
[afi
][safi
])
523 if (!peer_established(peer
))
526 rvp
= XCALLOC(MTYPE_BGP_RPKI_REVALIDATE
,
533 bm
->master
, bgp_rpki_revalidate_peer
,
535 &peer
->t_revalidate_all
[afi
][safi
]);
541 static void rpki_update_cb_sync_rtr(struct pfx_table
*p
__attribute__((unused
)),
542 const struct pfx_record rec
,
543 const bool added
__attribute__((unused
)))
546 atomic_load_explicit(&rtr_update_overflow
, memory_order_seq_cst
))
550 write(rpki_sync_socket_rtr
, &rec
, sizeof(struct pfx_record
));
551 if (retval
== -1 && (errno
== EAGAIN
|| errno
== EWOULDBLOCK
))
552 atomic_store_explicit(&rtr_update_overflow
, 1,
553 memory_order_seq_cst
);
555 else if (retval
!= sizeof(struct pfx_record
))
556 RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
559 static void rpki_init_sync_socket(void)
564 RPKI_DEBUG("initializing sync socket");
565 if (socketpair(PF_LOCAL
, SOCK_DGRAM
, 0, fds
) != 0) {
566 msg
= "could not open rpki sync socketpair";
569 rpki_sync_socket_rtr
= fds
[0];
570 rpki_sync_socket_bgpd
= fds
[1];
572 if (set_nonblocking(rpki_sync_socket_rtr
) != 0) {
573 msg
= "could not set rpki_sync_socket_rtr to non blocking";
577 if (set_nonblocking(rpki_sync_socket_bgpd
) != 0) {
578 msg
= "could not set rpki_sync_socket_bgpd to non blocking";
583 event_add_read(bm
->master
, bgpd_sync_callback
, NULL
,
584 rpki_sync_socket_bgpd
, NULL
);
589 zlog_err("RPKI: %s", msg
);
594 static int bgp_rpki_init(struct event_loop
*master
)
597 rtr_is_running
= false;
598 rtr_is_stopping
= false;
599 rtr_is_synced
= false;
601 cache_list
= list_new();
602 cache_list
->del
= (void (*)(void *)) & free_cache
;
604 polling_period
= POLLING_PERIOD_DEFAULT
;
605 expire_interval
= EXPIRE_INTERVAL_DEFAULT
;
606 retry_interval
= RETRY_INTERVAL_DEFAULT
;
607 install_cli_commands();
608 rpki_init_sync_socket();
612 static int bgp_rpki_fini(void)
615 list_delete(&cache_list
);
617 close(rpki_sync_socket_rtr
);
618 close(rpki_sync_socket_bgpd
);
623 static int bgp_rpki_module_init(void)
625 lrtr_set_alloc_functions(malloc_wrapper
, realloc_wrapper
, free_wrapper
);
627 hook_register(bgp_rpki_prefix_status
, rpki_validate_prefix
);
628 hook_register(frr_late_init
, bgp_rpki_init
);
629 hook_register(frr_early_fini
, bgp_rpki_fini
);
634 static void sync_expired(struct event
*thread
)
636 if (!rtr_mgr_conf_in_sync(rtr_config
)) {
637 RPKI_DEBUG("rtr_mgr is not synced, retrying.");
638 event_add_timer(bm
->master
, sync_expired
, NULL
,
639 BGP_RPKI_CACHE_SERVER_SYNC_RETRY_TIMEOUT
,
644 RPKI_DEBUG("rtr_mgr sync is done.");
646 rtr_is_synced
= true;
649 static int start(void)
653 rtr_is_stopping
= false;
654 rtr_is_synced
= false;
655 rtr_update_overflow
= 0;
657 if (list_isempty(cache_list
)) {
659 "No caches were found in config. Prefix validation is off.");
662 RPKI_DEBUG("Init rtr_mgr.");
663 int groups_len
= listcount(cache_list
);
664 struct rtr_mgr_group
*groups
= get_groups();
666 RPKI_DEBUG("Polling period: %d", polling_period
);
667 ret
= rtr_mgr_init(&rtr_config
, groups
, groups_len
, polling_period
,
668 expire_interval
, retry_interval
,
669 rpki_update_cb_sync_rtr
, NULL
, NULL
, NULL
);
670 if (ret
== RTR_ERROR
) {
671 RPKI_DEBUG("Init rtr_mgr failed.");
675 RPKI_DEBUG("Starting rtr_mgr.");
676 ret
= rtr_mgr_start(rtr_config
);
677 if (ret
== RTR_ERROR
) {
678 RPKI_DEBUG("Starting rtr_mgr failed.");
679 rtr_mgr_free(rtr_config
);
683 event_add_timer(bm
->master
, sync_expired
, NULL
, 0, &t_rpki_sync
);
685 XFREE(MTYPE_BGP_RPKI_CACHE_GROUP
, groups
);
687 rtr_is_running
= true;
692 static void stop(void)
694 rtr_is_stopping
= true;
696 EVENT_OFF(t_rpki_sync
);
697 rtr_mgr_stop(rtr_config
);
698 rtr_mgr_free(rtr_config
);
699 rtr_is_running
= false;
703 static int reset(bool force
)
705 if (is_running() && !force
)
708 RPKI_DEBUG("Resetting RPKI Session");
713 static struct rtr_mgr_group
*get_connected_group(void)
715 if (!cache_list
|| list_isempty(cache_list
))
718 return rtr_mgr_get_first_group(rtr_config
);
721 static void print_prefix_table_by_asn(struct vty
*vty
, as_t as
,
724 unsigned int number_of_ipv4_prefixes
= 0;
725 unsigned int number_of_ipv6_prefixes
= 0;
726 struct rtr_mgr_group
*group
= get_connected_group();
727 struct rpki_for_each_record_arg arg
;
728 json_object
*json_records
= NULL
;
733 arg
.asnotation
= bgp_get_asnotation(bgp_lookup_by_vrf_id(VRF_DEFAULT
));
737 vty_out(vty
, "Cannot find a connected group.\n");
741 struct pfx_table
*pfx_table
= group
->sockets
[0]->pfx_table
;
744 vty_out(vty
, "RPKI/RTR prefix table\n");
745 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length",
748 json_records
= json_object_new_array();
749 json_object_object_add(json
, "prefixes", json_records
);
750 arg
.json
= json_records
;
753 arg
.prefix_amount
= &number_of_ipv4_prefixes
;
754 pfx_table_for_each_ipv4_record(pfx_table
, print_record_by_asn
, &arg
);
756 arg
.prefix_amount
= &number_of_ipv6_prefixes
;
757 pfx_table_for_each_ipv6_record(pfx_table
, print_record_by_asn
, &arg
);
760 vty_out(vty
, "Number of IPv4 Prefixes: %u\n",
761 number_of_ipv4_prefixes
);
762 vty_out(vty
, "Number of IPv6 Prefixes: %u\n",
763 number_of_ipv6_prefixes
);
765 json_object_int_add(json
, "ipv4PrefixCount",
766 number_of_ipv4_prefixes
);
767 json_object_int_add(json
, "ipv6PrefixCount",
768 number_of_ipv6_prefixes
);
775 static void print_prefix_table(struct vty
*vty
, json_object
*json
)
777 struct rpki_for_each_record_arg arg
;
779 unsigned int number_of_ipv4_prefixes
= 0;
780 unsigned int number_of_ipv6_prefixes
= 0;
781 struct rtr_mgr_group
*group
= get_connected_group();
782 json_object
*json_records
= NULL
;
786 arg
.asnotation
= bgp_get_asnotation(bgp_lookup_by_vrf_id(VRF_DEFAULT
));
790 vty_out(vty
, "Cannot find a connected group.\n");
794 struct pfx_table
*pfx_table
= group
->sockets
[0]->pfx_table
;
797 vty_out(vty
, "RPKI/RTR prefix table\n");
798 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length",
801 json_records
= json_object_new_array();
802 json_object_object_add(json
, "prefixes", json_records
);
803 arg
.json
= json_records
;
806 arg
.prefix_amount
= &number_of_ipv4_prefixes
;
807 pfx_table_for_each_ipv4_record(pfx_table
, print_record_cb
, &arg
);
809 arg
.prefix_amount
= &number_of_ipv6_prefixes
;
810 pfx_table_for_each_ipv6_record(pfx_table
, print_record_cb
, &arg
);
813 vty_out(vty
, "Number of IPv4 Prefixes: %u\n",
814 number_of_ipv4_prefixes
);
815 vty_out(vty
, "Number of IPv6 Prefixes: %u\n",
816 number_of_ipv6_prefixes
);
818 json_object_int_add(json
, "ipv4PrefixCount",
819 number_of_ipv4_prefixes
);
820 json_object_int_add(json
, "ipv6PrefixCount",
821 number_of_ipv6_prefixes
);
828 static int rpki_validate_prefix(struct peer
*peer
, struct attr
*attr
,
829 const struct prefix
*prefix
)
831 struct assegment
*as_segment
;
833 struct lrtr_ip_addr ip_addr_prefix
;
834 enum pfxv_state result
;
836 if (!is_synchronized())
837 return RPKI_NOT_BEING_USED
;
839 // No aspath means route comes from iBGP
840 if (!attr
->aspath
|| !attr
->aspath
->segments
) {
842 as_number
= peer
->bgp
->as
;
844 as_segment
= attr
->aspath
->segments
;
845 // Find last AsSegment
846 while (as_segment
->next
)
847 as_segment
= as_segment
->next
;
849 if (as_segment
->type
== AS_SEQUENCE
) {
851 as_number
= as_segment
->as
[as_segment
->length
- 1];
852 } else if (as_segment
->type
== AS_CONFED_SEQUENCE
853 || as_segment
->type
== AS_CONFED_SET
) {
855 as_number
= peer
->bgp
->as
;
857 // RFC says: "Take distinguished value NONE as asn"
858 // which means state is unknown
859 return RPKI_NOTFOUND
;
863 // Get the prefix in requested format
864 switch (prefix
->family
) {
866 ip_addr_prefix
.ver
= LRTR_IPV4
;
867 ip_addr_prefix
.u
.addr4
.addr
= ntohl(prefix
->u
.prefix4
.s_addr
);
871 ip_addr_prefix
.ver
= LRTR_IPV6
;
872 ipv6_addr_to_host_byte_order(prefix
->u
.prefix6
.s6_addr32
,
873 ip_addr_prefix
.u
.addr6
.addr
);
877 return RPKI_NOT_BEING_USED
;
880 // Do the actual validation
881 rtr_mgr_validate(rtr_config
, as_number
, &ip_addr_prefix
,
882 prefix
->prefixlen
, &result
);
884 // Print Debug output
886 case BGP_PFXV_STATE_VALID
:
888 "Validating Prefix %pFX from asn %u Result: VALID",
891 case BGP_PFXV_STATE_NOT_FOUND
:
893 "Validating Prefix %pFX from asn %u Result: NOT FOUND",
895 return RPKI_NOTFOUND
;
896 case BGP_PFXV_STATE_INVALID
:
898 "Validating Prefix %pFX from asn %u Result: INVALID",
903 "Validating Prefix %pFX from asn %u Result: CANNOT VALIDATE",
907 return RPKI_NOT_BEING_USED
;
910 static int add_cache(struct cache
*cache
)
912 uint8_t preference
= cache
->preference
;
913 struct rtr_mgr_group group
;
915 group
.preference
= preference
;
916 group
.sockets_len
= 1;
917 group
.sockets
= &cache
->rtr_socket
;
920 init_tr_socket(cache
);
922 if (rtr_mgr_add_group(rtr_config
, &group
) != RTR_SUCCESS
) {
923 free_tr_socket(cache
);
928 listnode_add(cache_list
, cache
);
933 static int add_tcp_cache(const char *host
, const char *port
,
934 const uint8_t preference
, const char *bindaddr
)
936 struct rtr_socket
*rtr_socket
;
937 struct tr_tcp_config
*tcp_config
=
938 XCALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_tcp_config
));
939 struct tr_socket
*tr_socket
=
940 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_socket
));
941 struct cache
*cache
=
942 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct cache
));
944 tcp_config
->host
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, host
);
945 tcp_config
->port
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, port
);
947 tcp_config
->bindaddr
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, bindaddr
);
949 tcp_config
->bindaddr
= NULL
;
951 rtr_socket
= create_rtr_socket(tr_socket
);
954 cache
->tr_socket
= tr_socket
;
955 cache
->tr_config
.tcp_config
= tcp_config
;
956 cache
->rtr_socket
= rtr_socket
;
957 cache
->preference
= preference
;
959 int ret
= add_cache(cache
);
960 if (ret
!= SUCCESS
) {
967 #if defined(FOUND_SSH)
968 static int add_ssh_cache(const char *host
, const unsigned int port
,
969 const char *username
, const char *client_privkey_path
,
970 const char *server_pubkey_path
,
971 const uint8_t preference
, const char *bindaddr
)
973 struct tr_ssh_config
*ssh_config
=
974 XCALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_ssh_config
));
975 struct cache
*cache
=
976 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct cache
));
977 struct tr_socket
*tr_socket
=
978 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_socket
));
979 struct rtr_socket
*rtr_socket
;
981 ssh_config
->port
= port
;
982 ssh_config
->host
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, host
);
984 ssh_config
->bindaddr
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, bindaddr
);
986 ssh_config
->bindaddr
= NULL
;
988 ssh_config
->username
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, username
);
989 ssh_config
->client_privkey_path
=
990 XSTRDUP(MTYPE_BGP_RPKI_CACHE
, client_privkey_path
);
991 ssh_config
->server_hostkey_path
=
992 XSTRDUP(MTYPE_BGP_RPKI_CACHE
, server_pubkey_path
);
994 rtr_socket
= create_rtr_socket(tr_socket
);
997 cache
->tr_socket
= tr_socket
;
998 cache
->tr_config
.ssh_config
= ssh_config
;
999 cache
->rtr_socket
= rtr_socket
;
1000 cache
->preference
= preference
;
1002 int ret
= add_cache(cache
);
1003 if (ret
!= SUCCESS
) {
1011 static void free_cache(struct cache
*cache
)
1013 if (cache
->type
== TCP
) {
1014 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
->host
);
1015 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
->port
);
1016 XFREE(MTYPE_BGP_RPKI_CACHE
,
1017 cache
->tr_config
.tcp_config
->bindaddr
);
1018 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
);
1020 #if defined(FOUND_SSH)
1022 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.ssh_config
->host
);
1023 XFREE(MTYPE_BGP_RPKI_CACHE
,
1024 cache
->tr_config
.ssh_config
->username
);
1025 XFREE(MTYPE_BGP_RPKI_CACHE
,
1026 cache
->tr_config
.ssh_config
->client_privkey_path
);
1027 XFREE(MTYPE_BGP_RPKI_CACHE
,
1028 cache
->tr_config
.ssh_config
->server_hostkey_path
);
1029 XFREE(MTYPE_BGP_RPKI_CACHE
,
1030 cache
->tr_config
.ssh_config
->bindaddr
);
1031 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.ssh_config
);
1034 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_socket
);
1035 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->rtr_socket
);
1036 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
);
1039 static int config_write(struct vty
*vty
)
1041 struct listnode
*cache_node
;
1042 struct cache
*cache
;
1045 vty_out(vty
, "debug rpki\n");
1047 vty_out(vty
, "!\n");
1048 vty_out(vty
, "rpki\n");
1050 if (polling_period
!= POLLING_PERIOD_DEFAULT
)
1051 vty_out(vty
, " rpki polling_period %d\n", polling_period
);
1052 if (retry_interval
!= RETRY_INTERVAL_DEFAULT
)
1053 vty_out(vty
, " rpki retry_interval %d\n", retry_interval
);
1054 if (expire_interval
!= EXPIRE_INTERVAL_DEFAULT
)
1055 vty_out(vty
, " rpki expire_interval %d\n", expire_interval
);
1057 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1058 switch (cache
->type
) {
1059 struct tr_tcp_config
*tcp_config
;
1060 #if defined(FOUND_SSH)
1061 struct tr_ssh_config
*ssh_config
;
1064 tcp_config
= cache
->tr_config
.tcp_config
;
1065 vty_out(vty
, " rpki cache %s %s ", tcp_config
->host
,
1067 if (tcp_config
->bindaddr
)
1068 vty_out(vty
, "source %s ",
1069 tcp_config
->bindaddr
);
1071 #if defined(FOUND_SSH)
1073 ssh_config
= cache
->tr_config
.ssh_config
;
1074 vty_out(vty
, " rpki cache %s %u %s %s %s ",
1075 ssh_config
->host
, ssh_config
->port
,
1076 ssh_config
->username
,
1077 ssh_config
->client_privkey_path
,
1078 ssh_config
->server_hostkey_path
!= NULL
1079 ? ssh_config
->server_hostkey_path
1081 if (ssh_config
->bindaddr
)
1082 vty_out(vty
, "source %s ",
1083 ssh_config
->bindaddr
);
1090 vty_out(vty
, "preference %hhu\n", cache
->preference
);
1092 vty_out(vty
, "exit\n");
1100 "Enable rpki and enter rpki configuration mode\n")
1102 vty
->node
= RPKI_NODE
;
1110 "Enable rpki and enter rpki configuration mode\n")
1112 rpki_delete_all_cache_nodes();
1117 DEFUN (bgp_rpki_start
,
1121 "start rpki support\n")
1123 if (listcount(cache_list
) == 0)
1125 "Could not start rpki because no caches are configured\n");
1127 if (!is_running()) {
1128 if (start() == ERROR
) {
1129 RPKI_DEBUG("RPKI failed to start");
1136 DEFUN (bgp_rpki_stop
,
1140 "start rpki support\n")
1148 DEFPY (rpki_polling_period
,
1149 rpki_polling_period_cmd
,
1150 "rpki polling_period (1-86400)$pp",
1152 "Set polling period\n"
1153 "Polling period value\n")
1155 polling_period
= pp
;
1159 DEFUN (no_rpki_polling_period
,
1160 no_rpki_polling_period_cmd
,
1161 "no rpki polling_period [(1-86400)]",
1164 "Set polling period back to default\n"
1165 "Polling period value\n")
1167 polling_period
= POLLING_PERIOD_DEFAULT
;
1171 DEFPY (rpki_expire_interval
,
1172 rpki_expire_interval_cmd
,
1173 "rpki expire_interval (600-172800)$tmp",
1175 "Set expire interval\n"
1176 "Expire interval value\n")
1178 if ((unsigned int)tmp
>= polling_period
) {
1179 expire_interval
= tmp
;
1183 vty_out(vty
, "%% Expiry interval must be polling period or larger\n");
1184 return CMD_WARNING_CONFIG_FAILED
;
1187 DEFUN (no_rpki_expire_interval
,
1188 no_rpki_expire_interval_cmd
,
1189 "no rpki expire_interval [(600-172800)]",
1192 "Set expire interval back to default\n"
1193 "Expire interval value\n")
1195 expire_interval
= polling_period
* 2;
1199 DEFPY (rpki_retry_interval
,
1200 rpki_retry_interval_cmd
,
1201 "rpki retry_interval (1-7200)$tmp",
1203 "Set retry interval\n"
1204 "retry interval value\n")
1206 retry_interval
= tmp
;
1210 DEFUN (no_rpki_retry_interval
,
1211 no_rpki_retry_interval_cmd
,
1212 "no rpki retry_interval [(1-7200)]",
1215 "Set retry interval back to default\n"
1216 "retry interval value\n")
1218 retry_interval
= RETRY_INTERVAL_DEFAULT
;
1222 DEFPY(rpki_cache
, rpki_cache_cmd
,
1223 "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)",
1225 "Install a cache server to current group\n"
1226 "IP address of cache server\n"
1227 "Hostname of cache server\n"
1231 "Path to own SSH private key\n"
1232 "Path to Public key of cache server\n"
1233 "Configure source IP address of RPKI connection\n"
1234 "Define a Source IP Address\n"
1235 "Preference of the cache server\n"
1236 "Preference value\n")
1239 struct listnode
*cache_node
;
1240 struct cache
*current_cache
;
1242 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, current_cache
)) {
1243 if (current_cache
->preference
== preference
) {
1245 "Cache with preference %ld is already configured\n",
1252 // use ssh connection
1254 #if defined(FOUND_SSH)
1256 add_ssh_cache(cache
, sshport
, ssh_uname
, ssh_privkey
,
1257 server_pubkey
, preference
, bindaddr_str
);
1259 return_value
= SUCCESS
;
1261 "ssh sockets are not supported. Please recompile rtrlib and frr with ssh support. If you want to use it\n");
1263 } else { // use tcp connection
1265 add_tcp_cache(cache
, tcpport
, preference
, bindaddr_str
);
1268 if (return_value
== ERROR
) {
1269 vty_out(vty
, "Could not create new rpki cache\n");
1276 DEFPY (no_rpki_cache
,
1278 "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)",
1281 "Install a cache server to current group\n"
1282 "IP address of cache server\n"
1283 "Hostname of cache server\n"
1287 "Path to own SSH private key\n"
1288 "Path to Public key of cache server\n"
1289 "Configure source IP address of RPKI connection\n"
1290 "Define a Source IP Address\n"
1291 "Preference of the cache server\n"
1292 "Preference value\n")
1294 struct cache
*cache_p
= find_cache(preference
);
1297 vty_out(vty
, "Could not find cache with preference %ld\n",
1302 if (is_running() && listcount(cache_list
) == 1) {
1304 } else if (is_running()) {
1305 if (rtr_mgr_remove_group(rtr_config
, preference
) == RTR_ERROR
) {
1307 "Could not remove cache with preference %ld\n",
1313 listnode_delete(cache_list
, cache_p
);
1314 free_cache(cache_p
);
1319 DEFPY (show_rpki_prefix_table
,
1320 show_rpki_prefix_table_cmd
,
1321 "show rpki prefix-table [json$uj]",
1324 "Show validated prefixes which were received from RPKI Cache\n"
1327 struct json_object
*json
= NULL
;
1329 if (!is_synchronized()) {
1331 vty_out(vty
, "No connection to RPKI cache server.\n");
1336 json
= json_object_new_object();
1338 print_prefix_table(vty
, json
);
1342 DEFPY (show_rpki_as_number
,
1343 show_rpki_as_number_cmd
,
1344 "show rpki as-number ASNUM$by_asn [json$uj]",
1347 "Lookup by ASN in prefix table\n"
1351 struct json_object
*json
= NULL
;
1353 if (!is_synchronized()) {
1355 vty_out(vty
, "No Connection to RPKI cache server.\n");
1360 json
= json_object_new_object();
1362 print_prefix_table_by_asn(vty
, by_asn
, json
);
1366 DEFPY (show_rpki_prefix
,
1367 show_rpki_prefix_cmd
,
1368 "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [ASNUM$asn] [json$uj]",
1371 "Lookup IP prefix and optionally ASN in prefix table\n"
1377 json_object
*json
= NULL
;
1378 json_object
*json_records
= NULL
;
1379 enum asnotation_mode asnotation
;
1381 if (!is_synchronized()) {
1383 vty_out(vty
, "No Connection to RPKI cache server.\n");
1387 struct lrtr_ip_addr addr
;
1388 char addr_str
[INET6_ADDRSTRLEN
];
1389 size_t addr_len
= strchr(prefix_str
, '/') - prefix_str
;
1391 memset(addr_str
, 0, sizeof(addr_str
));
1392 memcpy(addr_str
, prefix_str
, addr_len
);
1394 if (lrtr_ip_str_to_addr(addr_str
, &addr
) != 0) {
1396 vty_out(vty
, "Invalid IP prefix\n");
1400 struct pfx_record
*matches
= NULL
;
1401 unsigned int match_count
= 0;
1402 enum pfxv_state result
;
1404 if (pfx_table_validate_r(rtr_config
->pfx_table
, &matches
, &match_count
,
1405 asn
, &addr
, prefix
->prefixlen
,
1406 &result
) != PFX_SUCCESS
) {
1408 vty_out(vty
, "Prefix lookup failed\n");
1413 json
= json_object_new_object();
1416 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length",
1419 json_records
= json_object_new_array();
1420 json_object_object_add(json
, "prefixes", json_records
);
1423 asnotation
= bgp_get_asnotation(bgp_lookup_by_vrf_id(VRF_DEFAULT
));
1424 for (size_t i
= 0; i
< match_count
; ++i
) {
1425 const struct pfx_record
*record
= &matches
[i
];
1427 if (record
->max_len
>= prefix
->prefixlen
&&
1428 ((asn
!= 0 && (uint32_t)asn
== record
->asn
) || asn
== 0)) {
1429 print_record(&matches
[i
], vty
, json_records
,
1435 vty_json(vty
, json
);
1440 DEFPY (show_rpki_cache_server
,
1441 show_rpki_cache_server_cmd
,
1442 "show rpki cache-server [json$uj]",
1445 "Show configured cache server\n"
1448 struct json_object
*json
= NULL
;
1449 struct json_object
*json_server
= NULL
;
1450 struct json_object
*json_servers
= NULL
;
1451 struct listnode
*cache_node
;
1452 struct cache
*cache
;
1455 json
= json_object_new_object();
1456 json_servers
= json_object_new_array();
1457 json_object_object_add(json
, "servers", json_servers
);
1460 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1461 if (cache
->type
== TCP
) {
1464 "host: %s port: %s, preference: %hhu\n",
1465 cache
->tr_config
.tcp_config
->host
,
1466 cache
->tr_config
.tcp_config
->port
,
1469 json_server
= json_object_new_object();
1470 json_object_string_add(json_server
, "mode",
1472 json_object_string_add(
1473 json_server
, "host",
1474 cache
->tr_config
.tcp_config
->host
);
1475 json_object_string_add(
1476 json_server
, "port",
1477 cache
->tr_config
.tcp_config
->port
);
1478 json_object_int_add(json_server
, "preference",
1480 json_object_array_add(json_servers
,
1484 #if defined(FOUND_SSH)
1485 } else if (cache
->type
== SSH
) {
1488 "host: %s port: %d username: %s server_hostkey_path: %s client_privkey_path: %s, preference: %hhu\n",
1489 cache
->tr_config
.ssh_config
->host
,
1490 cache
->tr_config
.ssh_config
->port
,
1491 cache
->tr_config
.ssh_config
->username
,
1492 cache
->tr_config
.ssh_config
1493 ->server_hostkey_path
,
1494 cache
->tr_config
.ssh_config
1495 ->client_privkey_path
,
1498 json_server
= json_object_new_object();
1499 json_object_string_add(json_server
, "mode",
1501 json_object_string_add(
1502 json_server
, "host",
1503 cache
->tr_config
.ssh_config
->host
);
1504 json_object_int_add(
1505 json_server
, "port",
1506 cache
->tr_config
.ssh_config
->port
);
1507 json_object_string_add(
1508 json_server
, "username",
1509 cache
->tr_config
.ssh_config
->username
);
1510 json_object_string_add(
1511 json_server
, "serverHostkeyPath",
1512 cache
->tr_config
.ssh_config
1513 ->server_hostkey_path
);
1514 json_object_string_add(
1515 json_server
, "clientPrivkeyPath",
1516 cache
->tr_config
.ssh_config
1517 ->client_privkey_path
);
1518 json_object_int_add(json_server
, "preference",
1520 json_object_array_add(json_servers
,
1528 vty_json(vty
, json
);
1533 DEFPY (show_rpki_cache_connection
,
1534 show_rpki_cache_connection_cmd
,
1535 "show rpki cache-connection [json$uj]",
1538 "Show to which RPKI Cache Servers we have a connection\n"
1541 struct json_object
*json
= NULL
;
1542 struct json_object
*json_conn
= NULL
;
1543 struct json_object
*json_conns
= NULL
;
1544 struct listnode
*cache_node
;
1545 struct cache
*cache
;
1546 struct rtr_mgr_group
*group
;
1549 json
= json_object_new_object();
1551 if (!is_synchronized()) {
1553 vty_out(vty
, "No connection to RPKI cache server.\n");
1555 vty_json(vty
, json
);
1560 group
= get_connected_group();
1563 vty_out(vty
, "Cannot find a connected group.\n");
1565 vty_json(vty
, json
);
1571 vty_out(vty
, "Connected to group %d\n", group
->preference
);
1573 json_conns
= json_object_new_array();
1574 json_object_int_add(json
, "connectedGroup", group
->preference
);
1575 json_object_object_add(json
, "connections", json_conns
);
1578 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1579 struct tr_tcp_config
*tcp_config
;
1580 #if defined(FOUND_SSH)
1581 struct tr_ssh_config
*ssh_config
;
1583 switch (cache
->type
) {
1585 tcp_config
= cache
->tr_config
.tcp_config
;
1589 "rpki tcp cache %s %s pref %hhu%s\n",
1590 tcp_config
->host
, tcp_config
->port
,
1592 cache
->rtr_socket
->state
==
1597 json_conn
= json_object_new_object();
1598 json_object_string_add(json_conn
, "mode",
1600 json_object_string_add(json_conn
, "host",
1602 json_object_string_add(json_conn
, "port",
1604 json_object_int_add(json_conn
, "preference",
1606 json_object_string_add(
1608 cache
->rtr_socket
->state
==
1612 json_object_array_add(json_conns
, json_conn
);
1615 #if defined(FOUND_SSH)
1617 ssh_config
= cache
->tr_config
.ssh_config
;
1621 "rpki ssh cache %s %u pref %hhu%s\n",
1622 ssh_config
->host
, ssh_config
->port
,
1624 cache
->rtr_socket
->state
==
1629 json_conn
= json_object_new_object();
1630 json_object_string_add(json_conn
, "mode",
1632 json_object_string_add(json_conn
, "host",
1634 json_object_int_add(json_conn
, "port",
1636 json_object_int_add(json_conn
, "preference",
1638 json_object_string_add(
1640 cache
->rtr_socket
->state
==
1644 json_object_array_add(json_conns
, json_conn
);
1654 vty_json(vty
, json
);
1659 static int config_on_exit(struct vty
*vty
)
1671 return reset(true) == SUCCESS
? CMD_SUCCESS
: CMD_WARNING
;
1678 "Enable debugging for rpki\n")
1684 DEFUN (no_debug_rpki
,
1689 "Disable debugging for rpki\n")
1695 DEFUN_YANG (match_rpki
,
1697 "match rpki <valid|invalid|notfound>",
1702 "Prefix not found\n")
1705 "./match-condition[condition='frr-bgp-route-map:rpki']";
1706 char xpath_value
[XPATH_MAXLEN
];
1708 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
1709 snprintf(xpath_value
, sizeof(xpath_value
),
1710 "%s/rmap-match-condition/frr-bgp-route-map:rpki", xpath
);
1711 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, argv
[2]->arg
);
1713 return nb_cli_apply_changes(vty
, NULL
);
1716 DEFUN_YANG (no_match_rpki
,
1718 "no match rpki <valid|invalid|notfound>",
1724 "Prefix not found\n")
1727 "./match-condition[condition='frr-bgp-route-map:rpki']";
1729 nb_cli_enqueue_change(vty
, xpath
, NB_OP_DESTROY
, NULL
);
1730 return nb_cli_apply_changes(vty
, NULL
);
1733 static void install_cli_commands(void)
1735 // TODO: make config write work
1736 install_node(&rpki_node
);
1737 install_default(RPKI_NODE
);
1738 install_element(CONFIG_NODE
, &rpki_cmd
);
1739 install_element(ENABLE_NODE
, &rpki_cmd
);
1740 install_element(CONFIG_NODE
, &no_rpki_cmd
);
1743 install_element(ENABLE_NODE
, &bgp_rpki_start_cmd
);
1744 install_element(ENABLE_NODE
, &bgp_rpki_stop_cmd
);
1746 /* Install rpki reset command */
1747 install_element(ENABLE_NODE
, &rpki_reset_cmd
);
1748 install_element(RPKI_NODE
, &rpki_reset_cmd
);
1750 /* Install rpki polling period commands */
1751 install_element(RPKI_NODE
, &rpki_polling_period_cmd
);
1752 install_element(RPKI_NODE
, &no_rpki_polling_period_cmd
);
1754 /* Install rpki expire interval commands */
1755 install_element(RPKI_NODE
, &rpki_expire_interval_cmd
);
1756 install_element(RPKI_NODE
, &no_rpki_expire_interval_cmd
);
1758 /* Install rpki retry interval commands */
1759 install_element(RPKI_NODE
, &rpki_retry_interval_cmd
);
1760 install_element(RPKI_NODE
, &no_rpki_retry_interval_cmd
);
1762 /* Install rpki cache commands */
1763 install_element(RPKI_NODE
, &rpki_cache_cmd
);
1764 install_element(RPKI_NODE
, &no_rpki_cache_cmd
);
1766 /* Install show commands */
1767 install_element(VIEW_NODE
, &show_rpki_prefix_table_cmd
);
1768 install_element(VIEW_NODE
, &show_rpki_cache_connection_cmd
);
1769 install_element(VIEW_NODE
, &show_rpki_cache_server_cmd
);
1770 install_element(VIEW_NODE
, &show_rpki_prefix_cmd
);
1771 install_element(VIEW_NODE
, &show_rpki_as_number_cmd
);
1773 /* Install debug commands */
1774 install_element(CONFIG_NODE
, &debug_rpki_cmd
);
1775 install_element(ENABLE_NODE
, &debug_rpki_cmd
);
1776 install_element(CONFIG_NODE
, &no_debug_rpki_cmd
);
1777 install_element(ENABLE_NODE
, &no_debug_rpki_cmd
);
1779 /* Install route match */
1780 route_map_install_match(&route_match_rpki_cmd
);
1781 install_element(RMAP_NODE
, &match_rpki_cmd
);
1782 install_element(RMAP_NODE
, &no_match_rpki_cmd
);
1785 FRR_MODULE_SETUP(.name
= "bgpd_rpki", .version
= "0.3.6",
1786 .description
= "Enable RPKI support for FRR.",
1787 .init
= bgp_rpki_module_init
,