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