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 "lib/network.h"
51 #include "lib/thread.h"
52 #ifndef VTYSH_EXTRACT_PL
53 #include "rtrlib/rtrlib.h"
59 #ifndef VTYSH_EXTRACT_PL
60 #include "bgpd/bgp_rpki_clippy.c"
63 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_CACHE
, "BGP RPKI Cache server")
64 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_CACHE_GROUP
, "BGP RPKI Cache server group")
67 #define RPKI_NOTFOUND 2
68 #define RPKI_INVALID 3
70 #define POLLING_PERIOD_DEFAULT 3600
71 #define EXPIRE_INTERVAL_DEFAULT 7200
72 #define RETRY_INTERVAL_DEFAULT 600
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
;
100 static int start(void);
101 static void stop(void);
102 static int reset(bool force
);
103 static struct rtr_mgr_group
*get_connected_group(void);
104 static void print_prefix_table(struct vty
*vty
);
105 static void install_cli_commands(void);
106 static int config_write(struct vty
*vty
);
107 static int config_on_exit(struct vty
*vty
);
108 static void free_cache(struct cache
*cache
);
109 static struct rtr_mgr_group
*get_groups(void);
110 #if defined(FOUND_SSH)
111 static int add_ssh_cache(const char *host
, const unsigned int port
,
112 const char *username
, const char *client_privkey_path
,
113 const char *client_pubkey_path
,
114 const char *server_pubkey_path
,
115 const uint8_t preference
);
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 int add_tcp_cache(const char *host
, const char *port
,
120 const uint8_t preference
);
121 static void print_record(const struct pfx_record
*record
, struct vty
*vty
);
122 static int is_synchronized(void);
123 static int is_running(void);
124 static void route_match_free(void *rule
);
125 static enum route_map_cmd_result_t
route_match(void *rule
,
126 const struct prefix
*prefix
,
127 route_map_object_t type
,
129 static void *route_match_compile(const char *arg
);
130 static void revalidate_bgp_node(struct bgp_dest
*dest
, afi_t afi
, safi_t safi
);
131 static void revalidate_all_routes(void);
133 static struct rtr_mgr_config
*rtr_config
;
134 static struct list
*cache_list
;
135 static int rtr_is_running
;
136 static int rtr_is_stopping
;
137 static _Atomic
int rtr_update_overflow
;
138 static int rpki_debug
;
139 static unsigned int polling_period
;
140 static unsigned int expire_interval
;
141 static unsigned int retry_interval
;
142 static int rpki_sync_socket_rtr
;
143 static int rpki_sync_socket_bgpd
;
145 static struct cmd_node rpki_node
= {
148 .parent_node
= CONFIG_NODE
,
149 .prompt
= "%s(config-rpki)# ",
150 .config_write
= config_write
,
151 .node_exit
= config_on_exit
,
153 static const struct route_map_rule_cmd route_match_rpki_cmd
= {
154 "rpki", route_match
, route_match_compile
, route_match_free
};
156 static void *malloc_wrapper(size_t size
)
158 return XMALLOC(MTYPE_BGP_RPKI_CACHE
, size
);
161 static void *realloc_wrapper(void *ptr
, size_t size
)
163 return XREALLOC(MTYPE_BGP_RPKI_CACHE
, ptr
, size
);
166 static void free_wrapper(void *ptr
)
168 XFREE(MTYPE_BGP_RPKI_CACHE
, ptr
);
171 static void init_tr_socket(struct cache
*cache
)
173 if (cache
->type
== TCP
)
174 tr_tcp_init(cache
->tr_config
.tcp_config
,
176 #if defined(FOUND_SSH)
178 tr_ssh_init(cache
->tr_config
.ssh_config
,
183 static void free_tr_socket(struct cache
*cache
)
185 if (cache
->type
== TCP
)
186 tr_tcp_init(cache
->tr_config
.tcp_config
,
188 #if defined(FOUND_SSH)
190 tr_ssh_init(cache
->tr_config
.ssh_config
,
195 static int rpki_validate_prefix(struct peer
*peer
, struct attr
*attr
,
196 const struct prefix
*prefix
);
198 static void ipv6_addr_to_network_byte_order(const uint32_t *src
, uint32_t *dest
)
202 for (i
= 0; i
< 4; i
++)
203 dest
[i
] = htonl(src
[i
]);
206 static void ipv6_addr_to_host_byte_order(const uint32_t *src
, uint32_t *dest
)
210 for (i
= 0; i
< 4; i
++)
211 dest
[i
] = ntohl(src
[i
]);
214 static enum route_map_cmd_result_t
route_match(void *rule
,
215 const struct prefix
*prefix
,
216 route_map_object_t type
,
219 int *rpki_status
= rule
;
220 struct bgp_path_info
*path
;
222 if (type
== RMAP_BGP
) {
225 if (rpki_validate_prefix(path
->peer
, path
->attr
, prefix
)
233 static void *route_match_compile(const char *arg
)
237 rpki_status
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(int));
239 if (strcmp(arg
, "valid") == 0)
240 *rpki_status
= RPKI_VALID
;
241 else if (strcmp(arg
, "invalid") == 0)
242 *rpki_status
= RPKI_INVALID
;
244 *rpki_status
= RPKI_NOTFOUND
;
249 static void route_match_free(void *rule
)
251 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
254 static struct rtr_socket
*create_rtr_socket(struct tr_socket
*tr_socket
)
256 struct rtr_socket
*rtr_socket
=
257 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct rtr_socket
));
258 rtr_socket
->tr_socket
= tr_socket
;
262 static struct cache
*find_cache(const uint8_t preference
)
264 struct listnode
*cache_node
;
267 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
268 if (cache
->preference
== preference
)
274 static void print_record(const struct pfx_record
*record
, struct vty
*vty
)
276 char ip
[INET6_ADDRSTRLEN
];
278 lrtr_ip_addr_to_str(&record
->prefix
, ip
, sizeof(ip
));
279 vty_out(vty
, "%-40s %3u - %3u %10u\n", ip
, record
->min_len
,
280 record
->max_len
, record
->asn
);
283 static void print_record_by_asn(const struct pfx_record
*record
, void *data
)
285 struct rpki_for_each_record_arg
*arg
= data
;
286 struct vty
*vty
= arg
->vty
;
288 if (record
->asn
== arg
->as
) {
289 (*arg
->prefix_amount
)++;
290 print_record(record
, vty
);
294 static void print_record_cb(const struct pfx_record
*record
, void *data
)
296 struct rpki_for_each_record_arg
*arg
= data
;
297 struct vty
*vty
= arg
->vty
;
299 (*arg
->prefix_amount
)++;
301 print_record(record
, vty
);
304 static struct rtr_mgr_group
*get_groups(void)
306 struct listnode
*cache_node
;
307 struct rtr_mgr_group
*rtr_mgr_groups
;
310 int group_count
= listcount(cache_list
);
312 if (group_count
== 0)
315 rtr_mgr_groups
= XMALLOC(MTYPE_BGP_RPKI_CACHE_GROUP
,
316 group_count
* sizeof(struct rtr_mgr_group
));
320 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
321 rtr_mgr_groups
[i
].sockets
= &cache
->rtr_socket
;
322 rtr_mgr_groups
[i
].sockets_len
= 1;
323 rtr_mgr_groups
[i
].preference
= cache
->preference
;
325 init_tr_socket(cache
);
330 return rtr_mgr_groups
;
333 inline int is_synchronized(void)
335 return rtr_is_running
&& rtr_mgr_conf_in_sync(rtr_config
);
338 inline int is_running(void)
340 return rtr_is_running
;
343 static struct prefix
*pfx_record_to_prefix(struct pfx_record
*record
)
345 struct prefix
*prefix
= prefix_new();
347 prefix
->prefixlen
= record
->min_len
;
349 if (record
->prefix
.ver
== LRTR_IPV4
) {
350 prefix
->family
= AF_INET
;
351 prefix
->u
.prefix4
.s_addr
= htonl(record
->prefix
.u
.addr4
.addr
);
353 prefix
->family
= AF_INET6
;
354 ipv6_addr_to_network_byte_order(record
->prefix
.u
.addr6
.addr
,
355 prefix
->u
.prefix6
.s6_addr32
);
361 static int bgpd_sync_callback(struct thread
*thread
)
364 struct listnode
*node
;
365 struct prefix
*prefix
;
366 struct pfx_record rec
;
368 thread_add_read(bm
->master
, bgpd_sync_callback
, NULL
,
369 rpki_sync_socket_bgpd
, NULL
);
371 if (atomic_load_explicit(&rtr_update_overflow
, memory_order_seq_cst
)) {
372 while (read(rpki_sync_socket_bgpd
, &rec
,
373 sizeof(struct pfx_record
))
377 atomic_store_explicit(&rtr_update_overflow
, 0,
378 memory_order_seq_cst
);
379 revalidate_all_routes();
384 read(rpki_sync_socket_bgpd
, &rec
, sizeof(struct pfx_record
));
385 if (retval
!= sizeof(struct pfx_record
)) {
386 RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd");
389 prefix
= pfx_record_to_prefix(&rec
);
391 afi_t afi
= (rec
.prefix
.ver
== LRTR_IPV4
) ? AFI_IP
: AFI_IP6
;
393 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
395 struct listnode
*peer_listnode
;
397 for (ALL_LIST_ELEMENTS_RO(bgp
->peer
, peer_listnode
, peer
)) {
400 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
401 if (!peer
->bgp
->rib
[afi
][safi
])
404 struct bgp_dest
*match
;
405 struct bgp_dest
*node
;
407 match
= bgp_table_subtree_lookup(
408 peer
->bgp
->rib
[afi
][safi
], prefix
);
412 if (bgp_dest_has_bgp_path_info_data(
414 revalidate_bgp_node(node
, afi
,
418 node
= bgp_route_next_until(node
,
425 prefix_free(&prefix
);
429 static void revalidate_bgp_node(struct bgp_dest
*bgp_dest
, afi_t afi
,
432 struct bgp_adj_in
*ain
;
434 for (ain
= bgp_dest
->adj_in
; ain
; ain
= ain
->next
) {
436 struct bgp_path_info
*path
=
437 bgp_dest_get_bgp_path_info(bgp_dest
);
438 mpls_label_t
*label
= NULL
;
439 uint32_t num_labels
= 0;
441 if (path
&& path
->extra
) {
442 label
= path
->extra
->label
;
443 num_labels
= path
->extra
->num_labels
;
445 ret
= bgp_update(ain
->peer
, bgp_dest_get_prefix(bgp_dest
),
446 ain
->addpath_rx_id
, ain
->attr
, afi
, safi
,
447 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
, label
,
448 num_labels
, 1, NULL
);
455 static void revalidate_all_routes(void)
458 struct listnode
*node
;
460 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
462 struct listnode
*peer_listnode
;
464 for (ALL_LIST_ELEMENTS_RO(bgp
->peer
, peer_listnode
, peer
)) {
466 for (size_t i
= 0; i
< 2; i
++) {
468 afi_t afi
= (i
== 0) ? AFI_IP
: AFI_IP6
;
470 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
;
472 if (!peer
->bgp
->rib
[afi
][safi
])
475 bgp_soft_reconfig_in(peer
, afi
, safi
);
482 static void rpki_update_cb_sync_rtr(struct pfx_table
*p
__attribute__((unused
)),
483 const struct pfx_record rec
,
484 const bool added
__attribute__((unused
)))
487 || atomic_load_explicit(&rtr_update_overflow
, memory_order_seq_cst
))
491 write(rpki_sync_socket_rtr
, &rec
, sizeof(struct pfx_record
));
492 if (retval
== -1 && (errno
== EAGAIN
|| errno
== EWOULDBLOCK
))
493 atomic_store_explicit(&rtr_update_overflow
, 1,
494 memory_order_seq_cst
);
496 else if (retval
!= sizeof(struct pfx_record
))
497 RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
500 static void rpki_init_sync_socket(void)
505 RPKI_DEBUG("initializing sync socket");
506 if (socketpair(PF_LOCAL
, SOCK_DGRAM
, 0, fds
) != 0) {
507 msg
= "could not open rpki sync socketpair";
510 rpki_sync_socket_rtr
= fds
[0];
511 rpki_sync_socket_bgpd
= fds
[1];
513 if (set_nonblocking(rpki_sync_socket_rtr
) != 0) {
514 msg
= "could not set rpki_sync_socket_rtr to non blocking";
518 if (set_nonblocking(rpki_sync_socket_bgpd
) != 0) {
519 msg
= "could not set rpki_sync_socket_bgpd to non blocking";
524 thread_add_read(bm
->master
, bgpd_sync_callback
, NULL
,
525 rpki_sync_socket_bgpd
, NULL
);
530 zlog_err("RPKI: %s", msg
);
535 static int bgp_rpki_init(struct thread_master
*master
)
541 cache_list
= list_new();
542 cache_list
->del
= (void (*)(void *)) & free_cache
;
544 polling_period
= POLLING_PERIOD_DEFAULT
;
545 expire_interval
= EXPIRE_INTERVAL_DEFAULT
;
546 retry_interval
= RETRY_INTERVAL_DEFAULT
;
547 install_cli_commands();
548 rpki_init_sync_socket();
552 static int bgp_rpki_fini(void)
555 list_delete(&cache_list
);
557 close(rpki_sync_socket_rtr
);
558 close(rpki_sync_socket_bgpd
);
563 static int bgp_rpki_module_init(void)
565 lrtr_set_alloc_functions(malloc_wrapper
, realloc_wrapper
, free_wrapper
);
567 hook_register(frr_late_init
, bgp_rpki_init
);
568 hook_register(frr_early_fini
, &bgp_rpki_fini
);
573 static int start(void)
578 rtr_update_overflow
= 0;
580 if (list_isempty(cache_list
)) {
582 "No caches were found in config. Prefix validation is off.");
585 RPKI_DEBUG("Init rtr_mgr.");
586 int groups_len
= listcount(cache_list
);
587 struct rtr_mgr_group
*groups
= get_groups();
589 RPKI_DEBUG("Polling period: %d", polling_period
);
590 ret
= rtr_mgr_init(&rtr_config
, groups
, groups_len
, polling_period
,
591 expire_interval
, retry_interval
,
592 rpki_update_cb_sync_rtr
, NULL
, NULL
, NULL
);
593 if (ret
== RTR_ERROR
) {
594 RPKI_DEBUG("Init rtr_mgr failed.");
598 RPKI_DEBUG("Starting rtr_mgr.");
599 ret
= rtr_mgr_start(rtr_config
);
600 if (ret
== RTR_ERROR
) {
601 RPKI_DEBUG("Starting rtr_mgr failed.");
602 rtr_mgr_free(rtr_config
);
607 XFREE(MTYPE_BGP_RPKI_CACHE_GROUP
, groups
);
612 static void stop(void)
615 if (rtr_is_running
) {
616 rtr_mgr_stop(rtr_config
);
617 rtr_mgr_free(rtr_config
);
622 static int reset(bool force
)
624 if (rtr_is_running
&& !force
)
627 RPKI_DEBUG("Resetting RPKI Session");
632 static struct rtr_mgr_group
*get_connected_group(void)
634 if (!cache_list
|| list_isempty(cache_list
))
637 return rtr_mgr_get_first_group(rtr_config
);
640 static void print_prefix_table_by_asn(struct vty
*vty
, as_t as
)
642 unsigned int number_of_ipv4_prefixes
= 0;
643 unsigned int number_of_ipv6_prefixes
= 0;
644 struct rtr_mgr_group
*group
= get_connected_group();
645 struct rpki_for_each_record_arg arg
;
651 vty_out(vty
, "Cannot find a connected group.\n");
655 struct pfx_table
*pfx_table
= group
->sockets
[0]->pfx_table
;
657 vty_out(vty
, "RPKI/RTR prefix table\n");
658 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
660 arg
.prefix_amount
= &number_of_ipv4_prefixes
;
661 pfx_table_for_each_ipv4_record(pfx_table
, print_record_by_asn
, &arg
);
663 arg
.prefix_amount
= &number_of_ipv6_prefixes
;
664 pfx_table_for_each_ipv6_record(pfx_table
, print_record_by_asn
, &arg
);
666 vty_out(vty
, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes
);
667 vty_out(vty
, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes
);
670 static void print_prefix_table(struct vty
*vty
)
672 struct rpki_for_each_record_arg arg
;
674 unsigned int number_of_ipv4_prefixes
= 0;
675 unsigned int number_of_ipv6_prefixes
= 0;
676 struct rtr_mgr_group
*group
= get_connected_group();
683 struct pfx_table
*pfx_table
= group
->sockets
[0]->pfx_table
;
685 vty_out(vty
, "RPKI/RTR prefix table\n");
686 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
688 arg
.prefix_amount
= &number_of_ipv4_prefixes
;
689 pfx_table_for_each_ipv4_record(pfx_table
, print_record_cb
, &arg
);
691 arg
.prefix_amount
= &number_of_ipv6_prefixes
;
692 pfx_table_for_each_ipv6_record(pfx_table
, print_record_cb
, &arg
);
694 vty_out(vty
, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes
);
695 vty_out(vty
, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes
);
698 static int rpki_validate_prefix(struct peer
*peer
, struct attr
*attr
,
699 const struct prefix
*prefix
)
701 struct assegment
*as_segment
;
703 struct lrtr_ip_addr ip_addr_prefix
;
704 enum pfxv_state result
;
706 if (!is_synchronized())
709 // No aspath means route comes from iBGP
710 if (!attr
->aspath
|| !attr
->aspath
->segments
) {
712 as_number
= peer
->bgp
->as
;
714 as_segment
= attr
->aspath
->segments
;
715 // Find last AsSegment
716 while (as_segment
->next
)
717 as_segment
= as_segment
->next
;
719 if (as_segment
->type
== AS_SEQUENCE
) {
721 as_number
= as_segment
->as
[as_segment
->length
- 1];
722 } else if (as_segment
->type
== AS_CONFED_SEQUENCE
723 || as_segment
->type
== AS_CONFED_SET
) {
725 as_number
= peer
->bgp
->as
;
727 // RFC says: "Take distinguished value NONE as asn"
728 // which means state is unknown
729 return RPKI_NOTFOUND
;
733 // Get the prefix in requested format
734 switch (prefix
->family
) {
736 ip_addr_prefix
.ver
= LRTR_IPV4
;
737 ip_addr_prefix
.u
.addr4
.addr
= ntohl(prefix
->u
.prefix4
.s_addr
);
741 ip_addr_prefix
.ver
= LRTR_IPV6
;
742 ipv6_addr_to_host_byte_order(prefix
->u
.prefix6
.s6_addr32
,
743 ip_addr_prefix
.u
.addr6
.addr
);
750 // Do the actual validation
751 rtr_mgr_validate(rtr_config
, as_number
, &ip_addr_prefix
,
752 prefix
->prefixlen
, &result
);
754 // Print Debug output
756 case BGP_PFXV_STATE_VALID
:
758 "Validating Prefix %pFX from asn %u Result: VALID",
761 case BGP_PFXV_STATE_NOT_FOUND
:
763 "Validating Prefix %pFX from asn %u Result: NOT FOUND",
765 return RPKI_NOTFOUND
;
766 case BGP_PFXV_STATE_INVALID
:
768 "Validating Prefix %pFX from asn %u Result: INVALID",
773 "Validating Prefix %pFX from asn %u Result: CANNOT VALIDATE",
780 static int add_cache(struct cache
*cache
)
782 uint8_t preference
= cache
->preference
;
783 struct rtr_mgr_group group
;
785 group
.preference
= preference
;
786 group
.sockets_len
= 1;
787 group
.sockets
= &cache
->rtr_socket
;
789 if (rtr_is_running
) {
790 init_tr_socket(cache
);
792 if (rtr_mgr_add_group(rtr_config
, &group
) != RTR_SUCCESS
) {
793 free_tr_socket(cache
);
798 listnode_add(cache_list
, cache
);
803 static int add_tcp_cache(const char *host
, const char *port
,
804 const uint8_t preference
)
806 struct rtr_socket
*rtr_socket
;
807 struct tr_tcp_config
*tcp_config
=
808 XCALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_tcp_config
));
809 struct tr_socket
*tr_socket
=
810 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_socket
));
811 struct cache
*cache
=
812 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct cache
));
814 tcp_config
->host
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, host
);
815 tcp_config
->port
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, port
);
816 tcp_config
->bindaddr
= NULL
;
818 rtr_socket
= create_rtr_socket(tr_socket
);
821 cache
->tr_socket
= tr_socket
;
822 cache
->tr_config
.tcp_config
= tcp_config
;
823 cache
->rtr_socket
= rtr_socket
;
824 cache
->preference
= preference
;
826 int ret
= add_cache(cache
);
827 if (ret
!= SUCCESS
) {
834 #if defined(FOUND_SSH)
835 static int add_ssh_cache(const char *host
, const unsigned int port
,
836 const char *username
, const char *client_privkey_path
,
837 const char *client_pubkey_path
,
838 const char *server_pubkey_path
,
839 const uint8_t preference
)
841 struct tr_ssh_config
*ssh_config
=
842 XCALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_ssh_config
));
843 struct cache
*cache
=
844 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct cache
));
845 struct tr_socket
*tr_socket
=
846 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_socket
));
847 struct rtr_socket
*rtr_socket
;
849 ssh_config
->port
= port
;
850 ssh_config
->host
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, host
);
851 ssh_config
->bindaddr
= NULL
;
853 ssh_config
->username
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, username
);
854 ssh_config
->client_privkey_path
=
855 XSTRDUP(MTYPE_BGP_RPKI_CACHE
, client_privkey_path
);
856 ssh_config
->server_hostkey_path
=
857 XSTRDUP(MTYPE_BGP_RPKI_CACHE
, server_pubkey_path
);
859 rtr_socket
= create_rtr_socket(tr_socket
);
862 cache
->tr_socket
= tr_socket
;
863 cache
->tr_config
.ssh_config
= ssh_config
;
864 cache
->rtr_socket
= rtr_socket
;
865 cache
->preference
= preference
;
867 int ret
= add_cache(cache
);
868 if (ret
!= SUCCESS
) {
876 static void free_cache(struct cache
*cache
)
878 if (cache
->type
== TCP
) {
879 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
->host
);
880 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
->port
);
881 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
);
883 #if defined(FOUND_SSH)
885 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.ssh_config
->host
);
886 XFREE(MTYPE_BGP_RPKI_CACHE
,
887 cache
->tr_config
.ssh_config
->username
);
888 XFREE(MTYPE_BGP_RPKI_CACHE
,
889 cache
->tr_config
.ssh_config
->client_privkey_path
);
890 XFREE(MTYPE_BGP_RPKI_CACHE
,
891 cache
->tr_config
.ssh_config
->server_hostkey_path
);
892 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.ssh_config
);
895 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_socket
);
896 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->rtr_socket
);
897 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
);
900 static int config_write(struct vty
*vty
)
902 struct listnode
*cache_node
;
905 if (listcount(cache_list
)) {
907 vty_out(vty
, "debug rpki\n");
910 vty_out(vty
, "rpki\n");
911 vty_out(vty
, " rpki polling_period %d\n", polling_period
);
912 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
913 switch (cache
->type
) {
914 struct tr_tcp_config
*tcp_config
;
915 #if defined(FOUND_SSH)
916 struct tr_ssh_config
*ssh_config
;
919 tcp_config
= cache
->tr_config
.tcp_config
;
920 vty_out(vty
, " rpki cache %s %s ",
921 tcp_config
->host
, tcp_config
->port
);
923 #if defined(FOUND_SSH)
925 ssh_config
= cache
->tr_config
.ssh_config
;
926 vty_out(vty
, " rpki cache %s %u %s %s %s ",
927 ssh_config
->host
, ssh_config
->port
,
928 ssh_config
->username
,
929 ssh_config
->client_privkey_path
,
930 ssh_config
->server_hostkey_path
!= NULL
932 ->server_hostkey_path
940 vty_out(vty
, "preference %hhu\n", cache
->preference
);
942 vty_out(vty
, " exit\n");
952 "Enable rpki and enter rpki configuration mode\n")
954 vty
->node
= RPKI_NODE
;
958 DEFUN (bgp_rpki_start
,
962 "start rpki support\n")
964 if (listcount(cache_list
) == 0)
966 "Could not start rpki because no caches are configured\n");
969 if (start() == ERROR
) {
970 RPKI_DEBUG("RPKI failed to start");
977 DEFUN (bgp_rpki_stop
,
981 "start rpki support\n")
989 DEFPY (rpki_polling_period
,
990 rpki_polling_period_cmd
,
991 "rpki polling_period (1-86400)$pp",
993 "Set polling period\n"
994 "Polling period value\n")
1000 DEFUN (no_rpki_polling_period
,
1001 no_rpki_polling_period_cmd
,
1002 "no rpki polling_period",
1005 "Set polling period back to default\n")
1007 polling_period
= POLLING_PERIOD_DEFAULT
;
1011 DEFPY (rpki_expire_interval
,
1012 rpki_expire_interval_cmd
,
1013 "rpki expire_interval (600-172800)$tmp",
1015 "Set expire interval\n"
1016 "Expire interval value\n")
1018 if ((unsigned int)tmp
>= polling_period
) {
1019 expire_interval
= tmp
;
1023 vty_out(vty
, "%% Expiry interval must be polling period or larger\n");
1024 return CMD_WARNING_CONFIG_FAILED
;
1027 DEFUN (no_rpki_expire_interval
,
1028 no_rpki_expire_interval_cmd
,
1029 "no rpki expire_interval",
1032 "Set expire interval back to default\n")
1034 expire_interval
= polling_period
* 2;
1038 DEFPY (rpki_retry_interval
,
1039 rpki_retry_interval_cmd
,
1040 "rpki retry_interval (1-7200)$tmp",
1042 "Set retry interval\n"
1043 "retry interval value\n")
1045 retry_interval
= tmp
;
1049 DEFUN (no_rpki_retry_interval
,
1050 no_rpki_retry_interval_cmd
,
1051 "no rpki retry_interval",
1054 "Set retry interval back to default\n")
1056 retry_interval
= RETRY_INTERVAL_DEFAULT
;
1062 "rpki cache <A.B.C.D|WORD><TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY SSH_PUBKEY [SERVER_PUBKEY]> preference (1-255)",
1064 "Install a cache server to current group\n"
1065 "IP address of cache server\n Hostname of cache server\n"
1069 "Path to own SSH private key\n"
1070 "Path to own SSH public key\n"
1071 "Path to Public key of cache server\n"
1072 "Preference of the cache server\n"
1073 "Preference value\n")
1076 struct listnode
*cache_node
;
1077 struct cache
*current_cache
;
1079 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, current_cache
)) {
1080 if (current_cache
->preference
== preference
) {
1082 "Cache with preference %ld is already configured\n",
1089 // use ssh connection
1091 #if defined(FOUND_SSH)
1093 add_ssh_cache(cache
, sshport
, ssh_uname
, ssh_privkey
,
1094 ssh_pubkey
, server_pubkey
, preference
);
1096 return_value
= SUCCESS
;
1098 "ssh sockets are not supported. Please recompile rtrlib and frr with ssh support. If you want to use it\n");
1100 } else { // use tcp connection
1101 return_value
= add_tcp_cache(cache
, tcpport
, preference
);
1104 if (return_value
== ERROR
) {
1105 vty_out(vty
, "Could not create new rpki cache\n");
1112 DEFPY (no_rpki_cache
,
1114 "no rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport> preference (1-255)$preference",
1117 "Remove a cache server\n"
1118 "IP address of cache server\n Hostname of cache server\n"
1121 "Preference of the cache server\n"
1122 "Preference value\n")
1124 struct cache
*cache_p
= find_cache(preference
);
1127 vty_out(vty
, "Could not find cache %ld\n", preference
);
1131 if (rtr_is_running
&& listcount(cache_list
) == 1) {
1133 } else if (rtr_is_running
) {
1134 if (rtr_mgr_remove_group(rtr_config
, preference
) == RTR_ERROR
) {
1135 vty_out(vty
, "Could not remove cache %ld", preference
);
1142 listnode_delete(cache_list
, cache_p
);
1143 free_cache(cache_p
);
1148 DEFUN (show_rpki_prefix_table
,
1149 show_rpki_prefix_table_cmd
,
1150 "show rpki prefix-table",
1153 "Show validated prefixes which were received from RPKI Cache\n")
1155 struct listnode
*cache_node
;
1156 struct cache
*cache
;
1158 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1159 vty_out(vty
, "host: %s port: %s\n",
1160 cache
->tr_config
.tcp_config
->host
,
1161 cache
->tr_config
.tcp_config
->port
);
1163 if (is_synchronized())
1164 print_prefix_table(vty
);
1166 vty_out(vty
, "No connection to RPKI cache server.\n");
1171 DEFPY(show_rpki_as_number
, show_rpki_as_number_cmd
,
1172 "show rpki as-number (1-4294967295)$by_asn",
1173 SHOW_STR RPKI_OUTPUT_STRING
1174 "Lookup by ASN in prefix table\n"
1177 if (!is_synchronized()) {
1178 vty_out(vty
, "No Connection to RPKI cache server.\n");
1182 print_prefix_table_by_asn(vty
, by_asn
);
1186 DEFPY (show_rpki_prefix
,
1187 show_rpki_prefix_cmd
,
1188 "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn]",
1191 "Lookup IP prefix and optionally ASN in prefix table\n"
1197 if (!is_synchronized()) {
1198 vty_out(vty
, "No Connection to RPKI cache server.\n");
1202 struct lrtr_ip_addr addr
;
1203 char addr_str
[INET6_ADDRSTRLEN
];
1204 size_t addr_len
= strchr(prefix_str
, '/') - prefix_str
;
1206 memset(addr_str
, 0, sizeof(addr_str
));
1207 memcpy(addr_str
, prefix_str
, addr_len
);
1209 if (lrtr_ip_str_to_addr(addr_str
, &addr
) != 0) {
1210 vty_out(vty
, "Invalid IP prefix\n");
1214 struct pfx_record
*matches
= NULL
;
1215 unsigned int match_count
= 0;
1216 enum pfxv_state result
;
1218 if (pfx_table_validate_r(rtr_config
->pfx_table
, &matches
, &match_count
,
1219 asn
, &addr
, prefix
->prefixlen
, &result
)
1221 vty_out(vty
, "Prefix lookup failed");
1225 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
1226 for (size_t i
= 0; i
< match_count
; ++i
) {
1227 const struct pfx_record
*record
= &matches
[i
];
1229 if (record
->max_len
>= prefix
->prefixlen
1230 && ((asn
!= 0 && (uint32_t)asn
== record
->asn
)
1232 print_record(&matches
[i
], vty
);
1239 DEFUN (show_rpki_cache_server
,
1240 show_rpki_cache_server_cmd
,
1241 "show rpki cache-server",
1244 "SHOW configured cache server\n")
1246 struct listnode
*cache_node
;
1247 struct cache
*cache
;
1249 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1250 if (cache
->type
== TCP
) {
1251 vty_out(vty
, "host: %s port: %s\n",
1252 cache
->tr_config
.tcp_config
->host
,
1253 cache
->tr_config
.tcp_config
->port
);
1255 #if defined(FOUND_SSH)
1256 } else if (cache
->type
== SSH
) {
1258 "host: %s port: %d username: %s server_hostkey_path: %s client_privkey_path: %s\n",
1259 cache
->tr_config
.ssh_config
->host
,
1260 cache
->tr_config
.ssh_config
->port
,
1261 cache
->tr_config
.ssh_config
->username
,
1262 cache
->tr_config
.ssh_config
1263 ->server_hostkey_path
,
1264 cache
->tr_config
.ssh_config
1265 ->client_privkey_path
);
1273 DEFUN (show_rpki_cache_connection
,
1274 show_rpki_cache_connection_cmd
,
1275 "show rpki cache-connection",
1278 "Show to which RPKI Cache Servers we have a connection\n")
1280 if (is_synchronized()) {
1281 struct listnode
*cache_node
;
1282 struct cache
*cache
;
1283 struct rtr_mgr_group
*group
= get_connected_group();
1286 vty_out(vty
, "Cannot find a connected group.\n");
1289 vty_out(vty
, "Connected to group %d\n", group
->preference
);
1290 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1291 if (cache
->preference
== group
->preference
) {
1292 struct tr_tcp_config
*tcp_config
;
1293 #if defined(FOUND_SSH)
1294 struct tr_ssh_config
*ssh_config
;
1297 switch (cache
->type
) {
1300 cache
->tr_config
.tcp_config
;
1302 "rpki tcp cache %s %s pref %hhu\n",
1308 #if defined(FOUND_SSH)
1311 cache
->tr_config
.ssh_config
;
1313 "rpki ssh cache %s %u pref %hhu\n",
1326 vty_out(vty
, "No connection to RPKI cache server.\n");
1332 static int config_on_exit(struct vty
*vty
)
1344 return reset(true) == SUCCESS
? CMD_SUCCESS
: CMD_WARNING
;
1351 "Enable debugging for rpki\n")
1357 DEFUN (no_debug_rpki
,
1362 "Disable debugging for rpki\n")
1370 "match rpki <valid|invalid|notfound>",
1375 "Prefix not found\n")
1377 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
1378 enum rmap_compile_rets ret
;
1380 ret
= route_map_add_match(index
, "rpki", argv
[2]->arg
,
1381 RMAP_EVENT_MATCH_ADDED
);
1383 case RMAP_RULE_MISSING
:
1384 vty_out(vty
, "%% BGP Can't find rule.\n");
1385 return CMD_WARNING_CONFIG_FAILED
;
1386 case RMAP_COMPILE_ERROR
:
1387 vty_out(vty
, "%% BGP Argument is malformed.\n");
1388 return CMD_WARNING_CONFIG_FAILED
;
1389 case RMAP_COMPILE_SUCCESS
:
1397 DEFUN (no_match_rpki
,
1399 "no match rpki <valid|invalid|notfound>",
1405 "Prefix not found\n")
1407 VTY_DECLVAR_CONTEXT(route_map_index
, index
);
1408 enum rmap_compile_rets ret
;
1410 ret
= route_map_delete_match(index
, "rpki", argv
[3]->arg
,
1411 RMAP_EVENT_MATCH_DELETED
);
1413 case RMAP_RULE_MISSING
:
1414 vty_out(vty
, "%% BGP Can't find rule.\n");
1415 return CMD_WARNING_CONFIG_FAILED
;
1417 case RMAP_COMPILE_ERROR
:
1418 vty_out(vty
, "%% BGP Argument is malformed.\n");
1419 return CMD_WARNING_CONFIG_FAILED
;
1421 case RMAP_COMPILE_SUCCESS
:
1429 static void install_cli_commands(void)
1431 // TODO: make config write work
1432 install_node(&rpki_node
);
1433 install_default(RPKI_NODE
);
1434 install_element(CONFIG_NODE
, &rpki_cmd
);
1435 install_element(ENABLE_NODE
, &rpki_cmd
);
1437 install_element(ENABLE_NODE
, &bgp_rpki_start_cmd
);
1438 install_element(ENABLE_NODE
, &bgp_rpki_stop_cmd
);
1440 /* Install rpki reset command */
1441 install_element(RPKI_NODE
, &rpki_reset_cmd
);
1443 /* Install rpki polling period commands */
1444 install_element(RPKI_NODE
, &rpki_polling_period_cmd
);
1445 install_element(RPKI_NODE
, &no_rpki_polling_period_cmd
);
1447 /* Install rpki expire interval commands */
1448 install_element(RPKI_NODE
, &rpki_expire_interval_cmd
);
1449 install_element(RPKI_NODE
, &no_rpki_expire_interval_cmd
);
1451 /* Install rpki retry interval commands */
1452 install_element(RPKI_NODE
, &rpki_retry_interval_cmd
);
1453 install_element(RPKI_NODE
, &no_rpki_retry_interval_cmd
);
1455 /* Install rpki cache commands */
1456 install_element(RPKI_NODE
, &rpki_cache_cmd
);
1457 install_element(RPKI_NODE
, &no_rpki_cache_cmd
);
1459 /* Install show commands */
1460 install_element(VIEW_NODE
, &show_rpki_prefix_table_cmd
);
1461 install_element(VIEW_NODE
, &show_rpki_cache_connection_cmd
);
1462 install_element(VIEW_NODE
, &show_rpki_cache_server_cmd
);
1463 install_element(VIEW_NODE
, &show_rpki_prefix_cmd
);
1464 install_element(VIEW_NODE
, &show_rpki_as_number_cmd
);
1466 /* Install debug commands */
1467 install_element(CONFIG_NODE
, &debug_rpki_cmd
);
1468 install_element(ENABLE_NODE
, &debug_rpki_cmd
);
1469 install_element(CONFIG_NODE
, &no_debug_rpki_cmd
);
1470 install_element(ENABLE_NODE
, &no_debug_rpki_cmd
);
1472 /* Install route match */
1473 route_map_install_match(&route_match_rpki_cmd
);
1474 install_element(RMAP_NODE
, &match_rpki_cmd
);
1475 install_element(RMAP_NODE
, &no_match_rpki_cmd
);
1478 FRR_MODULE_SETUP(.name
= "bgpd_rpki", .version
= "0.3.6",
1479 .description
= "Enable RPKI support for FRR.",
1480 .init
= bgp_rpki_module_init
)