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