]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_rpki.c
Merge pull request #12084 from ak503/bgp_show_lc
[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 430 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
7e7f61ed
DA
431 struct bgp_table *table = bgp->rib[afi][safi];
432
433 if (!table)
35a1e798 434 continue;
31a2af32 435
35a1e798
DS
436 struct bgp_dest *match;
437 struct bgp_dest *node;
1dacdd8b 438
7e7f61ed 439 match = bgp_table_subtree_lookup(table, prefix);
35a1e798 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 }
7e7f61ed
DA
449
450 if (match)
451 bgp_dest_unlock_node(match);
1dacdd8b
MR
452 }
453 }
454
45206fe2 455 prefix_free(&prefix);
1dacdd8b
MR
456}
457
9bcb3eef 458static void revalidate_bgp_node(struct bgp_dest *bgp_dest, afi_t afi,
1dacdd8b
MR
459 safi_t safi)
460{
461 struct bgp_adj_in *ain;
462
9bcb3eef 463 for (ain = bgp_dest->adj_in; ain; ain = ain->next) {
2b964e86 464 struct bgp_path_info *path =
9bcb3eef 465 bgp_dest_get_bgp_path_info(bgp_dest);
1dacdd8b
MR
466 mpls_label_t *label = NULL;
467 uint32_t num_labels = 0;
468
9b6d8fcf
DS
469 if (path && path->extra) {
470 label = path->extra->label;
471 num_labels = path->extra->num_labels;
1dacdd8b 472 }
73261b47 473 (void)bgp_update(ain->peer, bgp_dest_get_prefix(bgp_dest),
b54892e0
DS
474 ain->addpath_rx_id, ain->attr, afi, safi,
475 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, label,
476 num_labels, 1, NULL);
1dacdd8b
MR
477 }
478}
479
480static void revalidate_all_routes(void)
481{
482 struct bgp *bgp;
483 struct listnode *node;
1dacdd8b
MR
484
485 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
31a2af32
MR
486 struct peer *peer;
487 struct listnode *peer_listnode;
1dacdd8b 488
31a2af32
MR
489 for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
490
d2e3f8a2
DA
491 for (size_t i = 0; i < 2; i++) {
492 safi_t safi;
493 afi_t afi = (i == 0) ? AFI_IP : AFI_IP6;
494
495 for (safi = SAFI_UNICAST; safi < SAFI_MAX;
496 safi++) {
497 if (!peer->bgp->rib[afi][safi])
498 continue;
1dacdd8b 499
d2e3f8a2
DA
500 bgp_soft_reconfig_in(peer, afi, safi);
501 }
1dacdd8b
MR
502 }
503 }
504 }
505}
506
507static void rpki_update_cb_sync_rtr(struct pfx_table *p __attribute__((unused)),
508 const struct pfx_record rec,
509 const bool added __attribute__((unused)))
510{
9ca44fc8
DA
511 if (is_stopping() ||
512 atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst))
1dacdd8b
MR
513 return;
514
515 int retval =
516 write(rpki_sync_socket_rtr, &rec, sizeof(struct pfx_record));
4ce82676
MR
517 if (retval == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
518 atomic_store_explicit(&rtr_update_overflow, 1,
519 memory_order_seq_cst);
520
521 else if (retval != sizeof(struct pfx_record))
1dacdd8b
MR
522 RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
523}
524
525static void rpki_init_sync_socket(void)
526{
527 int fds[2];
4ce82676 528 const char *msg;
1dacdd8b
MR
529
530 RPKI_DEBUG("initializing sync socket");
531 if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, fds) != 0) {
4ce82676
MR
532 msg = "could not open rpki sync socketpair";
533 goto err;
1dacdd8b
MR
534 }
535 rpki_sync_socket_rtr = fds[0];
536 rpki_sync_socket_bgpd = fds[1];
4ce82676
MR
537
538 if (set_nonblocking(rpki_sync_socket_rtr) != 0) {
539 msg = "could not set rpki_sync_socket_rtr to non blocking";
540 goto err;
541 }
542
543 if (set_nonblocking(rpki_sync_socket_bgpd) != 0) {
544 msg = "could not set rpki_sync_socket_bgpd to non blocking";
545 goto err;
546 }
547
d2e3f8a2 548
1dacdd8b 549 thread_add_read(bm->master, bgpd_sync_callback, NULL,
d2e3f8a2 550 rpki_sync_socket_bgpd, NULL);
4ce82676
MR
551
552 return;
553
554err:
555 zlog_err("RPKI: %s", msg);
556 abort();
557
1dacdd8b
MR
558}
559
dabecd7c
MR
560static int bgp_rpki_init(struct thread_master *master)
561{
0e3d96bf
DA
562 rpki_debug = false;
563 rtr_is_running = false;
564 rtr_is_stopping = false;
d67485c6 565 rtr_is_synced = false;
dabecd7c
MR
566
567 cache_list = list_new();
996c9314 568 cache_list->del = (void (*)(void *)) & free_cache;
dabecd7c
MR
569
570 polling_period = POLLING_PERIOD_DEFAULT;
571 expire_interval = EXPIRE_INTERVAL_DEFAULT;
572 retry_interval = RETRY_INTERVAL_DEFAULT;
dabecd7c 573 install_cli_commands();
1dacdd8b 574 rpki_init_sync_socket();
dabecd7c
MR
575 return 0;
576}
577
578static int bgp_rpki_fini(void)
579{
580 stop();
6a154c88 581 list_delete(&cache_list);
dabecd7c 582
1dacdd8b
MR
583 close(rpki_sync_socket_rtr);
584 close(rpki_sync_socket_bgpd);
585
dabecd7c
MR
586 return 0;
587}
588
589static int bgp_rpki_module_init(void)
590{
996c9314 591 lrtr_set_alloc_functions(malloc_wrapper, realloc_wrapper, free_wrapper);
dabecd7c 592
b5b99af8 593 hook_register(bgp_rpki_prefix_status, rpki_validate_prefix);
dabecd7c 594 hook_register(frr_late_init, bgp_rpki_init);
f714e57a 595 hook_register(frr_early_fini, bgp_rpki_fini);
dabecd7c
MR
596
597 return 0;
598}
599
d67485c6 600static void sync_expired(struct thread *thread)
1b2095d1
DA
601{
602 if (!rtr_mgr_conf_in_sync(rtr_config)) {
d67485c6
DA
603 RPKI_DEBUG("rtr_mgr is not synced, retrying.");
604 thread_add_timer(bm->master, sync_expired, NULL,
1b2095d1 605 BGP_RPKI_CACHE_SERVER_SYNC_RETRY_TIMEOUT,
d67485c6 606 &t_rpki_sync);
1b2095d1
DA
607 return;
608 }
609
d67485c6
DA
610 RPKI_DEBUG("rtr_mgr sync is done.");
611
612 rtr_is_synced = true;
1b2095d1
DA
613}
614
dabecd7c
MR
615static int start(void)
616{
dabecd7c
MR
617 int ret;
618
0e3d96bf 619 rtr_is_stopping = false;
d67485c6 620 rtr_is_synced = false;
4ce82676 621 rtr_update_overflow = 0;
1dacdd8b 622
dabecd7c
MR
623 if (list_isempty(cache_list)) {
624 RPKI_DEBUG(
625 "No caches were found in config. Prefix validation is off.");
626 return ERROR;
627 }
628 RPKI_DEBUG("Init rtr_mgr.");
629 int groups_len = listcount(cache_list);
630 struct rtr_mgr_group *groups = get_groups();
631
1dacdd8b 632 RPKI_DEBUG("Polling period: %d", polling_period);
dabecd7c 633 ret = rtr_mgr_init(&rtr_config, groups, groups_len, polling_period,
1dacdd8b 634 expire_interval, retry_interval,
d2e3f8a2 635 rpki_update_cb_sync_rtr, NULL, NULL, NULL);
dabecd7c
MR
636 if (ret == RTR_ERROR) {
637 RPKI_DEBUG("Init rtr_mgr failed.");
638 return ERROR;
639 }
640
641 RPKI_DEBUG("Starting rtr_mgr.");
642 ret = rtr_mgr_start(rtr_config);
643 if (ret == RTR_ERROR) {
644 RPKI_DEBUG("Starting rtr_mgr failed.");
645 rtr_mgr_free(rtr_config);
646 return ERROR;
647 }
1b2095d1 648
d67485c6 649 thread_add_timer(bm->master, sync_expired, NULL, 0, &t_rpki_sync);
dabecd7c
MR
650
651 XFREE(MTYPE_BGP_RPKI_CACHE_GROUP, groups);
652
0e3d96bf 653 rtr_is_running = true;
d67485c6 654
dabecd7c
MR
655 return SUCCESS;
656}
657
658static void stop(void)
659{
0e3d96bf 660 rtr_is_stopping = true;
01fcc189 661 if (is_running()) {
d67485c6 662 THREAD_OFF(t_rpki_sync);
dabecd7c
MR
663 rtr_mgr_stop(rtr_config);
664 rtr_mgr_free(rtr_config);
0e3d96bf 665 rtr_is_running = false;
dabecd7c
MR
666 }
667}
668
669static int reset(bool force)
670{
01fcc189 671 if (is_running() && !force)
dabecd7c
MR
672 return SUCCESS;
673
674 RPKI_DEBUG("Resetting RPKI Session");
675 stop();
676 return start();
677}
678
679static struct rtr_mgr_group *get_connected_group(void)
680{
18b91526 681 if (!cache_list || list_isempty(cache_list))
dabecd7c
MR
682 return NULL;
683
684 return rtr_mgr_get_first_group(rtr_config);
685}
686
dff41cc8
DA
687static void print_prefix_table_by_asn(struct vty *vty, as_t as,
688 json_object *json)
02334bb2
DA
689{
690 unsigned int number_of_ipv4_prefixes = 0;
691 unsigned int number_of_ipv6_prefixes = 0;
692 struct rtr_mgr_group *group = get_connected_group();
693 struct rpki_for_each_record_arg arg;
dff41cc8 694 json_object *json_records = NULL;
02334bb2
DA
695
696 arg.vty = vty;
697 arg.as = as;
dff41cc8 698 arg.json = NULL;
02334bb2
DA
699
700 if (!group) {
dff41cc8
DA
701 if (!json)
702 vty_out(vty, "Cannot find a connected group.\n");
02334bb2
DA
703 return;
704 }
705
706 struct pfx_table *pfx_table = group->sockets[0]->pfx_table;
707
dff41cc8
DA
708 if (!json) {
709 vty_out(vty, "RPKI/RTR prefix table\n");
710 vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length",
711 "Origin-AS");
712 } else {
713 json_records = json_object_new_array();
714 json_object_object_add(json, "prefixes", json_records);
715 arg.json = json_records;
716 }
02334bb2
DA
717
718 arg.prefix_amount = &number_of_ipv4_prefixes;
719 pfx_table_for_each_ipv4_record(pfx_table, print_record_by_asn, &arg);
720
721 arg.prefix_amount = &number_of_ipv6_prefixes;
722 pfx_table_for_each_ipv6_record(pfx_table, print_record_by_asn, &arg);
723
dff41cc8
DA
724 if (!json) {
725 vty_out(vty, "Number of IPv4 Prefixes: %u\n",
726 number_of_ipv4_prefixes);
727 vty_out(vty, "Number of IPv6 Prefixes: %u\n",
728 number_of_ipv6_prefixes);
729 } else {
730 json_object_int_add(json, "ipv4PrefixCount",
731 number_of_ipv4_prefixes);
732 json_object_int_add(json, "ipv6PrefixCount",
733 number_of_ipv6_prefixes);
734 }
735
736 if (json)
737 vty_json(vty, json);
02334bb2
DA
738}
739
dff41cc8 740static void print_prefix_table(struct vty *vty, json_object *json)
dabecd7c
MR
741{
742 struct rpki_for_each_record_arg arg;
743
744 unsigned int number_of_ipv4_prefixes = 0;
745 unsigned int number_of_ipv6_prefixes = 0;
746 struct rtr_mgr_group *group = get_connected_group();
dff41cc8 747 json_object *json_records = NULL;
dabecd7c
MR
748
749 arg.vty = vty;
dff41cc8 750 arg.json = NULL;
dabecd7c 751
dff41cc8
DA
752 if (!group) {
753 if (!json)
754 vty_out(vty, "Cannot find a connected group.\n");
dabecd7c 755 return;
dff41cc8 756 }
dabecd7c
MR
757
758 struct pfx_table *pfx_table = group->sockets[0]->pfx_table;
759
dff41cc8
DA
760 if (!json) {
761 vty_out(vty, "RPKI/RTR prefix table\n");
762 vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length",
763 "Origin-AS");
764 } else {
765 json_records = json_object_new_array();
766 json_object_object_add(json, "prefixes", json_records);
767 arg.json = json_records;
768 }
dabecd7c
MR
769
770 arg.prefix_amount = &number_of_ipv4_prefixes;
5d799192 771 pfx_table_for_each_ipv4_record(pfx_table, print_record_cb, &arg);
dabecd7c
MR
772
773 arg.prefix_amount = &number_of_ipv6_prefixes;
5d799192 774 pfx_table_for_each_ipv6_record(pfx_table, print_record_cb, &arg);
dabecd7c 775
dff41cc8
DA
776 if (!json) {
777 vty_out(vty, "Number of IPv4 Prefixes: %u\n",
778 number_of_ipv4_prefixes);
779 vty_out(vty, "Number of IPv6 Prefixes: %u\n",
780 number_of_ipv6_prefixes);
781 } else {
782 json_object_int_add(json, "ipv4PrefixCount",
783 number_of_ipv4_prefixes);
784 json_object_int_add(json, "ipv6PrefixCount",
785 number_of_ipv6_prefixes);
786 }
787
788 if (json)
789 vty_json(vty, json);
dabecd7c
MR
790}
791
792static int rpki_validate_prefix(struct peer *peer, struct attr *attr,
898c4e66 793 const struct prefix *prefix)
dabecd7c
MR
794{
795 struct assegment *as_segment;
796 as_t as_number = 0;
797 struct lrtr_ip_addr ip_addr_prefix;
798 enum pfxv_state result;
dabecd7c
MR
799
800 if (!is_synchronized())
e1a05dd4 801 return RPKI_NOT_BEING_USED;
dabecd7c
MR
802
803 // No aspath means route comes from iBGP
804 if (!attr->aspath || !attr->aspath->segments) {
805 // Set own as number
806 as_number = peer->bgp->as;
807 } else {
808 as_segment = attr->aspath->segments;
809 // Find last AsSegment
810 while (as_segment->next)
811 as_segment = as_segment->next;
812
813 if (as_segment->type == AS_SEQUENCE) {
814 // Get rightmost asn
815 as_number = as_segment->as[as_segment->length - 1];
996c9314
LB
816 } else if (as_segment->type == AS_CONFED_SEQUENCE
817 || as_segment->type == AS_CONFED_SET) {
dabecd7c
MR
818 // Set own as number
819 as_number = peer->bgp->as;
820 } else {
821 // RFC says: "Take distinguished value NONE as asn"
822 // which means state is unknown
823 return RPKI_NOTFOUND;
824 }
825 }
826
827 // Get the prefix in requested format
828 switch (prefix->family) {
829 case AF_INET:
830 ip_addr_prefix.ver = LRTR_IPV4;
831 ip_addr_prefix.u.addr4.addr = ntohl(prefix->u.prefix4.s_addr);
832 break;
833
dabecd7c
MR
834 case AF_INET6:
835 ip_addr_prefix.ver = LRTR_IPV6;
836 ipv6_addr_to_host_byte_order(prefix->u.prefix6.s6_addr32,
837 ip_addr_prefix.u.addr6.addr);
838 break;
dabecd7c
MR
839
840 default:
e1a05dd4 841 return RPKI_NOT_BEING_USED;
dabecd7c
MR
842 }
843
844 // Do the actual validation
845 rtr_mgr_validate(rtr_config, as_number, &ip_addr_prefix,
846 prefix->prefixlen, &result);
847
848 // Print Debug output
dabecd7c
MR
849 switch (result) {
850 case BGP_PFXV_STATE_VALID:
851 RPKI_DEBUG(
2dbe669b
DA
852 "Validating Prefix %pFX from asn %u Result: VALID",
853 prefix, as_number);
dabecd7c
MR
854 return RPKI_VALID;
855 case BGP_PFXV_STATE_NOT_FOUND:
856 RPKI_DEBUG(
2dbe669b
DA
857 "Validating Prefix %pFX from asn %u Result: NOT FOUND",
858 prefix, as_number);
dabecd7c
MR
859 return RPKI_NOTFOUND;
860 case BGP_PFXV_STATE_INVALID:
861 RPKI_DEBUG(
2dbe669b
DA
862 "Validating Prefix %pFX from asn %u Result: INVALID",
863 prefix, as_number);
dabecd7c
MR
864 return RPKI_INVALID;
865 default:
866 RPKI_DEBUG(
2dbe669b
DA
867 "Validating Prefix %pFX from asn %u Result: CANNOT VALIDATE",
868 prefix, as_number);
dabecd7c
MR
869 break;
870 }
e1a05dd4 871 return RPKI_NOT_BEING_USED;
dabecd7c
MR
872}
873
874static int add_cache(struct cache *cache)
875{
876 uint8_t preference = cache->preference;
877 struct rtr_mgr_group group;
878
879 group.preference = preference;
880 group.sockets_len = 1;
881 group.sockets = &cache->rtr_socket;
882
01fcc189 883 if (is_running()) {
92110aab
MR
884 init_tr_socket(cache);
885
886 if (rtr_mgr_add_group(rtr_config, &group) != RTR_SUCCESS) {
887 free_tr_socket(cache);
888 return ERROR;
889 }
dabecd7c
MR
890 }
891
6893064b
MR
892 listnode_add(cache_list, cache);
893
dabecd7c
MR
894 return SUCCESS;
895}
896
996c9314 897static int add_tcp_cache(const char *host, const char *port,
7253a7bc 898 const uint8_t preference, const char *bindaddr)
dabecd7c
MR
899{
900 struct rtr_socket *rtr_socket;
901 struct tr_tcp_config *tcp_config =
a633498e 902 XCALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_tcp_config));
dabecd7c
MR
903 struct tr_socket *tr_socket =
904 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
905 struct cache *cache =
906 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
907
908 tcp_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
909 tcp_config->port = XSTRDUP(MTYPE_BGP_RPKI_CACHE, port);
7253a7bc
PG
910 if (bindaddr)
911 tcp_config->bindaddr = XSTRDUP(MTYPE_BGP_RPKI_CACHE, bindaddr);
912 else
913 tcp_config->bindaddr = NULL;
dabecd7c
MR
914
915 rtr_socket = create_rtr_socket(tr_socket);
916
917 cache->type = TCP;
918 cache->tr_socket = tr_socket;
919 cache->tr_config.tcp_config = tcp_config;
920 cache->rtr_socket = rtr_socket;
921 cache->preference = preference;
922
6893064b
MR
923 int ret = add_cache(cache);
924 if (ret != SUCCESS) {
925 free_cache(cache);
926 }
927
928 return ret;
dabecd7c
MR
929}
930
931#if defined(FOUND_SSH)
996c9314
LB
932static int add_ssh_cache(const char *host, const unsigned int port,
933 const char *username, const char *client_privkey_path,
dabecd7c 934 const char *server_pubkey_path,
7253a7bc 935 const uint8_t preference, const char *bindaddr)
dabecd7c
MR
936{
937 struct tr_ssh_config *ssh_config =
a633498e 938 XCALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_ssh_config));
dabecd7c
MR
939 struct cache *cache =
940 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
941 struct tr_socket *tr_socket =
942 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
943 struct rtr_socket *rtr_socket;
944
945 ssh_config->port = port;
946 ssh_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
7253a7bc
PG
947 if (bindaddr)
948 ssh_config->bindaddr = XSTRDUP(MTYPE_BGP_RPKI_CACHE, bindaddr);
949 else
950 ssh_config->bindaddr = NULL;
dabecd7c
MR
951
952 ssh_config->username = XSTRDUP(MTYPE_BGP_RPKI_CACHE, username);
996c9314
LB
953 ssh_config->client_privkey_path =
954 XSTRDUP(MTYPE_BGP_RPKI_CACHE, client_privkey_path);
dabecd7c
MR
955 ssh_config->server_hostkey_path =
956 XSTRDUP(MTYPE_BGP_RPKI_CACHE, server_pubkey_path);
957
958 rtr_socket = create_rtr_socket(tr_socket);
959
960 cache->type = SSH;
961 cache->tr_socket = tr_socket;
962 cache->tr_config.ssh_config = ssh_config;
963 cache->rtr_socket = rtr_socket;
964 cache->preference = preference;
965
6893064b
MR
966 int ret = add_cache(cache);
967 if (ret != SUCCESS) {
968 free_cache(cache);
969 }
970
971 return ret;
dabecd7c
MR
972}
973#endif
974
975static void free_cache(struct cache *cache)
976{
977 if (cache->type == TCP) {
996c9314
LB
978 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->host);
979 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->port);
c41a3cc5
DA
980 XFREE(MTYPE_BGP_RPKI_CACHE,
981 cache->tr_config.tcp_config->bindaddr);
dabecd7c
MR
982 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config);
983 }
984#if defined(FOUND_SSH)
985 else {
996c9314 986 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config->host);
dabecd7c
MR
987 XFREE(MTYPE_BGP_RPKI_CACHE,
988 cache->tr_config.ssh_config->username);
989 XFREE(MTYPE_BGP_RPKI_CACHE,
990 cache->tr_config.ssh_config->client_privkey_path);
991 XFREE(MTYPE_BGP_RPKI_CACHE,
992 cache->tr_config.ssh_config->server_hostkey_path);
c41a3cc5
DA
993 XFREE(MTYPE_BGP_RPKI_CACHE,
994 cache->tr_config.ssh_config->bindaddr);
dabecd7c
MR
995 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config);
996 }
997#endif
998 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_socket);
999 XFREE(MTYPE_BGP_RPKI_CACHE, cache->rtr_socket);
1000 XFREE(MTYPE_BGP_RPKI_CACHE, cache);
1001}
1002
1003static int config_write(struct vty *vty)
1004{
1005 struct listnode *cache_node;
1006 struct cache *cache;
1007
708b8053
DS
1008 if (rpki_debug)
1009 vty_out(vty, "debug rpki\n");
1010
1011 vty_out(vty, "!\n");
1012 vty_out(vty, "rpki\n");
9a651153 1013
8f401cda
DA
1014 if (polling_period != POLLING_PERIOD_DEFAULT)
1015 vty_out(vty, " rpki polling_period %d\n", polling_period);
9a651153
DS
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,
2a5f5ec0 1187 "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
1188 RPKI_OUTPUT_STRING
1189 "Install a cache server to current group\n"
2a5f5ec0
DA
1190 "IP address of cache server\n"
1191 "Hostname of cache server\n"
7253a7bc
PG
1192 "TCP port number\n"
1193 "SSH port number\n"
1194 "SSH user name\n"
1195 "Path to own SSH private key\n"
7253a7bc 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)
2a5f5ec0
DA
1219 return_value =
1220 add_ssh_cache(cache, sshport, ssh_uname, ssh_privkey,
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,
2a5f5ec0 1242 "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
1243 NO_STR
1244 RPKI_OUTPUT_STRING
cc22635a 1245 "Install a cache server to current group\n"
2a5f5ec0
DA
1246 "IP address of cache server\n"
1247 "Hostname of cache server\n"
dabecd7c
MR
1248 "TCP port number\n"
1249 "SSH port number\n"
cc22635a
DA
1250 "SSH user name\n"
1251 "Path to own SSH private key\n"
cc22635a
DA
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) {
11423e50
DA
1261 vty_out(vty, "Could not find cache with preference %ld\n",
1262 preference);
dabecd7c
MR
1263 return CMD_WARNING;
1264 }
1265
01fcc189 1266 if (is_running() && listcount(cache_list) == 1) {
8add1719 1267 stop();
01fcc189 1268 } else if (is_running()) {
dabecd7c 1269 if (rtr_mgr_remove_group(rtr_config, preference) == RTR_ERROR) {
11423e50
DA
1270 vty_out(vty,
1271 "Could not remove cache with preference %ld\n",
1272 preference);
dabecd7c
MR
1273 return CMD_WARNING;
1274 }
1275 }
1276
1277 listnode_delete(cache_list, cache_p);
1278 free_cache(cache_p);
1279
1280 return CMD_SUCCESS;
1281}
1282
dff41cc8 1283DEFPY (show_rpki_prefix_table,
dabecd7c 1284 show_rpki_prefix_table_cmd,
dff41cc8 1285 "show rpki prefix-table [json$uj]",
dabecd7c
MR
1286 SHOW_STR
1287 RPKI_OUTPUT_STRING
dff41cc8
DA
1288 "Show validated prefixes which were received from RPKI Cache\n"
1289 JSON_STR)
dabecd7c 1290{
dff41cc8
DA
1291 struct json_object *json = NULL;
1292
1293 if (!is_synchronized()) {
1294 if (!uj)
1295 vty_out(vty, "No connection to RPKI cache server.\n");
1296 return CMD_WARNING;
1297 }
1298
1299 if (uj)
1300 json = json_object_new_object();
dabecd7c 1301
dff41cc8 1302 print_prefix_table(vty, json);
dabecd7c
MR
1303 return CMD_SUCCESS;
1304}
1305
dff41cc8
DA
1306DEFPY (show_rpki_as_number,
1307 show_rpki_as_number_cmd,
1308 "show rpki as-number (1-4294967295)$by_asn [json$uj]",
1309 SHOW_STR
1310 RPKI_OUTPUT_STRING
1311 "Lookup by ASN in prefix table\n"
1312 "AS Number\n"
1313 JSON_STR)
02334bb2 1314{
dff41cc8
DA
1315 struct json_object *json = NULL;
1316
02334bb2 1317 if (!is_synchronized()) {
dff41cc8
DA
1318 if (!uj)
1319 vty_out(vty, "No Connection to RPKI cache server.\n");
02334bb2
DA
1320 return CMD_WARNING;
1321 }
1322
dff41cc8
DA
1323 if (uj)
1324 json = json_object_new_object();
1325
1326 print_prefix_table_by_asn(vty, by_asn, json);
02334bb2
DA
1327 return CMD_SUCCESS;
1328}
1329
5d799192
MR
1330DEFPY (show_rpki_prefix,
1331 show_rpki_prefix_cmd,
dff41cc8 1332 "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn] [json$uj]",
5d799192
MR
1333 SHOW_STR
1334 RPKI_OUTPUT_STRING
1335 "Lookup IP prefix and optionally ASN in prefix table\n"
1336 "IPv4 prefix\n"
1337 "IPv6 prefix\n"
dff41cc8
DA
1338 "AS Number\n"
1339 JSON_STR)
5d799192 1340{
dff41cc8
DA
1341 json_object *json = NULL;
1342 json_object *json_records = NULL;
5d799192
MR
1343
1344 if (!is_synchronized()) {
dff41cc8
DA
1345 if (!uj)
1346 vty_out(vty, "No Connection to RPKI cache server.\n");
5d799192
MR
1347 return CMD_WARNING;
1348 }
1349
1350 struct lrtr_ip_addr addr;
1351 char addr_str[INET6_ADDRSTRLEN];
1352 size_t addr_len = strchr(prefix_str, '/') - prefix_str;
1353
1354 memset(addr_str, 0, sizeof(addr_str));
1355 memcpy(addr_str, prefix_str, addr_len);
1356
1357 if (lrtr_ip_str_to_addr(addr_str, &addr) != 0) {
dff41cc8
DA
1358 if (!json)
1359 vty_out(vty, "Invalid IP prefix\n");
5d799192
MR
1360 return CMD_WARNING;
1361 }
1362
1363 struct pfx_record *matches = NULL;
1364 unsigned int match_count = 0;
1365 enum pfxv_state result;
1366
1367 if (pfx_table_validate_r(rtr_config->pfx_table, &matches, &match_count,
1368 asn, &addr, prefix->prefixlen, &result)
1369 != PFX_SUCCESS) {
dff41cc8
DA
1370 if (!json)
1371 vty_out(vty, "Prefix lookup failed\n");
5d799192
MR
1372 return CMD_WARNING;
1373 }
1374
dff41cc8
DA
1375 if (uj)
1376 json = json_object_new_object();
1377
1378 if (!json) {
1379 vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length",
1380 "Origin-AS");
1381 } else {
1382 json_records = json_object_new_array();
1383 json_object_object_add(json, "prefixes", json_records);
1384 }
1385
5d799192
MR
1386 for (size_t i = 0; i < match_count; ++i) {
1387 const struct pfx_record *record = &matches[i];
1388
1389 if (record->max_len >= prefix->prefixlen
c17140fd
DS
1390 && ((asn != 0 && (uint32_t)asn == record->asn)
1391 || asn == 0)) {
dff41cc8 1392 print_record(&matches[i], vty, json_records);
5d799192
MR
1393 }
1394 }
1395
dff41cc8
DA
1396 if (json)
1397 vty_json(vty, json);
1398
5d799192
MR
1399 return CMD_SUCCESS;
1400}
1401
cc4d121f 1402DEFPY (show_rpki_cache_server,
dabecd7c 1403 show_rpki_cache_server_cmd,
cc4d121f 1404 "show rpki cache-server [json$uj]",
dabecd7c
MR
1405 SHOW_STR
1406 RPKI_OUTPUT_STRING
cc4d121f
DA
1407 "Show configured cache server\n"
1408 JSON_STR)
dabecd7c 1409{
cc4d121f
DA
1410 struct json_object *json = NULL;
1411 struct json_object *json_server = NULL;
1412 struct json_object *json_servers = NULL;
dabecd7c
MR
1413 struct listnode *cache_node;
1414 struct cache *cache;
1415
cc4d121f
DA
1416 if (uj) {
1417 json = json_object_new_object();
1418 json_servers = json_object_new_array();
1419 json_object_object_add(json, "servers", json_servers);
1420 }
1421
dabecd7c 1422 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
745ae9c0 1423 if (cache->type == TCP) {
cc4d121f 1424 if (!json) {
77be6d6a
DA
1425 vty_out(vty,
1426 "host: %s port: %s, preference: %hhu\n",
cc4d121f 1427 cache->tr_config.tcp_config->host,
77be6d6a
DA
1428 cache->tr_config.tcp_config->port,
1429 cache->preference);
cc4d121f
DA
1430 } else {
1431 json_server = json_object_new_object();
1432 json_object_string_add(json_server, "mode",
1433 "tcp");
1434 json_object_string_add(
1435 json_server, "host",
1436 cache->tr_config.tcp_config->host);
1437 json_object_string_add(
1438 json_server, "port",
1439 cache->tr_config.tcp_config->port);
77be6d6a
DA
1440 json_object_int_add(json_server, "preference",
1441 cache->preference);
cc4d121f
DA
1442 json_object_array_add(json_servers,
1443 json_server);
1444 }
745ae9c0 1445
fef6fafa 1446#if defined(FOUND_SSH)
745ae9c0 1447 } else if (cache->type == SSH) {
cc4d121f
DA
1448 if (!json) {
1449 vty_out(vty,
77be6d6a 1450 "host: %s port: %d username: %s server_hostkey_path: %s client_privkey_path: %s, preference: %hhu\n",
cc4d121f
DA
1451 cache->tr_config.ssh_config->host,
1452 cache->tr_config.ssh_config->port,
1453 cache->tr_config.ssh_config->username,
1454 cache->tr_config.ssh_config
1455 ->server_hostkey_path,
1456 cache->tr_config.ssh_config
77be6d6a
DA
1457 ->client_privkey_path,
1458 cache->preference);
cc4d121f
DA
1459 } else {
1460 json_server = json_object_new_object();
1461 json_object_string_add(json_server, "mode",
1462 "ssh");
1463 json_object_string_add(
1464 json_server, "host",
1465 cache->tr_config.ssh_config->host);
1466 json_object_int_add(
1467 json_server, "port",
1468 cache->tr_config.ssh_config->port);
1469 json_object_string_add(
1470 json_server, "username",
1471 cache->tr_config.ssh_config->username);
1472 json_object_string_add(
1473 json_server, "serverHostkeyPath",
1474 cache->tr_config.ssh_config
1475 ->server_hostkey_path);
1476 json_object_string_add(
1477 json_server, "clientPrivkeyPath",
1478 cache->tr_config.ssh_config
1479 ->client_privkey_path);
77be6d6a
DA
1480 json_object_int_add(json_server, "preference",
1481 cache->preference);
cc4d121f
DA
1482 json_object_array_add(json_servers,
1483 json_server);
1484 }
fef6fafa 1485#endif
745ae9c0 1486 }
dabecd7c
MR
1487 }
1488
cc4d121f
DA
1489 if (json)
1490 vty_json(vty, json);
1491
dabecd7c
MR
1492 return CMD_SUCCESS;
1493}
1494
ae872c2f 1495DEFPY (show_rpki_cache_connection,
dabecd7c 1496 show_rpki_cache_connection_cmd,
ae872c2f 1497 "show rpki cache-connection [json$uj]",
dabecd7c
MR
1498 SHOW_STR
1499 RPKI_OUTPUT_STRING
ae872c2f
DA
1500 "Show to which RPKI Cache Servers we have a connection\n"
1501 JSON_STR)
dabecd7c 1502{
ae872c2f
DA
1503 struct json_object *json = NULL;
1504 struct json_object *json_conn = NULL;
1505 struct json_object *json_conns = NULL;
1506 struct listnode *cache_node;
1507 struct cache *cache;
1508 struct rtr_mgr_group *group;
1509
1510 if (uj)
1511 json = json_object_new_object();
1512
708b8053 1513 if (!is_synchronized()) {
ae872c2f
DA
1514 if (!json)
1515 vty_out(vty, "No connection to RPKI cache server.\n");
1516 else
1517 vty_json(vty, json);
708b8053
DS
1518
1519 return CMD_SUCCESS;
1520 }
1521
ae872c2f 1522 group = get_connected_group();
708b8053 1523 if (!group) {
ae872c2f
DA
1524 if (!json)
1525 vty_out(vty, "Cannot find a connected group.\n");
1526 else
1527 vty_json(vty, json);
1528
708b8053
DS
1529 return CMD_SUCCESS;
1530 }
ae872c2f
DA
1531
1532 if (!json) {
1533 vty_out(vty, "Connected to group %d\n", group->preference);
1534 } else {
1535 json_conns = json_object_new_array();
1536 json_object_int_add(json, "connectedGroup", group->preference);
1537 json_object_object_add(json, "connections", json_conns);
1538 }
1539
708b8053 1540 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
c1a68b62 1541 struct tr_tcp_config *tcp_config;
acd4a9f4 1542#if defined(FOUND_SSH)
c1a68b62 1543 struct tr_ssh_config *ssh_config;
acd4a9f4 1544#endif
c1a68b62
DA
1545 switch (cache->type) {
1546 case TCP:
1547 tcp_config = cache->tr_config.tcp_config;
ae872c2f
DA
1548
1549 if (!json) {
1550 vty_out(vty,
1551 "rpki tcp cache %s %s pref %hhu%s\n",
1552 tcp_config->host, tcp_config->port,
1553 cache->preference,
1554 cache->rtr_socket->state ==
1555 RTR_ESTABLISHED
1556 ? " (connected)"
1557 : "");
1558 } else {
1559 json_conn = json_object_new_object();
1560 json_object_string_add(json_conn, "mode",
1561 "tcp");
1562 json_object_string_add(json_conn, "host",
1563 tcp_config->host);
1564 json_object_string_add(json_conn, "port",
1565 tcp_config->port);
1566 json_object_int_add(json_conn, "preference",
1567 cache->preference);
1568 json_object_string_add(
1569 json_conn, "state",
1570 cache->rtr_socket->state ==
1571 RTR_ESTABLISHED
1572 ? "connected"
1573 : "disconnected");
1574 json_object_array_add(json_conns, json_conn);
1575 }
c1a68b62 1576 break;
dabecd7c 1577#if defined(FOUND_SSH)
c1a68b62
DA
1578 case SSH:
1579 ssh_config = cache->tr_config.ssh_config;
ae872c2f
DA
1580
1581 if (!json) {
1582 vty_out(vty,
1583 "rpki ssh cache %s %u pref %hhu%s\n",
1584 ssh_config->host, ssh_config->port,
1585 cache->preference,
1586 cache->rtr_socket->state ==
1587 RTR_ESTABLISHED
1588 ? " (connected)"
1589 : "");
1590 } else {
1591 json_conn = json_object_new_object();
1592 json_object_string_add(json_conn, "mode",
1593 "ssh");
1594 json_object_string_add(json_conn, "host",
1595 ssh_config->host);
4d4b9dc1
DA
1596 json_object_int_add(json_conn, "port",
1597 ssh_config->port);
ae872c2f
DA
1598 json_object_int_add(json_conn, "preference",
1599 cache->preference);
1600 json_object_string_add(
1601 json_conn, "state",
1602 cache->rtr_socket->state ==
1603 RTR_ESTABLISHED
1604 ? "connected"
1605 : "disconnected");
1606 json_object_array_add(json_conns, json_conn);
1607 }
c1a68b62 1608 break;
dabecd7c 1609#endif
c1a68b62
DA
1610 default:
1611 break;
dabecd7c 1612 }
dabecd7c
MR
1613 }
1614
ae872c2f
DA
1615 if (json)
1616 vty_json(vty, json);
1617
dabecd7c
MR
1618 return CMD_SUCCESS;
1619}
1620
791ded4a 1621static int config_on_exit(struct vty *vty)
dabecd7c 1622{
61a484a9 1623 reset(false);
791ded4a 1624 return 1;
dabecd7c
MR
1625}
1626
1627DEFUN (rpki_reset,
1628 rpki_reset_cmd,
1629 "rpki reset",
1630 RPKI_OUTPUT_STRING
1631 "reset rpki\n")
1632{
1633 return reset(true) == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1634}
1635
1636DEFUN (debug_rpki,
1637 debug_rpki_cmd,
1638 "debug rpki",
1639 DEBUG_STR
08f9cfb8 1640 "Enable debugging for rpki\n")
dabecd7c 1641{
0e3d96bf 1642 rpki_debug = true;
dabecd7c
MR
1643 return CMD_SUCCESS;
1644}
1645
1646DEFUN (no_debug_rpki,
1647 no_debug_rpki_cmd,
1648 "no debug rpki",
1649 NO_STR
1650 DEBUG_STR
08f9cfb8 1651 "Disable debugging for rpki\n")
dabecd7c 1652{
0e3d96bf 1653 rpki_debug = false;
dabecd7c
MR
1654 return CMD_SUCCESS;
1655}
1656
48cb7ea9 1657DEFUN_YANG (match_rpki,
dabecd7c
MR
1658 match_rpki_cmd,
1659 "match rpki <valid|invalid|notfound>",
1660 MATCH_STR
1661 RPKI_OUTPUT_STRING
1662 "Valid prefix\n"
1663 "Invalid prefix\n"
1664 "Prefix not found\n")
1665{
48cb7ea9
SP
1666 const char *xpath =
1667 "./match-condition[condition='frr-bgp-route-map:rpki']";
1668 char xpath_value[XPATH_MAXLEN];
69337c34 1669
48cb7ea9
SP
1670 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
1671 snprintf(xpath_value, sizeof(xpath_value),
1672 "%s/rmap-match-condition/frr-bgp-route-map:rpki", xpath);
1673 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, argv[2]->arg);
1674
1675 return nb_cli_apply_changes(vty, NULL);
dabecd7c
MR
1676}
1677
48cb7ea9 1678DEFUN_YANG (no_match_rpki,
dabecd7c
MR
1679 no_match_rpki_cmd,
1680 "no match rpki <valid|invalid|notfound>",
1681 NO_STR
1682 MATCH_STR
1683 RPKI_OUTPUT_STRING
1684 "Valid prefix\n"
1685 "Invalid prefix\n"
1686 "Prefix not found\n")
1687{
48cb7ea9
SP
1688 const char *xpath =
1689 "./match-condition[condition='frr-bgp-route-map:rpki']";
dabecd7c 1690
48cb7ea9
SP
1691 nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
1692 return nb_cli_apply_changes(vty, NULL);
dabecd7c
MR
1693}
1694
dabecd7c
MR
1695static void install_cli_commands(void)
1696{
996c9314 1697 // TODO: make config write work
612c2c15 1698 install_node(&rpki_node);
dabecd7c 1699 install_default(RPKI_NODE);
dabecd7c 1700 install_element(CONFIG_NODE, &rpki_cmd);
9593708d 1701 install_element(ENABLE_NODE, &rpki_cmd);
8156765a
DA
1702 install_element(CONFIG_NODE, &no_rpki_cmd);
1703
dabecd7c
MR
1704
1705 install_element(ENABLE_NODE, &bgp_rpki_start_cmd);
1706 install_element(ENABLE_NODE, &bgp_rpki_stop_cmd);
1707
1708 /* Install rpki reset command */
8f14ae47 1709 install_element(ENABLE_NODE, &rpki_reset_cmd);
dabecd7c
MR
1710 install_element(RPKI_NODE, &rpki_reset_cmd);
1711
1712 /* Install rpki polling period commands */
1713 install_element(RPKI_NODE, &rpki_polling_period_cmd);
1714 install_element(RPKI_NODE, &no_rpki_polling_period_cmd);
1715
1716 /* Install rpki expire interval commands */
1717 install_element(RPKI_NODE, &rpki_expire_interval_cmd);
1718 install_element(RPKI_NODE, &no_rpki_expire_interval_cmd);
1719
1720 /* Install rpki retry interval commands */
1721 install_element(RPKI_NODE, &rpki_retry_interval_cmd);
1722 install_element(RPKI_NODE, &no_rpki_retry_interval_cmd);
1723
dabecd7c
MR
1724 /* Install rpki cache commands */
1725 install_element(RPKI_NODE, &rpki_cache_cmd);
1726 install_element(RPKI_NODE, &no_rpki_cache_cmd);
1727
1728 /* Install show commands */
9593708d 1729 install_element(VIEW_NODE, &show_rpki_prefix_table_cmd);
1730 install_element(VIEW_NODE, &show_rpki_cache_connection_cmd);
1731 install_element(VIEW_NODE, &show_rpki_cache_server_cmd);
1732 install_element(VIEW_NODE, &show_rpki_prefix_cmd);
02334bb2 1733 install_element(VIEW_NODE, &show_rpki_as_number_cmd);
dabecd7c
MR
1734
1735 /* Install debug commands */
1736 install_element(CONFIG_NODE, &debug_rpki_cmd);
1737 install_element(ENABLE_NODE, &debug_rpki_cmd);
1738 install_element(CONFIG_NODE, &no_debug_rpki_cmd);
1739 install_element(ENABLE_NODE, &no_debug_rpki_cmd);
1740
1741 /* Install route match */
1742 route_map_install_match(&route_match_rpki_cmd);
1743 install_element(RMAP_NODE, &match_rpki_cmd);
1744 install_element(RMAP_NODE, &no_match_rpki_cmd);
1745}
1746
1747FRR_MODULE_SETUP(.name = "bgpd_rpki", .version = "0.3.6",
1748 .description = "Enable RPKI support for FRR.",
80413c20
DL
1749 .init = bgp_rpki_module_init,
1750);