]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_rpki.c
bgpd: Allow deleting full line for RPKI cache server
[mirror_frr.git] / bgpd / bgp_rpki.c
CommitLineData
dabecd7c
MR
1/*
2 * BGP RPKI
3 * Copyright (C) 2013 Michael Mester (m.mester@fu-berlin.de), for FU Berlin
996c9314
LB
4 * Copyright (C) 2014-2017 Andreas Reuter (andreas.reuter@fu-berlin.de), for FU
5 * Berlin
6 * Copyright (C) 2016-2017 Colin Sames (colin.sames@haw-hamburg.de), for HAW
7 * Hamburg
e4234602
MR
8 * Copyright (C) 2017-2018 Marcel Röthke (marcel.roethke@haw-hamburg.de),
9 * for HAW Hamburg
dabecd7c
MR
10 *
11 * This file is part of FRRouting.
12 *
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)
16 * any later version.
17 *
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
21 * more details.
22 *
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
26 */
27
45c0beda
AK
28/* If rtrlib compiled with ssh support, don`t fail build */
29#define LIBSSH_LEGACY_0_4
30
dabecd7c
MR
31#include <zebra.h>
32#include <pthread.h>
33#include <time.h>
34#include <stdbool.h>
35#include <stdlib.h>
36#include "prefix.h"
37#include "log.h"
38#include "command.h"
39#include "linklist.h"
40#include "memory.h"
41#include "thread.h"
42#include "filter.h"
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"
fdeb5a81 50#include "bgpd/bgp_rpki.h"
0d951156 51#include "northbound_cli.h"
fdeb5a81 52
4ce82676 53#include "lib/network.h"
1dacdd8b 54#include "lib/thread.h"
74dc19a2 55#ifndef VTYSH_EXTRACT_PL
dabecd7c 56#include "rtrlib/rtrlib.h"
74dc19a2 57#endif
dabecd7c
MR
58#include "hook.h"
59#include "libfrr.h"
09781197 60#include "lib/version.h"
dabecd7c 61
2e4c2296
RW
62#ifndef VTYSH_EXTRACT_PL
63#include "bgpd/bgp_rpki_clippy.c"
64#endif
dabecd7c 65
bf8d3d6a
DL
66DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_CACHE, "BGP RPKI Cache server");
67DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_CACHE_GROUP, "BGP RPKI Cache server group");
94ff78a7 68DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_RTRLIB, "BGP RPKI RTRLib");
dabecd7c 69
dabecd7c
MR
70#define POLLING_PERIOD_DEFAULT 3600
71#define EXPIRE_INTERVAL_DEFAULT 7200
72#define RETRY_INTERVAL_DEFAULT 600
1b2095d1 73#define BGP_RPKI_CACHE_SERVER_SYNC_RETRY_TIMEOUT 3
dabecd7c 74
d67485c6
DA
75static struct thread *t_rpki_sync;
76
dabecd7c
MR
77#define RPKI_DEBUG(...) \
78 if (rpki_debug) { \
79 zlog_debug("RPKI: " __VA_ARGS__); \
80 }
81
82#define RPKI_OUTPUT_STRING "Control rpki specific settings\n"
83
84struct cache {
996c9314
LB
85 enum { TCP, SSH } type;
86 struct tr_socket *tr_socket;
87 union {
dabecd7c
MR
88 struct tr_tcp_config *tcp_config;
89 struct tr_ssh_config *ssh_config;
996c9314
LB
90 } tr_config;
91 struct rtr_socket *rtr_socket;
92 uint8_t preference;
dabecd7c
MR
93};
94
95enum return_values { SUCCESS = 0, ERROR = -1 };
96
97struct rpki_for_each_record_arg {
98 struct vty *vty;
99 unsigned int *prefix_amount;
02334bb2 100 as_t as;
dff41cc8 101 json_object *json;
dabecd7c
MR
102};
103
104static int start(void);
105static void stop(void);
106static int reset(bool force);
107static struct rtr_mgr_group *get_connected_group(void);
dff41cc8 108static void print_prefix_table(struct vty *vty, json_object *json);
dabecd7c
MR
109static void install_cli_commands(void);
110static int config_write(struct vty *vty);
791ded4a 111static int config_on_exit(struct vty *vty);
dabecd7c
MR
112static void free_cache(struct cache *cache);
113static struct rtr_mgr_group *get_groups(void);
114#if defined(FOUND_SSH)
996c9314
LB
115static int add_ssh_cache(const char *host, const unsigned int port,
116 const char *username, const char *client_privkey_path,
dabecd7c
MR
117 const char *client_pubkey_path,
118 const char *server_pubkey_path,
7253a7bc 119 const uint8_t preference, const char *bindaddr);
dabecd7c
MR
120#endif
121static struct rtr_socket *create_rtr_socket(struct tr_socket *tr_socket);
122static struct cache *find_cache(const uint8_t preference);
8156765a 123static void rpki_delete_all_cache_nodes(void);
996c9314 124static int add_tcp_cache(const char *host, const char *port,
7253a7bc 125 const uint8_t preference, const char *bindaddr);
dff41cc8
DA
126static void print_record(const struct pfx_record *record, struct vty *vty,
127 json_object *json);
d67485c6 128static bool is_synchronized(void);
0e3d96bf
DA
129static bool is_running(void);
130static bool is_stopping(void);
dabecd7c 131static void route_match_free(void *rule);
b68885f9
LK
132static enum route_map_cmd_result_t route_match(void *rule,
133 const struct prefix *prefix,
1782514f 134
b68885f9 135 void *object);
dabecd7c 136static void *route_match_compile(const char *arg);
9bcb3eef 137static void revalidate_bgp_node(struct bgp_dest *dest, afi_t afi, safi_t safi);
4ce82676 138static void revalidate_all_routes(void);
dabecd7c
MR
139
140static struct rtr_mgr_config *rtr_config;
141static struct list *cache_list;
0e3d96bf
DA
142static bool rtr_is_running;
143static bool rtr_is_stopping;
d67485c6 144static bool rtr_is_synced;
4ce82676 145static _Atomic int rtr_update_overflow;
0e3d96bf 146static bool rpki_debug;
dabecd7c
MR
147static unsigned int polling_period;
148static unsigned int expire_interval;
149static unsigned int retry_interval;
1dacdd8b
MR
150static int rpki_sync_socket_rtr;
151static int rpki_sync_socket_bgpd;
dabecd7c 152
62b346ee 153static struct cmd_node rpki_node = {
f4b8291f 154 .name = "rpki",
62b346ee 155 .node = RPKI_NODE,
24389580 156 .parent_node = CONFIG_NODE,
62b346ee 157 .prompt = "%s(config-rpki)# ",
612c2c15 158 .config_write = config_write,
791ded4a 159 .node_exit = config_on_exit,
62b346ee 160};
364deb04 161static const struct route_map_rule_cmd route_match_rpki_cmd = {
996c9314 162 "rpki", route_match, route_match_compile, route_match_free};
dabecd7c
MR
163
164static void *malloc_wrapper(size_t size)
165{
94ff78a7 166 return XMALLOC(MTYPE_BGP_RPKI_RTRLIB, size);
dabecd7c
MR
167}
168
169static void *realloc_wrapper(void *ptr, size_t size)
170{
94ff78a7 171 return XREALLOC(MTYPE_BGP_RPKI_RTRLIB, ptr, size);
dabecd7c
MR
172}
173
174static void free_wrapper(void *ptr)
175{
94ff78a7 176 XFREE(MTYPE_BGP_RPKI_RTRLIB, ptr);
dabecd7c
MR
177}
178
92110aab
MR
179static void init_tr_socket(struct cache *cache)
180{
181 if (cache->type == TCP)
182 tr_tcp_init(cache->tr_config.tcp_config,
183 cache->tr_socket);
184#if defined(FOUND_SSH)
185 else
186 tr_ssh_init(cache->tr_config.ssh_config,
187 cache->tr_socket);
188#endif
189}
190
191static void free_tr_socket(struct cache *cache)
192{
193 if (cache->type == TCP)
194 tr_tcp_init(cache->tr_config.tcp_config,
195 cache->tr_socket);
196#if defined(FOUND_SSH)
197 else
198 tr_ssh_init(cache->tr_config.ssh_config,
199 cache->tr_socket);
200#endif
201}
202
dabecd7c 203static int rpki_validate_prefix(struct peer *peer, struct attr *attr,
898c4e66 204 const struct prefix *prefix);
dabecd7c 205
1dacdd8b
MR
206static void ipv6_addr_to_network_byte_order(const uint32_t *src, uint32_t *dest)
207{
208 int i;
209
210 for (i = 0; i < 4; i++)
211 dest[i] = htonl(src[i]);
212}
213
e4234602
MR
214static void ipv6_addr_to_host_byte_order(const uint32_t *src, uint32_t *dest)
215{
216 int i;
217
218 for (i = 0; i < 4; i++)
219 dest[i] = ntohl(src[i]);
220}
221
b68885f9
LK
222static enum route_map_cmd_result_t route_match(void *rule,
223 const struct prefix *prefix,
b68885f9 224 void *object)
dabecd7c
MR
225{
226 int *rpki_status = rule;
9b6d8fcf 227 struct bgp_path_info *path;
dabecd7c 228
1782514f 229 path = object;
dabecd7c 230
1782514f
DS
231 if (rpki_validate_prefix(path->peer, path->attr, prefix)
232 == *rpki_status) {
233 return RMAP_MATCH;
dabecd7c 234 }
1782514f 235
dabecd7c
MR
236 return RMAP_NOMATCH;
237}
238
239static void *route_match_compile(const char *arg)
240{
241 int *rpki_status;
242
0b2c4b35 243 rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
dabecd7c
MR
244
245 if (strcmp(arg, "valid") == 0)
246 *rpki_status = RPKI_VALID;
247 else if (strcmp(arg, "invalid") == 0)
248 *rpki_status = RPKI_INVALID;
249 else
250 *rpki_status = RPKI_NOTFOUND;
251
252 return rpki_status;
253}
254
255static void route_match_free(void *rule)
256{
257 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
258}
259
260static struct rtr_socket *create_rtr_socket(struct tr_socket *tr_socket)
261{
262 struct rtr_socket *rtr_socket =
263 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct rtr_socket));
264 rtr_socket->tr_socket = tr_socket;
265 return rtr_socket;
266}
267
268static struct cache *find_cache(const uint8_t preference)
269{
270 struct listnode *cache_node;
271 struct cache *cache;
272
273 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
274 if (cache->preference == preference)
275 return cache;
276 }
277 return NULL;
278}
279
8156765a
DA
280static void rpki_delete_all_cache_nodes(void)
281{
282 struct listnode *cache_node, *cache_next;
283 struct cache *cache;
284
285 for (ALL_LIST_ELEMENTS(cache_list, cache_node, cache_next, cache)) {
286 rtr_mgr_remove_group(rtr_config, cache->preference);
287 listnode_delete(cache_list, cache);
288 }
289}
290
dff41cc8
DA
291static void print_record(const struct pfx_record *record, struct vty *vty,
292 json_object *json)
dabecd7c
MR
293{
294 char ip[INET6_ADDRSTRLEN];
dff41cc8 295 json_object *json_record = NULL;
5d799192
MR
296
297 lrtr_ip_addr_to_str(&record->prefix, ip, sizeof(ip));
dff41cc8
DA
298
299 if (!json) {
300 vty_out(vty, "%-40s %3u - %3u %10u\n", ip, record->min_len,
301 record->max_len, record->asn);
302 } else {
303 json_record = json_object_new_object();
304 json_object_string_add(json_record, "prefix", ip);
305 json_object_int_add(json_record, "prefixLenMin",
306 record->min_len);
307 json_object_int_add(json_record, "prefixLenMax",
308 record->max_len);
309 json_object_int_add(json_record, "asn", record->asn);
310 json_object_array_add(json, json_record);
311 }
5d799192
MR
312}
313
02334bb2
DA
314static void print_record_by_asn(const struct pfx_record *record, void *data)
315{
316 struct rpki_for_each_record_arg *arg = data;
317 struct vty *vty = arg->vty;
318
319 if (record->asn == arg->as) {
320 (*arg->prefix_amount)++;
dff41cc8 321 print_record(record, vty, arg->json);
02334bb2
DA
322 }
323}
324
5d799192
MR
325static void print_record_cb(const struct pfx_record *record, void *data)
326{
dabecd7c
MR
327 struct rpki_for_each_record_arg *arg = data;
328 struct vty *vty = arg->vty;
329
a220aec6 330 (*arg->prefix_amount)++;
dabecd7c 331
dff41cc8 332 print_record(record, vty, arg->json);
dabecd7c
MR
333}
334
335static struct rtr_mgr_group *get_groups(void)
336{
337 struct listnode *cache_node;
338 struct rtr_mgr_group *rtr_mgr_groups;
339 struct cache *cache;
340
341 int group_count = listcount(cache_list);
342
343 if (group_count == 0)
344 return NULL;
345
346 rtr_mgr_groups = XMALLOC(MTYPE_BGP_RPKI_CACHE_GROUP,
347 group_count * sizeof(struct rtr_mgr_group));
348
349 size_t i = 0;
350
351 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
352 rtr_mgr_groups[i].sockets = &cache->rtr_socket;
353 rtr_mgr_groups[i].sockets_len = 1;
354 rtr_mgr_groups[i].preference = cache->preference;
355
92110aab 356 init_tr_socket(cache);
dabecd7c
MR
357
358 i++;
359 }
360
361 return rtr_mgr_groups;
362}
363
d67485c6 364inline bool is_synchronized(void)
dabecd7c 365{
d67485c6 366 return rtr_is_synced;
dabecd7c
MR
367}
368
0e3d96bf 369inline bool is_running(void)
dabecd7c
MR
370{
371 return rtr_is_running;
372}
373
0e3d96bf 374inline bool is_stopping(void)
9ca44fc8
DA
375{
376 return rtr_is_stopping;
377}
378
1dacdd8b
MR
379static struct prefix *pfx_record_to_prefix(struct pfx_record *record)
380{
381 struct prefix *prefix = prefix_new();
382
383 prefix->prefixlen = record->min_len;
384
385 if (record->prefix.ver == LRTR_IPV4) {
386 prefix->family = AF_INET;
387 prefix->u.prefix4.s_addr = htonl(record->prefix.u.addr4.addr);
388 } else {
389 prefix->family = AF_INET6;
390 ipv6_addr_to_network_byte_order(record->prefix.u.addr6.addr,
391 prefix->u.prefix6.s6_addr32);
392 }
393
394 return prefix;
395}
396
cc9f21da 397static void bgpd_sync_callback(struct thread *thread)
1dacdd8b
MR
398{
399 struct bgp *bgp;
400 struct listnode *node;
401 struct prefix *prefix;
402 struct pfx_record rec;
403
d2e3f8a2
DA
404 thread_add_read(bm->master, bgpd_sync_callback, NULL,
405 rpki_sync_socket_bgpd, NULL);
4ce82676
MR
406
407 if (atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst)) {
d2e3f8a2
DA
408 while (read(rpki_sync_socket_bgpd, &rec,
409 sizeof(struct pfx_record)) != -1)
4ce82676
MR
410 ;
411
412 atomic_store_explicit(&rtr_update_overflow, 0,
413 memory_order_seq_cst);
414 revalidate_all_routes();
cc9f21da 415 return;
4ce82676
MR
416 }
417
d2e3f8a2
DA
418 int retval =
419 read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record));
3b128228 420 if (retval != sizeof(struct pfx_record)) {
d2e3f8a2 421 RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd");
cc9f21da 422 return;
38775a3c 423 }
1dacdd8b
MR
424 prefix = pfx_record_to_prefix(&rec);
425
426 afi_t afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6;
427
428 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
35a1e798 429 safi_t safi;
1dacdd8b 430
35a1e798
DS
431 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
432 if (!bgp->rib[afi][safi])
433 continue;
31a2af32 434
35a1e798
DS
435 struct bgp_dest *match;
436 struct bgp_dest *node;
1dacdd8b 437
35a1e798
DS
438 match = bgp_table_subtree_lookup(bgp->rib[afi][safi],
439 prefix);
440 node = match;
bac31cb8 441
35a1e798
DS
442 while (node) {
443 if (bgp_dest_has_bgp_path_info_data(node)) {
444 revalidate_bgp_node(node, afi, safi);
bac31cb8 445 }
35a1e798
DS
446
447 node = bgp_route_next_until(node, match);
31a2af32 448 }
1dacdd8b
MR
449 }
450 }
451
45206fe2 452 prefix_free(&prefix);
1dacdd8b
MR
453}
454
9bcb3eef 455static void revalidate_bgp_node(struct bgp_dest *bgp_dest, afi_t afi,
1dacdd8b
MR
456 safi_t safi)
457{
458 struct bgp_adj_in *ain;
459
9bcb3eef 460 for (ain = bgp_dest->adj_in; ain; ain = ain->next) {
2b964e86 461 struct bgp_path_info *path =
9bcb3eef 462 bgp_dest_get_bgp_path_info(bgp_dest);
1dacdd8b
MR
463 mpls_label_t *label = NULL;
464 uint32_t num_labels = 0;
465
9b6d8fcf
DS
466 if (path && path->extra) {
467 label = path->extra->label;
468 num_labels = path->extra->num_labels;
1dacdd8b 469 }
73261b47 470 (void)bgp_update(ain->peer, bgp_dest_get_prefix(bgp_dest),
b54892e0
DS
471 ain->addpath_rx_id, ain->attr, afi, safi,
472 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, label,
473 num_labels, 1, NULL);
1dacdd8b
MR
474 }
475}
476
477static void revalidate_all_routes(void)
478{
479 struct bgp *bgp;
480 struct listnode *node;
1dacdd8b
MR
481
482 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
31a2af32
MR
483 struct peer *peer;
484 struct listnode *peer_listnode;
1dacdd8b 485
31a2af32
MR
486 for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
487
d2e3f8a2
DA
488 for (size_t i = 0; i < 2; i++) {
489 safi_t safi;
490 afi_t afi = (i == 0) ? AFI_IP : AFI_IP6;
491
492 for (safi = SAFI_UNICAST; safi < SAFI_MAX;
493 safi++) {
494 if (!peer->bgp->rib[afi][safi])
495 continue;
1dacdd8b 496
d2e3f8a2
DA
497 bgp_soft_reconfig_in(peer, afi, safi);
498 }
1dacdd8b
MR
499 }
500 }
501 }
502}
503
504static void rpki_update_cb_sync_rtr(struct pfx_table *p __attribute__((unused)),
505 const struct pfx_record rec,
506 const bool added __attribute__((unused)))
507{
9ca44fc8
DA
508 if (is_stopping() ||
509 atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst))
1dacdd8b
MR
510 return;
511
512 int retval =
513 write(rpki_sync_socket_rtr, &rec, sizeof(struct pfx_record));
4ce82676
MR
514 if (retval == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
515 atomic_store_explicit(&rtr_update_overflow, 1,
516 memory_order_seq_cst);
517
518 else if (retval != sizeof(struct pfx_record))
1dacdd8b
MR
519 RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
520}
521
522static void rpki_init_sync_socket(void)
523{
524 int fds[2];
4ce82676 525 const char *msg;
1dacdd8b
MR
526
527 RPKI_DEBUG("initializing sync socket");
528 if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, fds) != 0) {
4ce82676
MR
529 msg = "could not open rpki sync socketpair";
530 goto err;
1dacdd8b
MR
531 }
532 rpki_sync_socket_rtr = fds[0];
533 rpki_sync_socket_bgpd = fds[1];
4ce82676
MR
534
535 if (set_nonblocking(rpki_sync_socket_rtr) != 0) {
536 msg = "could not set rpki_sync_socket_rtr to non blocking";
537 goto err;
538 }
539
540 if (set_nonblocking(rpki_sync_socket_bgpd) != 0) {
541 msg = "could not set rpki_sync_socket_bgpd to non blocking";
542 goto err;
543 }
544
d2e3f8a2 545
1dacdd8b 546 thread_add_read(bm->master, bgpd_sync_callback, NULL,
d2e3f8a2 547 rpki_sync_socket_bgpd, NULL);
4ce82676
MR
548
549 return;
550
551err:
552 zlog_err("RPKI: %s", msg);
553 abort();
554
1dacdd8b
MR
555}
556
dabecd7c
MR
557static int bgp_rpki_init(struct thread_master *master)
558{
0e3d96bf
DA
559 rpki_debug = false;
560 rtr_is_running = false;
561 rtr_is_stopping = false;
d67485c6 562 rtr_is_synced = false;
dabecd7c
MR
563
564 cache_list = list_new();
996c9314 565 cache_list->del = (void (*)(void *)) & free_cache;
dabecd7c
MR
566
567 polling_period = POLLING_PERIOD_DEFAULT;
568 expire_interval = EXPIRE_INTERVAL_DEFAULT;
569 retry_interval = RETRY_INTERVAL_DEFAULT;
dabecd7c 570 install_cli_commands();
1dacdd8b 571 rpki_init_sync_socket();
dabecd7c
MR
572 return 0;
573}
574
575static int bgp_rpki_fini(void)
576{
577 stop();
6a154c88 578 list_delete(&cache_list);
dabecd7c 579
1dacdd8b
MR
580 close(rpki_sync_socket_rtr);
581 close(rpki_sync_socket_bgpd);
582
dabecd7c
MR
583 return 0;
584}
585
586static int bgp_rpki_module_init(void)
587{
996c9314 588 lrtr_set_alloc_functions(malloc_wrapper, realloc_wrapper, free_wrapper);
dabecd7c 589
b5b99af8 590 hook_register(bgp_rpki_prefix_status, rpki_validate_prefix);
dabecd7c
MR
591 hook_register(frr_late_init, bgp_rpki_init);
592 hook_register(frr_early_fini, &bgp_rpki_fini);
593
594 return 0;
595}
596
d67485c6 597static void sync_expired(struct thread *thread)
1b2095d1
DA
598{
599 if (!rtr_mgr_conf_in_sync(rtr_config)) {
d67485c6
DA
600 RPKI_DEBUG("rtr_mgr is not synced, retrying.");
601 thread_add_timer(bm->master, sync_expired, NULL,
1b2095d1 602 BGP_RPKI_CACHE_SERVER_SYNC_RETRY_TIMEOUT,
d67485c6 603 &t_rpki_sync);
1b2095d1
DA
604 return;
605 }
606
d67485c6
DA
607 RPKI_DEBUG("rtr_mgr sync is done.");
608
609 rtr_is_synced = true;
1b2095d1
DA
610}
611
dabecd7c
MR
612static int start(void)
613{
dabecd7c
MR
614 int ret;
615
0e3d96bf 616 rtr_is_stopping = false;
d67485c6 617 rtr_is_synced = false;
4ce82676 618 rtr_update_overflow = 0;
1dacdd8b 619
dabecd7c
MR
620 if (list_isempty(cache_list)) {
621 RPKI_DEBUG(
622 "No caches were found in config. Prefix validation is off.");
623 return ERROR;
624 }
625 RPKI_DEBUG("Init rtr_mgr.");
626 int groups_len = listcount(cache_list);
627 struct rtr_mgr_group *groups = get_groups();
628
1dacdd8b 629 RPKI_DEBUG("Polling period: %d", polling_period);
dabecd7c 630 ret = rtr_mgr_init(&rtr_config, groups, groups_len, polling_period,
1dacdd8b 631 expire_interval, retry_interval,
d2e3f8a2 632 rpki_update_cb_sync_rtr, NULL, NULL, NULL);
dabecd7c
MR
633 if (ret == RTR_ERROR) {
634 RPKI_DEBUG("Init rtr_mgr failed.");
635 return ERROR;
636 }
637
638 RPKI_DEBUG("Starting rtr_mgr.");
639 ret = rtr_mgr_start(rtr_config);
640 if (ret == RTR_ERROR) {
641 RPKI_DEBUG("Starting rtr_mgr failed.");
642 rtr_mgr_free(rtr_config);
643 return ERROR;
644 }
1b2095d1 645
d67485c6 646 thread_add_timer(bm->master, sync_expired, NULL, 0, &t_rpki_sync);
dabecd7c
MR
647
648 XFREE(MTYPE_BGP_RPKI_CACHE_GROUP, groups);
649
0e3d96bf 650 rtr_is_running = true;
d67485c6 651
dabecd7c
MR
652 return SUCCESS;
653}
654
655static void stop(void)
656{
0e3d96bf 657 rtr_is_stopping = true;
01fcc189 658 if (is_running()) {
d67485c6 659 THREAD_OFF(t_rpki_sync);
dabecd7c
MR
660 rtr_mgr_stop(rtr_config);
661 rtr_mgr_free(rtr_config);
0e3d96bf 662 rtr_is_running = false;
dabecd7c
MR
663 }
664}
665
666static int reset(bool force)
667{
01fcc189 668 if (is_running() && !force)
dabecd7c
MR
669 return SUCCESS;
670
671 RPKI_DEBUG("Resetting RPKI Session");
672 stop();
673 return start();
674}
675
676static struct rtr_mgr_group *get_connected_group(void)
677{
18b91526 678 if (!cache_list || list_isempty(cache_list))
dabecd7c
MR
679 return NULL;
680
681 return rtr_mgr_get_first_group(rtr_config);
682}
683
dff41cc8
DA
684static void print_prefix_table_by_asn(struct vty *vty, as_t as,
685 json_object *json)
02334bb2
DA
686{
687 unsigned int number_of_ipv4_prefixes = 0;
688 unsigned int number_of_ipv6_prefixes = 0;
689 struct rtr_mgr_group *group = get_connected_group();
690 struct rpki_for_each_record_arg arg;
dff41cc8 691 json_object *json_records = NULL;
02334bb2
DA
692
693 arg.vty = vty;
694 arg.as = as;
dff41cc8 695 arg.json = NULL;
02334bb2
DA
696
697 if (!group) {
dff41cc8
DA
698 if (!json)
699 vty_out(vty, "Cannot find a connected group.\n");
02334bb2
DA
700 return;
701 }
702
703 struct pfx_table *pfx_table = group->sockets[0]->pfx_table;
704
dff41cc8
DA
705 if (!json) {
706 vty_out(vty, "RPKI/RTR prefix table\n");
707 vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length",
708 "Origin-AS");
709 } else {
710 json_records = json_object_new_array();
711 json_object_object_add(json, "prefixes", json_records);
712 arg.json = json_records;
713 }
02334bb2
DA
714
715 arg.prefix_amount = &number_of_ipv4_prefixes;
716 pfx_table_for_each_ipv4_record(pfx_table, print_record_by_asn, &arg);
717
718 arg.prefix_amount = &number_of_ipv6_prefixes;
719 pfx_table_for_each_ipv6_record(pfx_table, print_record_by_asn, &arg);
720
dff41cc8
DA
721 if (!json) {
722 vty_out(vty, "Number of IPv4 Prefixes: %u\n",
723 number_of_ipv4_prefixes);
724 vty_out(vty, "Number of IPv6 Prefixes: %u\n",
725 number_of_ipv6_prefixes);
726 } else {
727 json_object_int_add(json, "ipv4PrefixCount",
728 number_of_ipv4_prefixes);
729 json_object_int_add(json, "ipv6PrefixCount",
730 number_of_ipv6_prefixes);
731 }
732
733 if (json)
734 vty_json(vty, json);
02334bb2
DA
735}
736
dff41cc8 737static void print_prefix_table(struct vty *vty, json_object *json)
dabecd7c
MR
738{
739 struct rpki_for_each_record_arg arg;
740
741 unsigned int number_of_ipv4_prefixes = 0;
742 unsigned int number_of_ipv6_prefixes = 0;
743 struct rtr_mgr_group *group = get_connected_group();
dff41cc8 744 json_object *json_records = NULL;
dabecd7c
MR
745
746 arg.vty = vty;
dff41cc8 747 arg.json = NULL;
dabecd7c 748
dff41cc8
DA
749 if (!group) {
750 if (!json)
751 vty_out(vty, "Cannot find a connected group.\n");
dabecd7c 752 return;
dff41cc8 753 }
dabecd7c
MR
754
755 struct pfx_table *pfx_table = group->sockets[0]->pfx_table;
756
dff41cc8
DA
757 if (!json) {
758 vty_out(vty, "RPKI/RTR prefix table\n");
759 vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length",
760 "Origin-AS");
761 } else {
762 json_records = json_object_new_array();
763 json_object_object_add(json, "prefixes", json_records);
764 arg.json = json_records;
765 }
dabecd7c
MR
766
767 arg.prefix_amount = &number_of_ipv4_prefixes;
5d799192 768 pfx_table_for_each_ipv4_record(pfx_table, print_record_cb, &arg);
dabecd7c
MR
769
770 arg.prefix_amount = &number_of_ipv6_prefixes;
5d799192 771 pfx_table_for_each_ipv6_record(pfx_table, print_record_cb, &arg);
dabecd7c 772
dff41cc8
DA
773 if (!json) {
774 vty_out(vty, "Number of IPv4 Prefixes: %u\n",
775 number_of_ipv4_prefixes);
776 vty_out(vty, "Number of IPv6 Prefixes: %u\n",
777 number_of_ipv6_prefixes);
778 } else {
779 json_object_int_add(json, "ipv4PrefixCount",
780 number_of_ipv4_prefixes);
781 json_object_int_add(json, "ipv6PrefixCount",
782 number_of_ipv6_prefixes);
783 }
784
785 if (json)
786 vty_json(vty, json);
dabecd7c
MR
787}
788
789static int rpki_validate_prefix(struct peer *peer, struct attr *attr,
898c4e66 790 const struct prefix *prefix)
dabecd7c
MR
791{
792 struct assegment *as_segment;
793 as_t as_number = 0;
794 struct lrtr_ip_addr ip_addr_prefix;
795 enum pfxv_state result;
dabecd7c
MR
796
797 if (!is_synchronized())
e1a05dd4 798 return RPKI_NOT_BEING_USED;
dabecd7c
MR
799
800 // No aspath means route comes from iBGP
801 if (!attr->aspath || !attr->aspath->segments) {
802 // Set own as number
803 as_number = peer->bgp->as;
804 } else {
805 as_segment = attr->aspath->segments;
806 // Find last AsSegment
807 while (as_segment->next)
808 as_segment = as_segment->next;
809
810 if (as_segment->type == AS_SEQUENCE) {
811 // Get rightmost asn
812 as_number = as_segment->as[as_segment->length - 1];
996c9314
LB
813 } else if (as_segment->type == AS_CONFED_SEQUENCE
814 || as_segment->type == AS_CONFED_SET) {
dabecd7c
MR
815 // Set own as number
816 as_number = peer->bgp->as;
817 } else {
818 // RFC says: "Take distinguished value NONE as asn"
819 // which means state is unknown
820 return RPKI_NOTFOUND;
821 }
822 }
823
824 // Get the prefix in requested format
825 switch (prefix->family) {
826 case AF_INET:
827 ip_addr_prefix.ver = LRTR_IPV4;
828 ip_addr_prefix.u.addr4.addr = ntohl(prefix->u.prefix4.s_addr);
829 break;
830
dabecd7c
MR
831 case AF_INET6:
832 ip_addr_prefix.ver = LRTR_IPV6;
833 ipv6_addr_to_host_byte_order(prefix->u.prefix6.s6_addr32,
834 ip_addr_prefix.u.addr6.addr);
835 break;
dabecd7c
MR
836
837 default:
e1a05dd4 838 return RPKI_NOT_BEING_USED;
dabecd7c
MR
839 }
840
841 // Do the actual validation
842 rtr_mgr_validate(rtr_config, as_number, &ip_addr_prefix,
843 prefix->prefixlen, &result);
844
845 // Print Debug output
dabecd7c
MR
846 switch (result) {
847 case BGP_PFXV_STATE_VALID:
848 RPKI_DEBUG(
2dbe669b
DA
849 "Validating Prefix %pFX from asn %u Result: VALID",
850 prefix, as_number);
dabecd7c
MR
851 return RPKI_VALID;
852 case BGP_PFXV_STATE_NOT_FOUND:
853 RPKI_DEBUG(
2dbe669b
DA
854 "Validating Prefix %pFX from asn %u Result: NOT FOUND",
855 prefix, as_number);
dabecd7c
MR
856 return RPKI_NOTFOUND;
857 case BGP_PFXV_STATE_INVALID:
858 RPKI_DEBUG(
2dbe669b
DA
859 "Validating Prefix %pFX from asn %u Result: INVALID",
860 prefix, as_number);
dabecd7c
MR
861 return RPKI_INVALID;
862 default:
863 RPKI_DEBUG(
2dbe669b
DA
864 "Validating Prefix %pFX from asn %u Result: CANNOT VALIDATE",
865 prefix, as_number);
dabecd7c
MR
866 break;
867 }
e1a05dd4 868 return RPKI_NOT_BEING_USED;
dabecd7c
MR
869}
870
871static int add_cache(struct cache *cache)
872{
873 uint8_t preference = cache->preference;
874 struct rtr_mgr_group group;
875
876 group.preference = preference;
877 group.sockets_len = 1;
878 group.sockets = &cache->rtr_socket;
879
01fcc189 880 if (is_running()) {
92110aab
MR
881 init_tr_socket(cache);
882
883 if (rtr_mgr_add_group(rtr_config, &group) != RTR_SUCCESS) {
884 free_tr_socket(cache);
885 return ERROR;
886 }
dabecd7c
MR
887 }
888
6893064b
MR
889 listnode_add(cache_list, cache);
890
dabecd7c
MR
891 return SUCCESS;
892}
893
996c9314 894static int add_tcp_cache(const char *host, const char *port,
7253a7bc 895 const uint8_t preference, const char *bindaddr)
dabecd7c
MR
896{
897 struct rtr_socket *rtr_socket;
898 struct tr_tcp_config *tcp_config =
a633498e 899 XCALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_tcp_config));
dabecd7c
MR
900 struct tr_socket *tr_socket =
901 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
902 struct cache *cache =
903 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
904
905 tcp_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
906 tcp_config->port = XSTRDUP(MTYPE_BGP_RPKI_CACHE, port);
7253a7bc
PG
907 if (bindaddr)
908 tcp_config->bindaddr = XSTRDUP(MTYPE_BGP_RPKI_CACHE, bindaddr);
909 else
910 tcp_config->bindaddr = NULL;
dabecd7c
MR
911
912 rtr_socket = create_rtr_socket(tr_socket);
913
914 cache->type = TCP;
915 cache->tr_socket = tr_socket;
916 cache->tr_config.tcp_config = tcp_config;
917 cache->rtr_socket = rtr_socket;
918 cache->preference = preference;
919
6893064b
MR
920 int ret = add_cache(cache);
921 if (ret != SUCCESS) {
922 free_cache(cache);
923 }
924
925 return ret;
dabecd7c
MR
926}
927
928#if defined(FOUND_SSH)
996c9314
LB
929static int add_ssh_cache(const char *host, const unsigned int port,
930 const char *username, const char *client_privkey_path,
dabecd7c
MR
931 const char *client_pubkey_path,
932 const char *server_pubkey_path,
7253a7bc 933 const uint8_t preference, const char *bindaddr)
dabecd7c
MR
934{
935 struct tr_ssh_config *ssh_config =
a633498e 936 XCALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_ssh_config));
dabecd7c
MR
937 struct cache *cache =
938 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
939 struct tr_socket *tr_socket =
940 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
941 struct rtr_socket *rtr_socket;
942
943 ssh_config->port = port;
944 ssh_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
7253a7bc
PG
945 if (bindaddr)
946 ssh_config->bindaddr = XSTRDUP(MTYPE_BGP_RPKI_CACHE, bindaddr);
947 else
948 ssh_config->bindaddr = NULL;
dabecd7c
MR
949
950 ssh_config->username = XSTRDUP(MTYPE_BGP_RPKI_CACHE, username);
996c9314
LB
951 ssh_config->client_privkey_path =
952 XSTRDUP(MTYPE_BGP_RPKI_CACHE, client_privkey_path);
dabecd7c
MR
953 ssh_config->server_hostkey_path =
954 XSTRDUP(MTYPE_BGP_RPKI_CACHE, server_pubkey_path);
955
956 rtr_socket = create_rtr_socket(tr_socket);
957
958 cache->type = SSH;
959 cache->tr_socket = tr_socket;
960 cache->tr_config.ssh_config = ssh_config;
961 cache->rtr_socket = rtr_socket;
962 cache->preference = preference;
963
6893064b
MR
964 int ret = add_cache(cache);
965 if (ret != SUCCESS) {
966 free_cache(cache);
967 }
968
969 return ret;
dabecd7c
MR
970}
971#endif
972
973static void free_cache(struct cache *cache)
974{
975 if (cache->type == TCP) {
996c9314
LB
976 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->host);
977 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->port);
c41a3cc5
DA
978 XFREE(MTYPE_BGP_RPKI_CACHE,
979 cache->tr_config.tcp_config->bindaddr);
dabecd7c
MR
980 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config);
981 }
982#if defined(FOUND_SSH)
983 else {
996c9314 984 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config->host);
dabecd7c
MR
985 XFREE(MTYPE_BGP_RPKI_CACHE,
986 cache->tr_config.ssh_config->username);
987 XFREE(MTYPE_BGP_RPKI_CACHE,
988 cache->tr_config.ssh_config->client_privkey_path);
989 XFREE(MTYPE_BGP_RPKI_CACHE,
990 cache->tr_config.ssh_config->server_hostkey_path);
c41a3cc5
DA
991 XFREE(MTYPE_BGP_RPKI_CACHE,
992 cache->tr_config.ssh_config->bindaddr);
dabecd7c
MR
993 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config);
994 }
995#endif
996 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_socket);
997 XFREE(MTYPE_BGP_RPKI_CACHE, cache->rtr_socket);
998 XFREE(MTYPE_BGP_RPKI_CACHE, cache);
999}
1000
1001static int config_write(struct vty *vty)
1002{
1003 struct listnode *cache_node;
1004 struct cache *cache;
1005
708b8053
DS
1006 if (!listcount(cache_list))
1007 return 0;
1008
1009 if (rpki_debug)
1010 vty_out(vty, "debug rpki\n");
1011
1012 vty_out(vty, "!\n");
1013 vty_out(vty, "rpki\n");
7dc7fb93 1014 vty_out(vty, " rpki polling_period %d\n", polling_period);
9a651153
DS
1015
1016 if (retry_interval != RETRY_INTERVAL_DEFAULT)
1017 vty_out(vty, " rpki retry_interval %d\n", retry_interval);
1018 if (expire_interval != EXPIRE_INTERVAL_DEFAULT)
1019 vty_out(vty, " rpki expire_interval %d\n", expire_interval);
1020
708b8053
DS
1021 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
1022 switch (cache->type) {
1023 struct tr_tcp_config *tcp_config;
acd4a9f4 1024#if defined(FOUND_SSH)
708b8053 1025 struct tr_ssh_config *ssh_config;
acd4a9f4 1026#endif
708b8053
DS
1027 case TCP:
1028 tcp_config = cache->tr_config.tcp_config;
484fc374 1029 vty_out(vty, " rpki cache %s %s ", tcp_config->host,
708b8053 1030 tcp_config->port);
484fc374
IR
1031 if (tcp_config->bindaddr)
1032 vty_out(vty, "source %s ",
1033 tcp_config->bindaddr);
708b8053 1034 break;
dabecd7c 1035#if defined(FOUND_SSH)
708b8053
DS
1036 case SSH:
1037 ssh_config = cache->tr_config.ssh_config;
484fc374
IR
1038 vty_out(vty, " rpki cache %s %u %s %s %s ",
1039 ssh_config->host, ssh_config->port,
1040 ssh_config->username,
708b8053
DS
1041 ssh_config->client_privkey_path,
1042 ssh_config->server_hostkey_path != NULL
1043 ? ssh_config->server_hostkey_path
1044 : " ");
484fc374
IR
1045 if (ssh_config->bindaddr)
1046 vty_out(vty, "source %s ",
1047 ssh_config->bindaddr);
708b8053 1048 break;
dabecd7c 1049#endif
708b8053
DS
1050 default:
1051 break;
dabecd7c 1052 }
708b8053
DS
1053
1054 vty_out(vty, "preference %hhu\n", cache->preference);
dabecd7c 1055 }
07679ad9 1056 vty_out(vty, "exit\n");
708b8053
DS
1057
1058 return 1;
dabecd7c
MR
1059}
1060
1061DEFUN_NOSH (rpki,
1062 rpki_cmd,
1063 "rpki",
1064 "Enable rpki and enter rpki configuration mode\n")
1065{
1066 vty->node = RPKI_NODE;
1067 return CMD_SUCCESS;
1068}
1069
8156765a
DA
1070DEFPY (no_rpki,
1071 no_rpki_cmd,
1072 "no rpki",
1073 NO_STR
1074 "Enable rpki and enter rpki configuration mode\n")
1075{
1076 rpki_delete_all_cache_nodes();
1077 stop();
1078 return CMD_SUCCESS;
1079}
1080
dabecd7c
MR
1081DEFUN (bgp_rpki_start,
1082 bgp_rpki_start_cmd,
1083 "rpki start",
1084 RPKI_OUTPUT_STRING
1085 "start rpki support\n")
1086{
1087 if (listcount(cache_list) == 0)
996c9314
LB
1088 vty_out(vty,
1089 "Could not start rpki because no caches are configured\n");
dabecd7c
MR
1090
1091 if (!is_running()) {
1092 if (start() == ERROR) {
1093 RPKI_DEBUG("RPKI failed to start");
1094 return CMD_WARNING;
1095 }
1096 }
1097 return CMD_SUCCESS;
1098}
1099
1100DEFUN (bgp_rpki_stop,
1101 bgp_rpki_stop_cmd,
1102 "rpki stop",
1103 RPKI_OUTPUT_STRING
1104 "start rpki support\n")
1105{
1106 if (is_running())
1107 stop();
1108
1109 return CMD_SUCCESS;
1110}
1111
1112DEFPY (rpki_polling_period,
1113 rpki_polling_period_cmd,
1114 "rpki polling_period (1-86400)$pp",
1115 RPKI_OUTPUT_STRING
1116 "Set polling period\n"
1117 "Polling period value\n")
1118{
1119 polling_period = pp;
1120 return CMD_SUCCESS;
1121}
1122
1123DEFUN (no_rpki_polling_period,
1124 no_rpki_polling_period_cmd,
e9f709e5 1125 "no rpki polling_period [(1-86400)]",
dabecd7c
MR
1126 NO_STR
1127 RPKI_OUTPUT_STRING
e9f709e5
DS
1128 "Set polling period back to default\n"
1129 "Polling period value\n")
dabecd7c
MR
1130{
1131 polling_period = POLLING_PERIOD_DEFAULT;
1132 return CMD_SUCCESS;
1133}
1134
1135DEFPY (rpki_expire_interval,
1136 rpki_expire_interval_cmd,
1137 "rpki expire_interval (600-172800)$tmp",
1138 RPKI_OUTPUT_STRING
1139 "Set expire interval\n"
1140 "Expire interval value\n")
1141{
6f577f58 1142 if ((unsigned int)tmp >= polling_period) {
dabecd7c
MR
1143 expire_interval = tmp;
1144 return CMD_SUCCESS;
1145 }
1146
1147 vty_out(vty, "%% Expiry interval must be polling period or larger\n");
1148 return CMD_WARNING_CONFIG_FAILED;
1149}
1150
1151DEFUN (no_rpki_expire_interval,
1152 no_rpki_expire_interval_cmd,
e9f709e5 1153 "no rpki expire_interval [(600-172800)]",
dabecd7c
MR
1154 NO_STR
1155 RPKI_OUTPUT_STRING
e9f709e5
DS
1156 "Set expire interval back to default\n"
1157 "Expire interval value\n")
dabecd7c
MR
1158{
1159 expire_interval = polling_period * 2;
1160 return CMD_SUCCESS;
1161}
1162
1163DEFPY (rpki_retry_interval,
1164 rpki_retry_interval_cmd,
1165 "rpki retry_interval (1-7200)$tmp",
1166 RPKI_OUTPUT_STRING
1167 "Set retry interval\n"
1168 "retry interval value\n")
1169{
1170 retry_interval = tmp;
1171 return CMD_SUCCESS;
1172}
1173
1174DEFUN (no_rpki_retry_interval,
1175 no_rpki_retry_interval_cmd,
e9f709e5 1176 "no rpki retry_interval [(1-7200)]",
dabecd7c
MR
1177 NO_STR
1178 RPKI_OUTPUT_STRING
e9f709e5
DS
1179 "Set retry interval back to default\n"
1180 "retry interval value\n")
dabecd7c
MR
1181{
1182 retry_interval = RETRY_INTERVAL_DEFAULT;
1183 return CMD_SUCCESS;
1184}
1185
7253a7bc 1186DEFPY(rpki_cache, rpki_cache_cmd,
484fc374 1187 "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)",
7253a7bc
PG
1188 RPKI_OUTPUT_STRING
1189 "Install a cache server to current group\n"
1190 "IP address of cache server\n Hostname of cache server\n"
7253a7bc
PG
1191 "TCP port number\n"
1192 "SSH port number\n"
1193 "SSH user name\n"
1194 "Path to own SSH private key\n"
1195 "Path to own SSH public key\n"
1196 "Path to Public key of cache server\n"
484fc374
IR
1197 "Configure source IP address of RPKI connection\n"
1198 "Define a Source IP Address\n"
7253a7bc
PG
1199 "Preference of the cache server\n"
1200 "Preference value\n")
dabecd7c 1201{
3f54c705 1202 int return_value;
a2ed7b2b
MR
1203 struct listnode *cache_node;
1204 struct cache *current_cache;
1205
1206 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, current_cache)) {
1207 if (current_cache->preference == preference) {
1208 vty_out(vty,
1209 "Cache with preference %ld is already configured\n",
1210 preference);
1211 return CMD_WARNING;
1212 }
1213 }
1214
dabecd7c
MR
1215
1216 // use ssh connection
1217 if (ssh_uname) {
1218#if defined(FOUND_SSH)
7253a7bc
PG
1219 return_value = add_ssh_cache(
1220 cache, sshport, ssh_uname, ssh_privkey, ssh_pubkey,
1221 server_pubkey, preference, bindaddr_str);
dabecd7c 1222#else
3f54c705 1223 return_value = SUCCESS;
dabecd7c 1224 vty_out(vty,
3efd0893 1225 "ssh sockets are not supported. Please recompile rtrlib and frr with ssh support. If you want to use it\n");
dabecd7c
MR
1226#endif
1227 } else { // use tcp connection
7253a7bc
PG
1228 return_value =
1229 add_tcp_cache(cache, tcpport, preference, bindaddr_str);
dabecd7c
MR
1230 }
1231
1232 if (return_value == ERROR) {
1233 vty_out(vty, "Could not create new rpki cache\n");
1234 return CMD_WARNING;
1235 }
1236
1237 return CMD_SUCCESS;
1238}
1239
1240DEFPY (no_rpki_cache,
1241 no_rpki_cache_cmd,
cc22635a 1242 "no 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)",
dabecd7c
MR
1243 NO_STR
1244 RPKI_OUTPUT_STRING
cc22635a 1245 "Install a cache server to current group\n"
dabecd7c
MR
1246 "IP address of cache server\n Hostname of cache server\n"
1247 "TCP port number\n"
1248 "SSH port number\n"
cc22635a
DA
1249 "SSH user name\n"
1250 "Path to own SSH private key\n"
1251 "Path to own SSH public key\n"
1252 "Path to Public key of cache server\n"
1253 "Configure source IP address of RPKI connection\n"
1254 "Define a Source IP Address\n"
dabecd7c
MR
1255 "Preference of the cache server\n"
1256 "Preference value\n")
1257{
1258 struct cache *cache_p = find_cache(preference);
1259
222487fe 1260 if (!cache_p) {
dabecd7c
MR
1261 vty_out(vty, "Could not find cache %ld\n", preference);
1262 return CMD_WARNING;
1263 }
1264
01fcc189 1265 if (is_running() && listcount(cache_list) == 1) {
8add1719 1266 stop();
01fcc189 1267 } else if (is_running()) {
dabecd7c
MR
1268 if (rtr_mgr_remove_group(rtr_config, preference) == RTR_ERROR) {
1269 vty_out(vty, "Could not remove cache %ld", preference);
dabecd7c
MR
1270
1271 vty_out(vty, "\n");
1272 return CMD_WARNING;
1273 }
1274 }
1275
1276 listnode_delete(cache_list, cache_p);
1277 free_cache(cache_p);
1278
1279 return CMD_SUCCESS;
1280}
1281
dff41cc8 1282DEFPY (show_rpki_prefix_table,
dabecd7c 1283 show_rpki_prefix_table_cmd,
dff41cc8 1284 "show rpki prefix-table [json$uj]",
dabecd7c
MR
1285 SHOW_STR
1286 RPKI_OUTPUT_STRING
dff41cc8
DA
1287 "Show validated prefixes which were received from RPKI Cache\n"
1288 JSON_STR)
dabecd7c 1289{
dff41cc8
DA
1290 struct json_object *json = NULL;
1291
1292 if (!is_synchronized()) {
1293 if (!uj)
1294 vty_out(vty, "No connection to RPKI cache server.\n");
1295 return CMD_WARNING;
1296 }
1297
1298 if (uj)
1299 json = json_object_new_object();
dabecd7c 1300
dff41cc8 1301 print_prefix_table(vty, json);
dabecd7c
MR
1302 return CMD_SUCCESS;
1303}
1304
dff41cc8
DA
1305DEFPY (show_rpki_as_number,
1306 show_rpki_as_number_cmd,
1307 "show rpki as-number (1-4294967295)$by_asn [json$uj]",
1308 SHOW_STR
1309 RPKI_OUTPUT_STRING
1310 "Lookup by ASN in prefix table\n"
1311 "AS Number\n"
1312 JSON_STR)
02334bb2 1313{
dff41cc8
DA
1314 struct json_object *json = NULL;
1315
02334bb2 1316 if (!is_synchronized()) {
dff41cc8
DA
1317 if (!uj)
1318 vty_out(vty, "No Connection to RPKI cache server.\n");
02334bb2
DA
1319 return CMD_WARNING;
1320 }
1321
dff41cc8
DA
1322 if (uj)
1323 json = json_object_new_object();
1324
1325 print_prefix_table_by_asn(vty, by_asn, json);
02334bb2
DA
1326 return CMD_SUCCESS;
1327}
1328
5d799192
MR
1329DEFPY (show_rpki_prefix,
1330 show_rpki_prefix_cmd,
dff41cc8 1331 "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn] [json$uj]",
5d799192
MR
1332 SHOW_STR
1333 RPKI_OUTPUT_STRING
1334 "Lookup IP prefix and optionally ASN in prefix table\n"
1335 "IPv4 prefix\n"
1336 "IPv6 prefix\n"
dff41cc8
DA
1337 "AS Number\n"
1338 JSON_STR)
5d799192 1339{
dff41cc8
DA
1340 json_object *json = NULL;
1341 json_object *json_records = NULL;
5d799192
MR
1342
1343 if (!is_synchronized()) {
dff41cc8
DA
1344 if (!uj)
1345 vty_out(vty, "No Connection to RPKI cache server.\n");
5d799192
MR
1346 return CMD_WARNING;
1347 }
1348
1349 struct lrtr_ip_addr addr;
1350 char addr_str[INET6_ADDRSTRLEN];
1351 size_t addr_len = strchr(prefix_str, '/') - prefix_str;
1352
1353 memset(addr_str, 0, sizeof(addr_str));
1354 memcpy(addr_str, prefix_str, addr_len);
1355
1356 if (lrtr_ip_str_to_addr(addr_str, &addr) != 0) {
dff41cc8
DA
1357 if (!json)
1358 vty_out(vty, "Invalid IP prefix\n");
5d799192
MR
1359 return CMD_WARNING;
1360 }
1361
1362 struct pfx_record *matches = NULL;
1363 unsigned int match_count = 0;
1364 enum pfxv_state result;
1365
1366 if (pfx_table_validate_r(rtr_config->pfx_table, &matches, &match_count,
1367 asn, &addr, prefix->prefixlen, &result)
1368 != PFX_SUCCESS) {
dff41cc8
DA
1369 if (!json)
1370 vty_out(vty, "Prefix lookup failed\n");
5d799192
MR
1371 return CMD_WARNING;
1372 }
1373
dff41cc8
DA
1374 if (uj)
1375 json = json_object_new_object();
1376
1377 if (!json) {
1378 vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length",
1379 "Origin-AS");
1380 } else {
1381 json_records = json_object_new_array();
1382 json_object_object_add(json, "prefixes", json_records);
1383 }
1384
5d799192
MR
1385 for (size_t i = 0; i < match_count; ++i) {
1386 const struct pfx_record *record = &matches[i];
1387
1388 if (record->max_len >= prefix->prefixlen
c17140fd
DS
1389 && ((asn != 0 && (uint32_t)asn == record->asn)
1390 || asn == 0)) {
dff41cc8 1391 print_record(&matches[i], vty, json_records);
5d799192
MR
1392 }
1393 }
1394
dff41cc8
DA
1395 if (json)
1396 vty_json(vty, json);
1397
5d799192
MR
1398 return CMD_SUCCESS;
1399}
1400
cc4d121f 1401DEFPY (show_rpki_cache_server,
dabecd7c 1402 show_rpki_cache_server_cmd,
cc4d121f 1403 "show rpki cache-server [json$uj]",
dabecd7c
MR
1404 SHOW_STR
1405 RPKI_OUTPUT_STRING
cc4d121f
DA
1406 "Show configured cache server\n"
1407 JSON_STR)
dabecd7c 1408{
cc4d121f
DA
1409 struct json_object *json = NULL;
1410 struct json_object *json_server = NULL;
1411 struct json_object *json_servers = NULL;
dabecd7c
MR
1412 struct listnode *cache_node;
1413 struct cache *cache;
1414
cc4d121f
DA
1415 if (uj) {
1416 json = json_object_new_object();
1417 json_servers = json_object_new_array();
1418 json_object_object_add(json, "servers", json_servers);
1419 }
1420
dabecd7c 1421 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
745ae9c0 1422 if (cache->type == TCP) {
cc4d121f
DA
1423 if (!json) {
1424 vty_out(vty, "host: %s port: %s\n",
1425 cache->tr_config.tcp_config->host,
1426 cache->tr_config.tcp_config->port);
1427 } else {
1428 json_server = json_object_new_object();
1429 json_object_string_add(json_server, "mode",
1430 "tcp");
1431 json_object_string_add(
1432 json_server, "host",
1433 cache->tr_config.tcp_config->host);
1434 json_object_string_add(
1435 json_server, "port",
1436 cache->tr_config.tcp_config->port);
1437 json_object_array_add(json_servers,
1438 json_server);
1439 }
745ae9c0 1440
fef6fafa 1441#if defined(FOUND_SSH)
745ae9c0 1442 } else if (cache->type == SSH) {
cc4d121f
DA
1443 if (!json) {
1444 vty_out(vty,
1445 "host: %s port: %d username: %s server_hostkey_path: %s client_privkey_path: %s\n",
1446 cache->tr_config.ssh_config->host,
1447 cache->tr_config.ssh_config->port,
1448 cache->tr_config.ssh_config->username,
1449 cache->tr_config.ssh_config
1450 ->server_hostkey_path,
1451 cache->tr_config.ssh_config
1452 ->client_privkey_path);
1453 } else {
1454 json_server = json_object_new_object();
1455 json_object_string_add(json_server, "mode",
1456 "ssh");
1457 json_object_string_add(
1458 json_server, "host",
1459 cache->tr_config.ssh_config->host);
1460 json_object_int_add(
1461 json_server, "port",
1462 cache->tr_config.ssh_config->port);
1463 json_object_string_add(
1464 json_server, "username",
1465 cache->tr_config.ssh_config->username);
1466 json_object_string_add(
1467 json_server, "serverHostkeyPath",
1468 cache->tr_config.ssh_config
1469 ->server_hostkey_path);
1470 json_object_string_add(
1471 json_server, "clientPrivkeyPath",
1472 cache->tr_config.ssh_config
1473 ->client_privkey_path);
1474 json_object_array_add(json_servers,
1475 json_server);
1476 }
fef6fafa 1477#endif
745ae9c0 1478 }
dabecd7c
MR
1479 }
1480
cc4d121f
DA
1481 if (json)
1482 vty_json(vty, json);
1483
dabecd7c
MR
1484 return CMD_SUCCESS;
1485}
1486
ae872c2f 1487DEFPY (show_rpki_cache_connection,
dabecd7c 1488 show_rpki_cache_connection_cmd,
ae872c2f 1489 "show rpki cache-connection [json$uj]",
dabecd7c
MR
1490 SHOW_STR
1491 RPKI_OUTPUT_STRING
ae872c2f
DA
1492 "Show to which RPKI Cache Servers we have a connection\n"
1493 JSON_STR)
dabecd7c 1494{
ae872c2f
DA
1495 struct json_object *json = NULL;
1496 struct json_object *json_conn = NULL;
1497 struct json_object *json_conns = NULL;
1498 struct listnode *cache_node;
1499 struct cache *cache;
1500 struct rtr_mgr_group *group;
1501
1502 if (uj)
1503 json = json_object_new_object();
1504
708b8053 1505 if (!is_synchronized()) {
ae872c2f
DA
1506 if (!json)
1507 vty_out(vty, "No connection to RPKI cache server.\n");
1508 else
1509 vty_json(vty, json);
708b8053
DS
1510
1511 return CMD_SUCCESS;
1512 }
1513
ae872c2f 1514 group = get_connected_group();
708b8053 1515 if (!group) {
ae872c2f
DA
1516 if (!json)
1517 vty_out(vty, "Cannot find a connected group.\n");
1518 else
1519 vty_json(vty, json);
1520
708b8053
DS
1521 return CMD_SUCCESS;
1522 }
ae872c2f
DA
1523
1524 if (!json) {
1525 vty_out(vty, "Connected to group %d\n", group->preference);
1526 } else {
1527 json_conns = json_object_new_array();
1528 json_object_int_add(json, "connectedGroup", group->preference);
1529 json_object_object_add(json, "connections", json_conns);
1530 }
1531
708b8053 1532 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
c1a68b62 1533 struct tr_tcp_config *tcp_config;
acd4a9f4 1534#if defined(FOUND_SSH)
c1a68b62 1535 struct tr_ssh_config *ssh_config;
acd4a9f4 1536#endif
c1a68b62
DA
1537 switch (cache->type) {
1538 case TCP:
1539 tcp_config = cache->tr_config.tcp_config;
ae872c2f
DA
1540
1541 if (!json) {
1542 vty_out(vty,
1543 "rpki tcp cache %s %s pref %hhu%s\n",
1544 tcp_config->host, tcp_config->port,
1545 cache->preference,
1546 cache->rtr_socket->state ==
1547 RTR_ESTABLISHED
1548 ? " (connected)"
1549 : "");
1550 } else {
1551 json_conn = json_object_new_object();
1552 json_object_string_add(json_conn, "mode",
1553 "tcp");
1554 json_object_string_add(json_conn, "host",
1555 tcp_config->host);
1556 json_object_string_add(json_conn, "port",
1557 tcp_config->port);
1558 json_object_int_add(json_conn, "preference",
1559 cache->preference);
1560 json_object_string_add(
1561 json_conn, "state",
1562 cache->rtr_socket->state ==
1563 RTR_ESTABLISHED
1564 ? "connected"
1565 : "disconnected");
1566 json_object_array_add(json_conns, json_conn);
1567 }
c1a68b62 1568 break;
dabecd7c 1569#if defined(FOUND_SSH)
c1a68b62
DA
1570 case SSH:
1571 ssh_config = cache->tr_config.ssh_config;
ae872c2f
DA
1572
1573 if (!json) {
1574 vty_out(vty,
1575 "rpki ssh cache %s %u pref %hhu%s\n",
1576 ssh_config->host, ssh_config->port,
1577 cache->preference,
1578 cache->rtr_socket->state ==
1579 RTR_ESTABLISHED
1580 ? " (connected)"
1581 : "");
1582 } else {
1583 json_conn = json_object_new_object();
1584 json_object_string_add(json_conn, "mode",
1585 "ssh");
1586 json_object_string_add(json_conn, "host",
1587 ssh_config->host);
4d4b9dc1
DA
1588 json_object_int_add(json_conn, "port",
1589 ssh_config->port);
ae872c2f
DA
1590 json_object_int_add(json_conn, "preference",
1591 cache->preference);
1592 json_object_string_add(
1593 json_conn, "state",
1594 cache->rtr_socket->state ==
1595 RTR_ESTABLISHED
1596 ? "connected"
1597 : "disconnected");
1598 json_object_array_add(json_conns, json_conn);
1599 }
c1a68b62 1600 break;
dabecd7c 1601#endif
c1a68b62
DA
1602 default:
1603 break;
dabecd7c 1604 }
dabecd7c
MR
1605 }
1606
ae872c2f
DA
1607 if (json)
1608 vty_json(vty, json);
1609
dabecd7c
MR
1610 return CMD_SUCCESS;
1611}
1612
791ded4a 1613static int config_on_exit(struct vty *vty)
dabecd7c 1614{
61a484a9 1615 reset(false);
791ded4a 1616 return 1;
dabecd7c
MR
1617}
1618
1619DEFUN (rpki_reset,
1620 rpki_reset_cmd,
1621 "rpki reset",
1622 RPKI_OUTPUT_STRING
1623 "reset rpki\n")
1624{
1625 return reset(true) == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1626}
1627
1628DEFUN (debug_rpki,
1629 debug_rpki_cmd,
1630 "debug rpki",
1631 DEBUG_STR
08f9cfb8 1632 "Enable debugging for rpki\n")
dabecd7c 1633{
0e3d96bf 1634 rpki_debug = true;
dabecd7c
MR
1635 return CMD_SUCCESS;
1636}
1637
1638DEFUN (no_debug_rpki,
1639 no_debug_rpki_cmd,
1640 "no debug rpki",
1641 NO_STR
1642 DEBUG_STR
08f9cfb8 1643 "Disable debugging for rpki\n")
dabecd7c 1644{
0e3d96bf 1645 rpki_debug = false;
dabecd7c
MR
1646 return CMD_SUCCESS;
1647}
1648
48cb7ea9 1649DEFUN_YANG (match_rpki,
dabecd7c
MR
1650 match_rpki_cmd,
1651 "match rpki <valid|invalid|notfound>",
1652 MATCH_STR
1653 RPKI_OUTPUT_STRING
1654 "Valid prefix\n"
1655 "Invalid prefix\n"
1656 "Prefix not found\n")
1657{
48cb7ea9
SP
1658 const char *xpath =
1659 "./match-condition[condition='frr-bgp-route-map:rpki']";
1660 char xpath_value[XPATH_MAXLEN];
69337c34 1661
48cb7ea9
SP
1662 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
1663 snprintf(xpath_value, sizeof(xpath_value),
1664 "%s/rmap-match-condition/frr-bgp-route-map:rpki", xpath);
1665 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[2]->arg);
1666
1667 return nb_cli_apply_changes(vty, NULL);
dabecd7c
MR
1668}
1669
48cb7ea9 1670DEFUN_YANG (no_match_rpki,
dabecd7c
MR
1671 no_match_rpki_cmd,
1672 "no match rpki <valid|invalid|notfound>",
1673 NO_STR
1674 MATCH_STR
1675 RPKI_OUTPUT_STRING
1676 "Valid prefix\n"
1677 "Invalid prefix\n"
1678 "Prefix not found\n")
1679{
48cb7ea9
SP
1680 const char *xpath =
1681 "./match-condition[condition='frr-bgp-route-map:rpki']";
dabecd7c 1682
48cb7ea9
SP
1683 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
1684 return nb_cli_apply_changes(vty, NULL);
dabecd7c
MR
1685}
1686
dabecd7c
MR
1687static void install_cli_commands(void)
1688{
996c9314 1689 // TODO: make config write work
612c2c15 1690 install_node(&rpki_node);
dabecd7c 1691 install_default(RPKI_NODE);
dabecd7c 1692 install_element(CONFIG_NODE, &rpki_cmd);
9593708d 1693 install_element(ENABLE_NODE, &rpki_cmd);
8156765a
DA
1694 install_element(CONFIG_NODE, &no_rpki_cmd);
1695
dabecd7c
MR
1696
1697 install_element(ENABLE_NODE, &bgp_rpki_start_cmd);
1698 install_element(ENABLE_NODE, &bgp_rpki_stop_cmd);
1699
1700 /* Install rpki reset command */
8f14ae47 1701 install_element(ENABLE_NODE, &rpki_reset_cmd);
dabecd7c
MR
1702 install_element(RPKI_NODE, &rpki_reset_cmd);
1703
1704 /* Install rpki polling period commands */
1705 install_element(RPKI_NODE, &rpki_polling_period_cmd);
1706 install_element(RPKI_NODE, &no_rpki_polling_period_cmd);
1707
1708 /* Install rpki expire interval commands */
1709 install_element(RPKI_NODE, &rpki_expire_interval_cmd);
1710 install_element(RPKI_NODE, &no_rpki_expire_interval_cmd);
1711
1712 /* Install rpki retry interval commands */
1713 install_element(RPKI_NODE, &rpki_retry_interval_cmd);
1714 install_element(RPKI_NODE, &no_rpki_retry_interval_cmd);
1715
dabecd7c
MR
1716 /* Install rpki cache commands */
1717 install_element(RPKI_NODE, &rpki_cache_cmd);
1718 install_element(RPKI_NODE, &no_rpki_cache_cmd);
1719
1720 /* Install show commands */
9593708d 1721 install_element(VIEW_NODE, &show_rpki_prefix_table_cmd);
1722 install_element(VIEW_NODE, &show_rpki_cache_connection_cmd);
1723 install_element(VIEW_NODE, &show_rpki_cache_server_cmd);
1724 install_element(VIEW_NODE, &show_rpki_prefix_cmd);
02334bb2 1725 install_element(VIEW_NODE, &show_rpki_as_number_cmd);
dabecd7c
MR
1726
1727 /* Install debug commands */
1728 install_element(CONFIG_NODE, &debug_rpki_cmd);
1729 install_element(ENABLE_NODE, &debug_rpki_cmd);
1730 install_element(CONFIG_NODE, &no_debug_rpki_cmd);
1731 install_element(ENABLE_NODE, &no_debug_rpki_cmd);
1732
1733 /* Install route match */
1734 route_map_install_match(&route_match_rpki_cmd);
1735 install_element(RMAP_NODE, &match_rpki_cmd);
1736 install_element(RMAP_NODE, &no_match_rpki_cmd);
1737}
1738
1739FRR_MODULE_SETUP(.name = "bgpd_rpki", .version = "0.3.6",
1740 .description = "Enable RPKI support for FRR.",
80413c20
DL
1741 .init = bgp_rpki_module_init,
1742);