3 * Copyright (C) 2013 Michael Mester (m.mester@fu-berlin.de), for FU Berlin
4 * Copyright (C) 2014-2017 Andreas Reuter (andreas.reuter@fu-berlin.de), for FU
6 * Copyright (C) 2016-2017 Colin Sames (colin.sames@haw-hamburg.de), for HAW
8 * Copyright (C) 2017-2018 Marcel Röthke (marcel.roethke@haw-hamburg.de),
11 * This file is part of FRRouting.
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the Free
15 * Software Foundation; either version 2 of the License, or (at your option)
18 * This program is distributed in the hope that it will be useful, but WITHOUT
19 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
23 * You should have received a copy of the GNU General Public License along
24 * with this program; see the file COPYING; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 /* If rtrlib compiled with ssh support, don`t fail build */
29 #define LIBSSH_LEGACY_0_4
43 #include "bgpd/bgpd.h"
44 #include "bgpd/bgp_table.h"
45 #include "bgp_advertise.h"
46 #include "bgpd/bgp_debug.h"
47 #include "bgpd/bgp_attr.h"
48 #include "bgpd/bgp_aspath.h"
49 #include "bgpd/bgp_route.h"
50 #include "bgpd/bgp_rpki.h"
51 #include "northbound_cli.h"
53 #include "lib/network.h"
54 #include "lib/thread.h"
55 #ifndef VTYSH_EXTRACT_PL
56 #include "rtrlib/rtrlib.h"
60 #include "lib/version.h"
62 #ifndef VTYSH_EXTRACT_PL
63 #include "bgpd/bgp_rpki_clippy.c"
66 static struct thread
*t_rpki
;
68 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_CACHE
, "BGP RPKI Cache server");
69 DEFINE_MTYPE_STATIC(BGPD
, BGP_RPKI_CACHE_GROUP
, "BGP RPKI Cache server group");
71 #define POLLING_PERIOD_DEFAULT 3600
72 #define EXPIRE_INTERVAL_DEFAULT 7200
73 #define RETRY_INTERVAL_DEFAULT 600
75 #define RPKI_DEBUG(...) \
77 zlog_debug("RPKI: " __VA_ARGS__); \
80 #define RPKI_OUTPUT_STRING "Control rpki specific settings\n"
83 enum { TCP
, SSH
} type
;
84 struct tr_socket
*tr_socket
;
86 struct tr_tcp_config
*tcp_config
;
87 struct tr_ssh_config
*ssh_config
;
89 struct rtr_socket
*rtr_socket
;
93 enum return_values
{ SUCCESS
= 0, ERROR
= -1 };
95 struct rpki_for_each_record_arg
{
97 unsigned int *prefix_amount
;
101 static int start(void);
102 static void stop(void);
103 static int reset(bool force
);
104 static struct rtr_mgr_group
*get_connected_group(void);
105 static void print_prefix_table(struct vty
*vty
);
106 static void install_cli_commands(void);
107 static int config_write(struct vty
*vty
);
108 static int config_on_exit(struct vty
*vty
);
109 static void free_cache(struct cache
*cache
);
110 static struct rtr_mgr_group
*get_groups(void);
111 #if defined(FOUND_SSH)
112 static int add_ssh_cache(const char *host
, const unsigned int port
,
113 const char *username
, const char *client_privkey_path
,
114 const char *client_pubkey_path
,
115 const char *server_pubkey_path
,
116 const uint8_t preference
, const char *bindaddr
);
118 static struct rtr_socket
*create_rtr_socket(struct tr_socket
*tr_socket
);
119 static struct cache
*find_cache(const uint8_t preference
);
120 static int add_tcp_cache(const char *host
, const char *port
,
121 const uint8_t preference
, const char *bindaddr
);
122 static void print_record(const struct pfx_record
*record
, struct vty
*vty
);
123 static int is_synchronized(void);
124 static int is_running(void);
125 static void route_match_free(void *rule
);
126 static enum route_map_cmd_result_t
route_match(void *rule
,
127 const struct prefix
*prefix
,
130 static void *route_match_compile(const char *arg
);
131 static void revalidate_bgp_node(struct bgp_dest
*dest
, afi_t afi
, safi_t safi
);
132 static void revalidate_all_routes(void);
134 static struct rtr_mgr_config
*rtr_config
;
135 static struct list
*cache_list
;
136 static int rtr_is_running
;
137 static int rtr_is_stopping
;
138 static _Atomic
int rtr_update_overflow
;
139 static int rpki_debug
;
140 static unsigned int polling_period
;
141 static unsigned int expire_interval
;
142 static unsigned int retry_interval
;
143 static int rpki_sync_socket_rtr
;
144 static int rpki_sync_socket_bgpd
;
146 static struct cmd_node rpki_node
= {
149 .parent_node
= CONFIG_NODE
,
150 .prompt
= "%s(config-rpki)# ",
151 .config_write
= config_write
,
152 .node_exit
= config_on_exit
,
154 static const struct route_map_rule_cmd route_match_rpki_cmd
= {
155 "rpki", route_match
, route_match_compile
, route_match_free
};
157 static void *malloc_wrapper(size_t size
)
159 return XMALLOC(MTYPE_BGP_RPKI_CACHE
, size
);
162 static void *realloc_wrapper(void *ptr
, size_t size
)
164 return XREALLOC(MTYPE_BGP_RPKI_CACHE
, ptr
, size
);
167 static void free_wrapper(void *ptr
)
169 XFREE(MTYPE_BGP_RPKI_CACHE
, ptr
);
172 static void init_tr_socket(struct cache
*cache
)
174 if (cache
->type
== TCP
)
175 tr_tcp_init(cache
->tr_config
.tcp_config
,
177 #if defined(FOUND_SSH)
179 tr_ssh_init(cache
->tr_config
.ssh_config
,
184 static void free_tr_socket(struct cache
*cache
)
186 if (cache
->type
== TCP
)
187 tr_tcp_init(cache
->tr_config
.tcp_config
,
189 #if defined(FOUND_SSH)
191 tr_ssh_init(cache
->tr_config
.ssh_config
,
196 static int rpki_validate_prefix(struct peer
*peer
, struct attr
*attr
,
197 const struct prefix
*prefix
);
199 static void ipv6_addr_to_network_byte_order(const uint32_t *src
, uint32_t *dest
)
203 for (i
= 0; i
< 4; i
++)
204 dest
[i
] = htonl(src
[i
]);
207 static void ipv6_addr_to_host_byte_order(const uint32_t *src
, uint32_t *dest
)
211 for (i
= 0; i
< 4; i
++)
212 dest
[i
] = ntohl(src
[i
]);
215 static enum route_map_cmd_result_t
route_match(void *rule
,
216 const struct prefix
*prefix
,
219 int *rpki_status
= rule
;
220 struct bgp_path_info
*path
;
224 if (rpki_validate_prefix(path
->peer
, path
->attr
, prefix
)
232 static void *route_match_compile(const char *arg
)
236 rpki_status
= XMALLOC(MTYPE_ROUTE_MAP_COMPILED
, sizeof(int));
238 if (strcmp(arg
, "valid") == 0)
239 *rpki_status
= RPKI_VALID
;
240 else if (strcmp(arg
, "invalid") == 0)
241 *rpki_status
= RPKI_INVALID
;
243 *rpki_status
= RPKI_NOTFOUND
;
248 static void route_match_free(void *rule
)
250 XFREE(MTYPE_ROUTE_MAP_COMPILED
, rule
);
253 static struct rtr_socket
*create_rtr_socket(struct tr_socket
*tr_socket
)
255 struct rtr_socket
*rtr_socket
=
256 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct rtr_socket
));
257 rtr_socket
->tr_socket
= tr_socket
;
261 static struct cache
*find_cache(const uint8_t preference
)
263 struct listnode
*cache_node
;
266 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
267 if (cache
->preference
== preference
)
273 static void print_record(const struct pfx_record
*record
, struct vty
*vty
)
275 char ip
[INET6_ADDRSTRLEN
];
277 lrtr_ip_addr_to_str(&record
->prefix
, ip
, sizeof(ip
));
278 vty_out(vty
, "%-40s %3u - %3u %10u\n", ip
, record
->min_len
,
279 record
->max_len
, record
->asn
);
282 static void print_record_by_asn(const struct pfx_record
*record
, void *data
)
284 struct rpki_for_each_record_arg
*arg
= data
;
285 struct vty
*vty
= arg
->vty
;
287 if (record
->asn
== arg
->as
) {
288 (*arg
->prefix_amount
)++;
289 print_record(record
, vty
);
293 static void print_record_cb(const struct pfx_record
*record
, void *data
)
295 struct rpki_for_each_record_arg
*arg
= data
;
296 struct vty
*vty
= arg
->vty
;
298 (*arg
->prefix_amount
)++;
300 print_record(record
, vty
);
303 static struct rtr_mgr_group
*get_groups(void)
305 struct listnode
*cache_node
;
306 struct rtr_mgr_group
*rtr_mgr_groups
;
309 int group_count
= listcount(cache_list
);
311 if (group_count
== 0)
314 rtr_mgr_groups
= XMALLOC(MTYPE_BGP_RPKI_CACHE_GROUP
,
315 group_count
* sizeof(struct rtr_mgr_group
));
319 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
320 rtr_mgr_groups
[i
].sockets
= &cache
->rtr_socket
;
321 rtr_mgr_groups
[i
].sockets_len
= 1;
322 rtr_mgr_groups
[i
].preference
= cache
->preference
;
324 init_tr_socket(cache
);
329 return rtr_mgr_groups
;
332 inline int is_synchronized(void)
334 return rtr_is_running
&& rtr_mgr_conf_in_sync(rtr_config
);
337 inline int is_running(void)
339 return rtr_is_running
;
342 static struct prefix
*pfx_record_to_prefix(struct pfx_record
*record
)
344 struct prefix
*prefix
= prefix_new();
346 prefix
->prefixlen
= record
->min_len
;
348 if (record
->prefix
.ver
== LRTR_IPV4
) {
349 prefix
->family
= AF_INET
;
350 prefix
->u
.prefix4
.s_addr
= htonl(record
->prefix
.u
.addr4
.addr
);
352 prefix
->family
= AF_INET6
;
353 ipv6_addr_to_network_byte_order(record
->prefix
.u
.addr6
.addr
,
354 prefix
->u
.prefix6
.s6_addr32
);
360 static void bgpd_sync_callback(struct thread
*thread
)
363 struct listnode
*node
;
364 struct prefix
*prefix
;
365 struct pfx_record rec
;
367 int socket
= THREAD_FD(thread
);
369 thread_add_read(bm
->master
, bgpd_sync_callback
, NULL
, socket
, &t_rpki
);
371 if (atomic_load_explicit(&rtr_update_overflow
, memory_order_seq_cst
)) {
372 while (read(socket
, &rec
, sizeof(struct pfx_record
)) != -1)
375 atomic_store_explicit(&rtr_update_overflow
, 0,
376 memory_order_seq_cst
);
377 revalidate_all_routes();
381 retval
= read(socket
, &rec
, sizeof(struct pfx_record
));
382 if (retval
!= sizeof(struct pfx_record
)) {
383 RPKI_DEBUG("Could not read from socket");
387 /* RTR-Server crashed/terminated, let's handle and switch
388 * to the second available RTR-Server according to preference.
390 if (rec
.socket
&& rec
.socket
->state
== RTR_ERROR_FATAL
) {
395 prefix
= pfx_record_to_prefix(&rec
);
397 afi_t afi
= (rec
.prefix
.ver
== LRTR_IPV4
) ? AFI_IP
: AFI_IP6
;
399 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
402 for (safi
= SAFI_UNICAST
; safi
< SAFI_MAX
; safi
++) {
403 if (!bgp
->rib
[afi
][safi
])
406 struct bgp_dest
*match
;
407 struct bgp_dest
*node
;
409 match
= bgp_table_subtree_lookup(bgp
->rib
[afi
][safi
],
414 if (bgp_dest_has_bgp_path_info_data(node
)) {
415 revalidate_bgp_node(node
, afi
, safi
);
418 node
= bgp_route_next_until(node
, match
);
423 prefix_free(&prefix
);
426 static void revalidate_bgp_node(struct bgp_dest
*bgp_dest
, afi_t afi
,
429 struct bgp_adj_in
*ain
;
431 for (ain
= bgp_dest
->adj_in
; ain
; ain
= ain
->next
) {
432 struct bgp_path_info
*path
=
433 bgp_dest_get_bgp_path_info(bgp_dest
);
434 mpls_label_t
*label
= NULL
;
435 uint32_t num_labels
= 0;
437 if (path
&& path
->extra
) {
438 label
= path
->extra
->label
;
439 num_labels
= path
->extra
->num_labels
;
441 (void)bgp_update(ain
->peer
, bgp_dest_get_prefix(bgp_dest
),
442 ain
->addpath_rx_id
, ain
->attr
, afi
, safi
,
443 ZEBRA_ROUTE_BGP
, BGP_ROUTE_NORMAL
, NULL
, label
,
444 num_labels
, 1, NULL
);
448 static void revalidate_all_routes(void)
451 struct listnode
*node
;
455 for (ALL_LIST_ELEMENTS_RO(bm
->bgp
, node
, bgp
)) {
457 struct listnode
*peer_listnode
;
459 for (ALL_LIST_ELEMENTS_RO(bgp
->peer
, peer_listnode
, peer
)) {
460 FOREACH_AFI_SAFI (afi
, safi
) {
461 if (!peer
->afc_nego
[afi
][safi
])
464 if (!peer
->bgp
->rib
[afi
][safi
])
467 bgp_soft_reconfig_in(peer
, afi
, safi
);
473 static void rpki_connection_status_cb(const struct rtr_mgr_group
*group
474 __attribute__((unused
)),
475 enum rtr_mgr_status status
,
476 const struct rtr_socket
*socket
477 __attribute__((unused
)),
478 void *data
__attribute__((unused
)))
480 struct pfx_record rec
= {0};
483 if (rtr_is_stopping
||
484 atomic_load_explicit(&rtr_update_overflow
, memory_order_seq_cst
))
487 if (status
== RTR_MGR_ERROR
)
490 retval
= write(rpki_sync_socket_rtr
, &rec
, sizeof(rec
));
491 if (retval
== -1 && (errno
== EAGAIN
|| errno
== EWOULDBLOCK
))
492 atomic_store_explicit(&rtr_update_overflow
, 1,
493 memory_order_seq_cst
);
495 else if (retval
!= sizeof(rec
))
496 RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
499 static void rpki_update_cb_sync_rtr(struct pfx_table
*p
__attribute__((unused
)),
500 const struct pfx_record rec
,
501 const bool added
__attribute__((unused
)))
504 || atomic_load_explicit(&rtr_update_overflow
, memory_order_seq_cst
))
508 write(rpki_sync_socket_rtr
, &rec
, sizeof(struct pfx_record
));
509 if (retval
== -1 && (errno
== EAGAIN
|| errno
== EWOULDBLOCK
))
510 atomic_store_explicit(&rtr_update_overflow
, 1,
511 memory_order_seq_cst
);
513 else if (retval
!= sizeof(struct pfx_record
))
514 RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
517 static void rpki_init_sync_socket(void)
522 RPKI_DEBUG("initializing sync socket");
523 if (socketpair(PF_LOCAL
, SOCK_DGRAM
, 0, fds
) != 0) {
524 msg
= "could not open rpki sync socketpair";
527 rpki_sync_socket_rtr
= fds
[0];
528 rpki_sync_socket_bgpd
= fds
[1];
530 if (set_nonblocking(rpki_sync_socket_rtr
) != 0) {
531 msg
= "could not set rpki_sync_socket_rtr to non blocking";
535 if (set_nonblocking(rpki_sync_socket_bgpd
) != 0) {
536 msg
= "could not set rpki_sync_socket_bgpd to non blocking";
540 thread_add_read(bm
->master
, bgpd_sync_callback
, NULL
,
541 rpki_sync_socket_bgpd
, &t_rpki
);
546 zlog_err("RPKI: %s", msg
);
551 static int bgp_rpki_init(struct thread_master
*master
)
557 cache_list
= list_new();
558 cache_list
->del
= (void (*)(void *)) & free_cache
;
560 polling_period
= POLLING_PERIOD_DEFAULT
;
561 expire_interval
= EXPIRE_INTERVAL_DEFAULT
;
562 retry_interval
= RETRY_INTERVAL_DEFAULT
;
563 install_cli_commands();
564 rpki_init_sync_socket();
568 static int bgp_rpki_fini(void)
571 list_delete(&cache_list
);
573 close(rpki_sync_socket_rtr
);
574 close(rpki_sync_socket_bgpd
);
579 static int bgp_rpki_module_init(void)
581 lrtr_set_alloc_functions(malloc_wrapper
, realloc_wrapper
, free_wrapper
);
583 hook_register(bgp_rpki_prefix_status
, rpki_validate_prefix
);
584 hook_register(frr_late_init
, bgp_rpki_init
);
585 hook_register(frr_early_fini
, &bgp_rpki_fini
);
590 static int start(void)
595 rtr_update_overflow
= 0;
597 if (list_isempty(cache_list
)) {
599 "No caches were found in config. Prefix validation is off.");
602 RPKI_DEBUG("Init rtr_mgr.");
603 int groups_len
= listcount(cache_list
);
604 struct rtr_mgr_group
*groups
= get_groups();
606 RPKI_DEBUG("Polling period: %d", polling_period
);
607 ret
= rtr_mgr_init(&rtr_config
, groups
, groups_len
, polling_period
,
608 expire_interval
, retry_interval
,
609 rpki_update_cb_sync_rtr
, NULL
,
610 rpki_connection_status_cb
, NULL
);
611 if (ret
== RTR_ERROR
) {
612 RPKI_DEBUG("Init rtr_mgr failed.");
616 RPKI_DEBUG("Starting rtr_mgr.");
617 ret
= rtr_mgr_start(rtr_config
);
618 if (ret
== RTR_ERROR
) {
619 RPKI_DEBUG("Starting rtr_mgr failed.");
620 rtr_mgr_free(rtr_config
);
625 XFREE(MTYPE_BGP_RPKI_CACHE_GROUP
, groups
);
630 static void stop(void)
633 if (rtr_is_running
) {
634 rtr_mgr_stop(rtr_config
);
635 rtr_mgr_free(rtr_config
);
640 static int reset(bool force
)
642 if (rtr_is_running
&& !force
)
645 RPKI_DEBUG("Resetting RPKI Session");
650 static struct rtr_mgr_group
*get_connected_group(void)
652 if (!cache_list
|| list_isempty(cache_list
))
655 return rtr_mgr_get_first_group(rtr_config
);
658 static void print_prefix_table_by_asn(struct vty
*vty
, as_t as
)
660 unsigned int number_of_ipv4_prefixes
= 0;
661 unsigned int number_of_ipv6_prefixes
= 0;
662 struct rtr_mgr_group
*group
= get_connected_group();
663 struct rpki_for_each_record_arg arg
;
669 vty_out(vty
, "Cannot find a connected group.\n");
673 struct pfx_table
*pfx_table
= group
->sockets
[0]->pfx_table
;
675 vty_out(vty
, "RPKI/RTR prefix table\n");
676 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
678 arg
.prefix_amount
= &number_of_ipv4_prefixes
;
679 pfx_table_for_each_ipv4_record(pfx_table
, print_record_by_asn
, &arg
);
681 arg
.prefix_amount
= &number_of_ipv6_prefixes
;
682 pfx_table_for_each_ipv6_record(pfx_table
, print_record_by_asn
, &arg
);
684 vty_out(vty
, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes
);
685 vty_out(vty
, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes
);
688 static void print_prefix_table(struct vty
*vty
)
690 struct rpki_for_each_record_arg arg
;
692 unsigned int number_of_ipv4_prefixes
= 0;
693 unsigned int number_of_ipv6_prefixes
= 0;
694 struct rtr_mgr_group
*group
= get_connected_group();
701 struct pfx_table
*pfx_table
= group
->sockets
[0]->pfx_table
;
703 vty_out(vty
, "RPKI/RTR prefix table\n");
704 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
706 arg
.prefix_amount
= &number_of_ipv4_prefixes
;
707 pfx_table_for_each_ipv4_record(pfx_table
, print_record_cb
, &arg
);
709 arg
.prefix_amount
= &number_of_ipv6_prefixes
;
710 pfx_table_for_each_ipv6_record(pfx_table
, print_record_cb
, &arg
);
712 vty_out(vty
, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes
);
713 vty_out(vty
, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes
);
716 static int rpki_validate_prefix(struct peer
*peer
, struct attr
*attr
,
717 const struct prefix
*prefix
)
719 struct assegment
*as_segment
;
721 struct lrtr_ip_addr ip_addr_prefix
;
722 enum pfxv_state result
;
724 if (!is_synchronized())
727 // No aspath means route comes from iBGP
728 if (!attr
->aspath
|| !attr
->aspath
->segments
) {
730 as_number
= peer
->bgp
->as
;
732 as_segment
= attr
->aspath
->segments
;
733 // Find last AsSegment
734 while (as_segment
->next
)
735 as_segment
= as_segment
->next
;
737 if (as_segment
->type
== AS_SEQUENCE
) {
739 as_number
= as_segment
->as
[as_segment
->length
- 1];
740 } else if (as_segment
->type
== AS_CONFED_SEQUENCE
741 || as_segment
->type
== AS_CONFED_SET
) {
743 as_number
= peer
->bgp
->as
;
745 // RFC says: "Take distinguished value NONE as asn"
746 // which means state is unknown
747 return RPKI_NOTFOUND
;
751 // Get the prefix in requested format
752 switch (prefix
->family
) {
754 ip_addr_prefix
.ver
= LRTR_IPV4
;
755 ip_addr_prefix
.u
.addr4
.addr
= ntohl(prefix
->u
.prefix4
.s_addr
);
759 ip_addr_prefix
.ver
= LRTR_IPV6
;
760 ipv6_addr_to_host_byte_order(prefix
->u
.prefix6
.s6_addr32
,
761 ip_addr_prefix
.u
.addr6
.addr
);
768 // Do the actual validation
769 rtr_mgr_validate(rtr_config
, as_number
, &ip_addr_prefix
,
770 prefix
->prefixlen
, &result
);
772 // Print Debug output
774 case BGP_PFXV_STATE_VALID
:
776 "Validating Prefix %pFX from asn %u Result: VALID",
779 case BGP_PFXV_STATE_NOT_FOUND
:
781 "Validating Prefix %pFX from asn %u Result: NOT FOUND",
783 return RPKI_NOTFOUND
;
784 case BGP_PFXV_STATE_INVALID
:
786 "Validating Prefix %pFX from asn %u Result: INVALID",
791 "Validating Prefix %pFX from asn %u Result: CANNOT VALIDATE",
798 static int add_cache(struct cache
*cache
)
800 uint8_t preference
= cache
->preference
;
801 struct rtr_mgr_group group
;
803 group
.preference
= preference
;
804 group
.sockets_len
= 1;
805 group
.sockets
= &cache
->rtr_socket
;
807 if (rtr_is_running
) {
808 init_tr_socket(cache
);
810 if (rtr_mgr_add_group(rtr_config
, &group
) != RTR_SUCCESS
) {
811 free_tr_socket(cache
);
816 listnode_add(cache_list
, cache
);
821 static int add_tcp_cache(const char *host
, const char *port
,
822 const uint8_t preference
, const char *bindaddr
)
824 struct rtr_socket
*rtr_socket
;
825 struct tr_tcp_config
*tcp_config
=
826 XCALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_tcp_config
));
827 struct tr_socket
*tr_socket
=
828 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_socket
));
829 struct cache
*cache
=
830 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct cache
));
832 tcp_config
->host
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, host
);
833 tcp_config
->port
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, port
);
835 tcp_config
->bindaddr
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, bindaddr
);
837 tcp_config
->bindaddr
= NULL
;
839 rtr_socket
= create_rtr_socket(tr_socket
);
842 cache
->tr_socket
= tr_socket
;
843 cache
->tr_config
.tcp_config
= tcp_config
;
844 cache
->rtr_socket
= rtr_socket
;
845 cache
->preference
= preference
;
847 int ret
= add_cache(cache
);
848 if (ret
!= SUCCESS
) {
855 #if defined(FOUND_SSH)
856 static int add_ssh_cache(const char *host
, const unsigned int port
,
857 const char *username
, const char *client_privkey_path
,
858 const char *client_pubkey_path
,
859 const char *server_pubkey_path
,
860 const uint8_t preference
, const char *bindaddr
)
862 struct tr_ssh_config
*ssh_config
=
863 XCALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_ssh_config
));
864 struct cache
*cache
=
865 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct cache
));
866 struct tr_socket
*tr_socket
=
867 XMALLOC(MTYPE_BGP_RPKI_CACHE
, sizeof(struct tr_socket
));
868 struct rtr_socket
*rtr_socket
;
870 ssh_config
->port
= port
;
871 ssh_config
->host
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, host
);
873 ssh_config
->bindaddr
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, bindaddr
);
875 ssh_config
->bindaddr
= NULL
;
877 ssh_config
->username
= XSTRDUP(MTYPE_BGP_RPKI_CACHE
, username
);
878 ssh_config
->client_privkey_path
=
879 XSTRDUP(MTYPE_BGP_RPKI_CACHE
, client_privkey_path
);
880 ssh_config
->server_hostkey_path
=
881 XSTRDUP(MTYPE_BGP_RPKI_CACHE
, server_pubkey_path
);
883 rtr_socket
= create_rtr_socket(tr_socket
);
886 cache
->tr_socket
= tr_socket
;
887 cache
->tr_config
.ssh_config
= ssh_config
;
888 cache
->rtr_socket
= rtr_socket
;
889 cache
->preference
= preference
;
891 int ret
= add_cache(cache
);
892 if (ret
!= SUCCESS
) {
900 static void free_cache(struct cache
*cache
)
902 if (cache
->type
== TCP
) {
903 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
->host
);
904 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
->port
);
905 if (cache
->tr_config
.tcp_config
->bindaddr
)
906 XFREE(MTYPE_BGP_RPKI_CACHE
,
907 cache
->tr_config
.tcp_config
->bindaddr
);
908 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.tcp_config
);
910 #if defined(FOUND_SSH)
912 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.ssh_config
->host
);
913 XFREE(MTYPE_BGP_RPKI_CACHE
,
914 cache
->tr_config
.ssh_config
->username
);
915 XFREE(MTYPE_BGP_RPKI_CACHE
,
916 cache
->tr_config
.ssh_config
->client_privkey_path
);
917 XFREE(MTYPE_BGP_RPKI_CACHE
,
918 cache
->tr_config
.ssh_config
->server_hostkey_path
);
919 if (cache
->tr_config
.ssh_config
->bindaddr
)
920 XFREE(MTYPE_BGP_RPKI_CACHE
,
921 cache
->tr_config
.ssh_config
->bindaddr
);
922 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_config
.ssh_config
);
925 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->tr_socket
);
926 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
->rtr_socket
);
927 XFREE(MTYPE_BGP_RPKI_CACHE
, cache
);
930 static int config_write(struct vty
*vty
)
932 struct listnode
*cache_node
;
935 if (!listcount(cache_list
))
939 vty_out(vty
, "debug rpki\n");
942 vty_out(vty
, "rpki\n");
943 vty_out(vty
, " rpki polling_period %d\n", polling_period
);
945 if (retry_interval
!= RETRY_INTERVAL_DEFAULT
)
946 vty_out(vty
, " rpki retry_interval %d\n", retry_interval
);
947 if (expire_interval
!= EXPIRE_INTERVAL_DEFAULT
)
948 vty_out(vty
, " rpki expire_interval %d\n", expire_interval
);
950 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
951 switch (cache
->type
) {
952 struct tr_tcp_config
*tcp_config
;
953 #if defined(FOUND_SSH)
954 struct tr_ssh_config
*ssh_config
;
957 tcp_config
= cache
->tr_config
.tcp_config
;
958 vty_out(vty
, " rpki cache %s %s ", tcp_config
->host
,
960 if (tcp_config
->bindaddr
)
961 vty_out(vty
, "source %s ",
962 tcp_config
->bindaddr
);
964 #if defined(FOUND_SSH)
966 ssh_config
= cache
->tr_config
.ssh_config
;
967 vty_out(vty
, " rpki cache %s %u %s %s %s ",
968 ssh_config
->host
, ssh_config
->port
,
969 ssh_config
->username
,
970 ssh_config
->client_privkey_path
,
971 ssh_config
->server_hostkey_path
!= NULL
972 ? ssh_config
->server_hostkey_path
974 if (ssh_config
->bindaddr
)
975 vty_out(vty
, "source %s ",
976 ssh_config
->bindaddr
);
983 vty_out(vty
, "preference %hhu\n", cache
->preference
);
985 vty_out(vty
, "exit\n");
993 "Enable rpki and enter rpki configuration mode\n")
995 vty
->node
= RPKI_NODE
;
999 DEFUN (bgp_rpki_start
,
1003 "start rpki support\n")
1005 if (listcount(cache_list
) == 0)
1007 "Could not start rpki because no caches are configured\n");
1009 if (!is_running()) {
1010 if (start() == ERROR
) {
1011 RPKI_DEBUG("RPKI failed to start");
1018 DEFUN (bgp_rpki_stop
,
1022 "start rpki support\n")
1030 DEFPY (rpki_polling_period
,
1031 rpki_polling_period_cmd
,
1032 "rpki polling_period (1-86400)$pp",
1034 "Set polling period\n"
1035 "Polling period value\n")
1037 polling_period
= pp
;
1041 DEFUN (no_rpki_polling_period
,
1042 no_rpki_polling_period_cmd
,
1043 "no rpki polling_period",
1046 "Set polling period back to default\n")
1048 polling_period
= POLLING_PERIOD_DEFAULT
;
1052 DEFPY (rpki_expire_interval
,
1053 rpki_expire_interval_cmd
,
1054 "rpki expire_interval (600-172800)$tmp",
1056 "Set expire interval\n"
1057 "Expire interval value\n")
1059 if ((unsigned int)tmp
>= polling_period
) {
1060 expire_interval
= tmp
;
1064 vty_out(vty
, "%% Expiry interval must be polling period or larger\n");
1065 return CMD_WARNING_CONFIG_FAILED
;
1068 DEFUN (no_rpki_expire_interval
,
1069 no_rpki_expire_interval_cmd
,
1070 "no rpki expire_interval",
1073 "Set expire interval back to default\n")
1075 expire_interval
= polling_period
* 2;
1079 DEFPY (rpki_retry_interval
,
1080 rpki_retry_interval_cmd
,
1081 "rpki retry_interval (1-7200)$tmp",
1083 "Set retry interval\n"
1084 "retry interval value\n")
1086 retry_interval
= tmp
;
1090 DEFUN (no_rpki_retry_interval
,
1091 no_rpki_retry_interval_cmd
,
1092 "no rpki retry_interval",
1095 "Set retry interval back to default\n")
1097 retry_interval
= RETRY_INTERVAL_DEFAULT
;
1101 DEFPY(rpki_cache
, rpki_cache_cmd
,
1102 "rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY SSH_PUBKEY [SERVER_PUBKEY]> [source <A.B.C.D>$bindaddr] preference (1-255)",
1104 "Install a cache server to current group\n"
1105 "IP address of cache server\n Hostname of cache server\n"
1109 "Path to own SSH private key\n"
1110 "Path to own SSH public key\n"
1111 "Path to Public key of cache server\n"
1112 "Configure source IP address of RPKI connection\n"
1113 "Define a Source IP Address\n"
1114 "Preference of the cache server\n"
1115 "Preference value\n")
1118 struct listnode
*cache_node
;
1119 struct cache
*current_cache
;
1121 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, current_cache
)) {
1122 if (current_cache
->preference
== preference
) {
1124 "Cache with preference %ld is already configured\n",
1131 // use ssh connection
1133 #if defined(FOUND_SSH)
1134 return_value
= add_ssh_cache(
1135 cache
, sshport
, ssh_uname
, ssh_privkey
, ssh_pubkey
,
1136 server_pubkey
, preference
, bindaddr_str
);
1138 return_value
= SUCCESS
;
1140 "ssh sockets are not supported. Please recompile rtrlib and frr with ssh support. If you want to use it\n");
1142 } else { // use tcp connection
1144 add_tcp_cache(cache
, tcpport
, preference
, bindaddr_str
);
1147 if (return_value
== ERROR
) {
1148 vty_out(vty
, "Could not create new rpki cache\n");
1155 DEFPY (no_rpki_cache
,
1157 "no rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport> preference (1-255)$preference",
1160 "Remove a cache server\n"
1161 "IP address of cache server\n Hostname of cache server\n"
1164 "Preference of the cache server\n"
1165 "Preference value\n")
1167 struct cache
*cache_p
= find_cache(preference
);
1170 vty_out(vty
, "Could not find cache %ld\n", preference
);
1174 if (rtr_is_running
&& listcount(cache_list
) == 1) {
1176 } else if (rtr_is_running
) {
1177 if (rtr_mgr_remove_group(rtr_config
, preference
) == RTR_ERROR
) {
1178 vty_out(vty
, "Could not remove cache %ld", preference
);
1185 listnode_delete(cache_list
, cache_p
);
1186 free_cache(cache_p
);
1191 DEFUN (show_rpki_prefix_table
,
1192 show_rpki_prefix_table_cmd
,
1193 "show rpki prefix-table",
1196 "Show validated prefixes which were received from RPKI Cache\n")
1198 struct listnode
*cache_node
;
1199 struct cache
*cache
;
1201 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1202 vty_out(vty
, "host: %s port: %s\n",
1203 cache
->tr_config
.tcp_config
->host
,
1204 cache
->tr_config
.tcp_config
->port
);
1206 if (is_synchronized())
1207 print_prefix_table(vty
);
1209 vty_out(vty
, "No connection to RPKI cache server.\n");
1214 DEFPY (show_rpki_as_number
, show_rpki_as_number_cmd
,
1215 "show rpki as-number (1-4294967295)$by_asn",
1216 SHOW_STR RPKI_OUTPUT_STRING
1217 "Lookup by ASN in prefix table\n"
1220 if (!is_synchronized()) {
1221 vty_out(vty
, "No Connection to RPKI cache server.\n");
1225 print_prefix_table_by_asn(vty
, by_asn
);
1229 DEFPY (show_rpki_prefix
,
1230 show_rpki_prefix_cmd
,
1231 "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn]",
1234 "Lookup IP prefix and optionally ASN in prefix table\n"
1240 if (!is_synchronized()) {
1241 vty_out(vty
, "No Connection to RPKI cache server.\n");
1245 struct lrtr_ip_addr addr
;
1246 char addr_str
[INET6_ADDRSTRLEN
];
1247 size_t addr_len
= strchr(prefix_str
, '/') - prefix_str
;
1249 memset(addr_str
, 0, sizeof(addr_str
));
1250 memcpy(addr_str
, prefix_str
, addr_len
);
1252 if (lrtr_ip_str_to_addr(addr_str
, &addr
) != 0) {
1253 vty_out(vty
, "Invalid IP prefix\n");
1257 struct pfx_record
*matches
= NULL
;
1258 unsigned int match_count
= 0;
1259 enum pfxv_state result
;
1261 if (pfx_table_validate_r(rtr_config
->pfx_table
, &matches
, &match_count
,
1262 asn
, &addr
, prefix
->prefixlen
, &result
)
1264 vty_out(vty
, "Prefix lookup failed\n");
1268 vty_out(vty
, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
1269 for (size_t i
= 0; i
< match_count
; ++i
) {
1270 const struct pfx_record
*record
= &matches
[i
];
1272 if (record
->max_len
>= prefix
->prefixlen
1273 && ((asn
!= 0 && (uint32_t)asn
== record
->asn
)
1275 print_record(&matches
[i
], vty
);
1282 DEFUN (show_rpki_cache_server
,
1283 show_rpki_cache_server_cmd
,
1284 "show rpki cache-server",
1287 "SHOW configured cache server\n")
1289 struct listnode
*cache_node
;
1290 struct cache
*cache
;
1292 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1293 if (cache
->type
== TCP
) {
1294 vty_out(vty
, "host: %s port: %s\n",
1295 cache
->tr_config
.tcp_config
->host
,
1296 cache
->tr_config
.tcp_config
->port
);
1298 #if defined(FOUND_SSH)
1299 } else if (cache
->type
== SSH
) {
1301 "host: %s port: %d username: %s server_hostkey_path: %s client_privkey_path: %s\n",
1302 cache
->tr_config
.ssh_config
->host
,
1303 cache
->tr_config
.ssh_config
->port
,
1304 cache
->tr_config
.ssh_config
->username
,
1305 cache
->tr_config
.ssh_config
1306 ->server_hostkey_path
,
1307 cache
->tr_config
.ssh_config
1308 ->client_privkey_path
);
1316 DEFUN (show_rpki_cache_connection
,
1317 show_rpki_cache_connection_cmd
,
1318 "show rpki cache-connection",
1321 "Show to which RPKI Cache Servers we have a connection\n")
1323 if (!is_synchronized()) {
1324 vty_out(vty
, "No connection to RPKI cache server.\n");
1329 struct listnode
*cache_node
;
1330 struct cache
*cache
;
1331 struct rtr_mgr_group
*group
= get_connected_group();
1334 vty_out(vty
, "Cannot find a connected group.\n");
1337 vty_out(vty
, "Connected to group %d\n", group
->preference
);
1338 for (ALL_LIST_ELEMENTS_RO(cache_list
, cache_node
, cache
)) {
1339 if (cache
->preference
== group
->preference
) {
1340 struct tr_tcp_config
*tcp_config
;
1341 #if defined(FOUND_SSH)
1342 struct tr_ssh_config
*ssh_config
;
1345 switch (cache
->type
) {
1347 tcp_config
= cache
->tr_config
.tcp_config
;
1348 vty_out(vty
, "rpki tcp cache %s %s pref %hhu\n",
1349 tcp_config
->host
, tcp_config
->port
,
1353 #if defined(FOUND_SSH)
1355 ssh_config
= cache
->tr_config
.ssh_config
;
1356 vty_out(vty
, "rpki ssh cache %s %u pref %hhu\n",
1357 ssh_config
->host
, ssh_config
->port
,
1371 static int config_on_exit(struct vty
*vty
)
1383 return reset(true) == SUCCESS
? CMD_SUCCESS
: CMD_WARNING
;
1390 "Enable debugging for rpki\n")
1396 DEFUN (no_debug_rpki
,
1401 "Disable debugging for rpki\n")
1407 DEFUN_YANG (match_rpki
,
1409 "match rpki <valid|invalid|notfound>",
1414 "Prefix not found\n")
1417 "./match-condition[condition='frr-bgp-route-map:rpki']";
1418 char xpath_value
[XPATH_MAXLEN
];
1420 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
1421 snprintf(xpath_value
, sizeof(xpath_value
),
1422 "%s/rmap-match-condition/frr-bgp-route-map:rpki", xpath
);
1423 nb_cli_enqueue_change(vty
, xpath_value
, NB_OP_MODIFY
, argv
[2]->arg
);
1425 return nb_cli_apply_changes(vty
, NULL
);
1428 DEFUN_YANG (no_match_rpki
,
1430 "no match rpki <valid|invalid|notfound>",
1436 "Prefix not found\n")
1439 "./match-condition[condition='frr-bgp-route-map:rpki']";
1441 nb_cli_enqueue_change(vty
, xpath
, NB_OP_CREATE
, NULL
);
1442 return nb_cli_apply_changes(vty
, NULL
);
1445 static void install_cli_commands(void)
1447 // TODO: make config write work
1448 install_node(&rpki_node
);
1449 install_default(RPKI_NODE
);
1450 install_element(CONFIG_NODE
, &rpki_cmd
);
1451 install_element(ENABLE_NODE
, &rpki_cmd
);
1453 install_element(ENABLE_NODE
, &bgp_rpki_start_cmd
);
1454 install_element(ENABLE_NODE
, &bgp_rpki_stop_cmd
);
1456 /* Install rpki reset command */
1457 install_element(RPKI_NODE
, &rpki_reset_cmd
);
1459 /* Install rpki polling period commands */
1460 install_element(RPKI_NODE
, &rpki_polling_period_cmd
);
1461 install_element(RPKI_NODE
, &no_rpki_polling_period_cmd
);
1463 /* Install rpki expire interval commands */
1464 install_element(RPKI_NODE
, &rpki_expire_interval_cmd
);
1465 install_element(RPKI_NODE
, &no_rpki_expire_interval_cmd
);
1467 /* Install rpki retry interval commands */
1468 install_element(RPKI_NODE
, &rpki_retry_interval_cmd
);
1469 install_element(RPKI_NODE
, &no_rpki_retry_interval_cmd
);
1471 /* Install rpki cache commands */
1472 install_element(RPKI_NODE
, &rpki_cache_cmd
);
1473 install_element(RPKI_NODE
, &no_rpki_cache_cmd
);
1475 /* Install show commands */
1476 install_element(VIEW_NODE
, &show_rpki_prefix_table_cmd
);
1477 install_element(VIEW_NODE
, &show_rpki_cache_connection_cmd
);
1478 install_element(VIEW_NODE
, &show_rpki_cache_server_cmd
);
1479 install_element(VIEW_NODE
, &show_rpki_prefix_cmd
);
1480 install_element(VIEW_NODE
, &show_rpki_as_number_cmd
);
1482 /* Install debug commands */
1483 install_element(CONFIG_NODE
, &debug_rpki_cmd
);
1484 install_element(ENABLE_NODE
, &debug_rpki_cmd
);
1485 install_element(CONFIG_NODE
, &no_debug_rpki_cmd
);
1486 install_element(ENABLE_NODE
, &no_debug_rpki_cmd
);
1488 /* Install route match */
1489 route_map_install_match(&route_match_rpki_cmd
);
1490 install_element(RMAP_NODE
, &match_rpki_cmd
);
1491 install_element(RMAP_NODE
, &no_match_rpki_cmd
);
1494 FRR_MODULE_SETUP(.name
= "bgpd_rpki", .version
= "0.3.6",
1495 .description
= "Enable RPKI support for FRR.",
1496 .init
= bgp_rpki_module_init
,