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