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