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