]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_rpki.c
Merge pull request #8188 from volta-networks/fix_ospf6_cost_flag
[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
MR
62
63DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_CACHE, "BGP RPKI Cache server")
64DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_CACHE_GROUP, "BGP RPKI Cache server group")
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
MR
564
565 hook_register(frr_late_init, bgp_rpki_init);
566 hook_register(frr_early_fini, &bgp_rpki_fini);
567
568 return 0;
569}
570
571static int start(void)
572{
dabecd7c
MR
573 int ret;
574
1dacdd8b 575 rtr_is_stopping = 0;
4ce82676 576 rtr_update_overflow = 0;
1dacdd8b 577
dabecd7c
MR
578 if (list_isempty(cache_list)) {
579 RPKI_DEBUG(
580 "No caches were found in config. Prefix validation is off.");
581 return ERROR;
582 }
583 RPKI_DEBUG("Init rtr_mgr.");
584 int groups_len = listcount(cache_list);
585 struct rtr_mgr_group *groups = get_groups();
586
1dacdd8b 587 RPKI_DEBUG("Polling period: %d", polling_period);
dabecd7c 588 ret = rtr_mgr_init(&rtr_config, groups, groups_len, polling_period,
1dacdd8b
MR
589 expire_interval, retry_interval,
590 rpki_update_cb_sync_rtr, NULL, NULL, NULL);
dabecd7c
MR
591 if (ret == RTR_ERROR) {
592 RPKI_DEBUG("Init rtr_mgr failed.");
593 return ERROR;
594 }
595
596 RPKI_DEBUG("Starting rtr_mgr.");
597 ret = rtr_mgr_start(rtr_config);
598 if (ret == RTR_ERROR) {
599 RPKI_DEBUG("Starting rtr_mgr failed.");
600 rtr_mgr_free(rtr_config);
601 return ERROR;
602 }
603 rtr_is_running = 1;
dabecd7c
MR
604
605 XFREE(MTYPE_BGP_RPKI_CACHE_GROUP, groups);
606
607 return SUCCESS;
608}
609
610static void stop(void)
611{
1dacdd8b 612 rtr_is_stopping = 1;
dabecd7c
MR
613 if (rtr_is_running) {
614 rtr_mgr_stop(rtr_config);
615 rtr_mgr_free(rtr_config);
616 rtr_is_running = 0;
617 }
618}
619
620static int reset(bool force)
621{
622 if (rtr_is_running && !force)
623 return SUCCESS;
624
625 RPKI_DEBUG("Resetting RPKI Session");
626 stop();
627 return start();
628}
629
630static struct rtr_mgr_group *get_connected_group(void)
631{
18b91526 632 if (!cache_list || list_isempty(cache_list))
dabecd7c
MR
633 return NULL;
634
635 return rtr_mgr_get_first_group(rtr_config);
636}
637
02334bb2
DA
638static void print_prefix_table_by_asn(struct vty *vty, as_t as)
639{
640 unsigned int number_of_ipv4_prefixes = 0;
641 unsigned int number_of_ipv6_prefixes = 0;
642 struct rtr_mgr_group *group = get_connected_group();
643 struct rpki_for_each_record_arg arg;
644
645 arg.vty = vty;
646 arg.as = as;
647
648 if (!group) {
649 vty_out(vty, "Cannot find a connected group.\n");
650 return;
651 }
652
653 struct pfx_table *pfx_table = group->sockets[0]->pfx_table;
654
655 vty_out(vty, "RPKI/RTR prefix table\n");
656 vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
657
658 arg.prefix_amount = &number_of_ipv4_prefixes;
659 pfx_table_for_each_ipv4_record(pfx_table, print_record_by_asn, &arg);
660
661 arg.prefix_amount = &number_of_ipv6_prefixes;
662 pfx_table_for_each_ipv6_record(pfx_table, print_record_by_asn, &arg);
663
664 vty_out(vty, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes);
665 vty_out(vty, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes);
666}
667
dabecd7c
MR
668static void print_prefix_table(struct vty *vty)
669{
670 struct rpki_for_each_record_arg arg;
671
672 unsigned int number_of_ipv4_prefixes = 0;
673 unsigned int number_of_ipv6_prefixes = 0;
674 struct rtr_mgr_group *group = get_connected_group();
675
676 arg.vty = vty;
677
678 if (!group)
679 return;
680
681 struct pfx_table *pfx_table = group->sockets[0]->pfx_table;
682
683 vty_out(vty, "RPKI/RTR prefix table\n");
684 vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
685
686 arg.prefix_amount = &number_of_ipv4_prefixes;
5d799192 687 pfx_table_for_each_ipv4_record(pfx_table, print_record_cb, &arg);
dabecd7c
MR
688
689 arg.prefix_amount = &number_of_ipv6_prefixes;
5d799192 690 pfx_table_for_each_ipv6_record(pfx_table, print_record_cb, &arg);
dabecd7c
MR
691
692 vty_out(vty, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes);
693 vty_out(vty, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes);
694}
695
696static int rpki_validate_prefix(struct peer *peer, struct attr *attr,
898c4e66 697 const struct prefix *prefix)
dabecd7c
MR
698{
699 struct assegment *as_segment;
700 as_t as_number = 0;
701 struct lrtr_ip_addr ip_addr_prefix;
702 enum pfxv_state result;
dabecd7c
MR
703
704 if (!is_synchronized())
705 return 0;
706
707 // No aspath means route comes from iBGP
708 if (!attr->aspath || !attr->aspath->segments) {
709 // Set own as number
710 as_number = peer->bgp->as;
711 } else {
712 as_segment = attr->aspath->segments;
713 // Find last AsSegment
714 while (as_segment->next)
715 as_segment = as_segment->next;
716
717 if (as_segment->type == AS_SEQUENCE) {
718 // Get rightmost asn
719 as_number = as_segment->as[as_segment->length - 1];
996c9314
LB
720 } else if (as_segment->type == AS_CONFED_SEQUENCE
721 || as_segment->type == AS_CONFED_SET) {
dabecd7c
MR
722 // Set own as number
723 as_number = peer->bgp->as;
724 } else {
725 // RFC says: "Take distinguished value NONE as asn"
726 // which means state is unknown
727 return RPKI_NOTFOUND;
728 }
729 }
730
731 // Get the prefix in requested format
732 switch (prefix->family) {
733 case AF_INET:
734 ip_addr_prefix.ver = LRTR_IPV4;
735 ip_addr_prefix.u.addr4.addr = ntohl(prefix->u.prefix4.s_addr);
736 break;
737
dabecd7c
MR
738 case AF_INET6:
739 ip_addr_prefix.ver = LRTR_IPV6;
740 ipv6_addr_to_host_byte_order(prefix->u.prefix6.s6_addr32,
741 ip_addr_prefix.u.addr6.addr);
742 break;
dabecd7c
MR
743
744 default:
745 return 0;
746 }
747
748 // Do the actual validation
749 rtr_mgr_validate(rtr_config, as_number, &ip_addr_prefix,
750 prefix->prefixlen, &result);
751
752 // Print Debug output
dabecd7c
MR
753 switch (result) {
754 case BGP_PFXV_STATE_VALID:
755 RPKI_DEBUG(
2dbe669b
DA
756 "Validating Prefix %pFX from asn %u Result: VALID",
757 prefix, as_number);
dabecd7c
MR
758 return RPKI_VALID;
759 case BGP_PFXV_STATE_NOT_FOUND:
760 RPKI_DEBUG(
2dbe669b
DA
761 "Validating Prefix %pFX from asn %u Result: NOT FOUND",
762 prefix, as_number);
dabecd7c
MR
763 return RPKI_NOTFOUND;
764 case BGP_PFXV_STATE_INVALID:
765 RPKI_DEBUG(
2dbe669b
DA
766 "Validating Prefix %pFX from asn %u Result: INVALID",
767 prefix, as_number);
dabecd7c
MR
768 return RPKI_INVALID;
769 default:
770 RPKI_DEBUG(
2dbe669b
DA
771 "Validating Prefix %pFX from asn %u Result: CANNOT VALIDATE",
772 prefix, as_number);
dabecd7c
MR
773 break;
774 }
775 return 0;
776}
777
778static int add_cache(struct cache *cache)
779{
780 uint8_t preference = cache->preference;
781 struct rtr_mgr_group group;
782
783 group.preference = preference;
784 group.sockets_len = 1;
785 group.sockets = &cache->rtr_socket;
786
92110aab
MR
787 if (rtr_is_running) {
788 init_tr_socket(cache);
789
790 if (rtr_mgr_add_group(rtr_config, &group) != RTR_SUCCESS) {
791 free_tr_socket(cache);
792 return ERROR;
793 }
dabecd7c
MR
794 }
795
6893064b
MR
796 listnode_add(cache_list, cache);
797
dabecd7c
MR
798 return SUCCESS;
799}
800
996c9314 801static int add_tcp_cache(const char *host, const char *port,
dabecd7c
MR
802 const uint8_t preference)
803{
804 struct rtr_socket *rtr_socket;
805 struct tr_tcp_config *tcp_config =
a633498e 806 XCALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_tcp_config));
dabecd7c
MR
807 struct tr_socket *tr_socket =
808 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
809 struct cache *cache =
810 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
811
812 tcp_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
813 tcp_config->port = XSTRDUP(MTYPE_BGP_RPKI_CACHE, port);
814 tcp_config->bindaddr = NULL;
815
816 rtr_socket = create_rtr_socket(tr_socket);
817
818 cache->type = TCP;
819 cache->tr_socket = tr_socket;
820 cache->tr_config.tcp_config = tcp_config;
821 cache->rtr_socket = rtr_socket;
822 cache->preference = preference;
823
6893064b
MR
824 int ret = add_cache(cache);
825 if (ret != SUCCESS) {
826 free_cache(cache);
827 }
828
829 return ret;
dabecd7c
MR
830}
831
832#if defined(FOUND_SSH)
996c9314
LB
833static int add_ssh_cache(const char *host, const unsigned int port,
834 const char *username, const char *client_privkey_path,
dabecd7c
MR
835 const char *client_pubkey_path,
836 const char *server_pubkey_path,
837 const uint8_t preference)
838{
839 struct tr_ssh_config *ssh_config =
a633498e 840 XCALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_ssh_config));
dabecd7c
MR
841 struct cache *cache =
842 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
843 struct tr_socket *tr_socket =
844 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
845 struct rtr_socket *rtr_socket;
846
847 ssh_config->port = port;
848 ssh_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
849 ssh_config->bindaddr = NULL;
850
851 ssh_config->username = XSTRDUP(MTYPE_BGP_RPKI_CACHE, username);
996c9314
LB
852 ssh_config->client_privkey_path =
853 XSTRDUP(MTYPE_BGP_RPKI_CACHE, client_privkey_path);
dabecd7c
MR
854 ssh_config->server_hostkey_path =
855 XSTRDUP(MTYPE_BGP_RPKI_CACHE, server_pubkey_path);
856
857 rtr_socket = create_rtr_socket(tr_socket);
858
859 cache->type = SSH;
860 cache->tr_socket = tr_socket;
861 cache->tr_config.ssh_config = ssh_config;
862 cache->rtr_socket = rtr_socket;
863 cache->preference = preference;
864
6893064b
MR
865 int ret = add_cache(cache);
866 if (ret != SUCCESS) {
867 free_cache(cache);
868 }
869
870 return ret;
dabecd7c
MR
871}
872#endif
873
874static void free_cache(struct cache *cache)
875{
876 if (cache->type == TCP) {
996c9314
LB
877 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->host);
878 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->port);
dabecd7c
MR
879 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config);
880 }
881#if defined(FOUND_SSH)
882 else {
996c9314 883 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config->host);
dabecd7c
MR
884 XFREE(MTYPE_BGP_RPKI_CACHE,
885 cache->tr_config.ssh_config->username);
886 XFREE(MTYPE_BGP_RPKI_CACHE,
887 cache->tr_config.ssh_config->client_privkey_path);
888 XFREE(MTYPE_BGP_RPKI_CACHE,
889 cache->tr_config.ssh_config->server_hostkey_path);
890 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config);
891 }
892#endif
893 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_socket);
894 XFREE(MTYPE_BGP_RPKI_CACHE, cache->rtr_socket);
895 XFREE(MTYPE_BGP_RPKI_CACHE, cache);
896}
897
898static int config_write(struct vty *vty)
899{
900 struct listnode *cache_node;
901 struct cache *cache;
902
708b8053
DS
903 if (!listcount(cache_list))
904 return 0;
905
906 if (rpki_debug)
907 vty_out(vty, "debug rpki\n");
908
909 vty_out(vty, "!\n");
910 vty_out(vty, "rpki\n");
911 vty_out(vty, " rpki polling_period %d\n", polling_period);
912 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
913 switch (cache->type) {
914 struct tr_tcp_config *tcp_config;
acd4a9f4 915#if defined(FOUND_SSH)
708b8053 916 struct tr_ssh_config *ssh_config;
acd4a9f4 917#endif
708b8053
DS
918 case TCP:
919 tcp_config = cache->tr_config.tcp_config;
920 vty_out(vty, " rpki cache %s %s ", tcp_config->host,
921 tcp_config->port);
922 break;
dabecd7c 923#if defined(FOUND_SSH)
708b8053
DS
924 case SSH:
925 ssh_config = cache->tr_config.ssh_config;
926 vty_out(vty, " rpki cache %s %u %s %s %s ",
927 ssh_config->host, ssh_config->port,
928 ssh_config->username,
929 ssh_config->client_privkey_path,
930 ssh_config->server_hostkey_path != NULL
931 ? ssh_config->server_hostkey_path
932 : " ");
933 break;
dabecd7c 934#endif
708b8053
DS
935 default:
936 break;
dabecd7c 937 }
708b8053
DS
938
939 vty_out(vty, "preference %hhu\n", cache->preference);
dabecd7c 940 }
708b8053
DS
941 vty_out(vty, " exit\n");
942
943 return 1;
dabecd7c
MR
944}
945
946DEFUN_NOSH (rpki,
947 rpki_cmd,
948 "rpki",
949 "Enable rpki and enter rpki configuration mode\n")
950{
951 vty->node = RPKI_NODE;
952 return CMD_SUCCESS;
953}
954
955DEFUN (bgp_rpki_start,
956 bgp_rpki_start_cmd,
957 "rpki start",
958 RPKI_OUTPUT_STRING
959 "start rpki support\n")
960{
961 if (listcount(cache_list) == 0)
996c9314
LB
962 vty_out(vty,
963 "Could not start rpki because no caches are configured\n");
dabecd7c
MR
964
965 if (!is_running()) {
966 if (start() == ERROR) {
967 RPKI_DEBUG("RPKI failed to start");
968 return CMD_WARNING;
969 }
970 }
971 return CMD_SUCCESS;
972}
973
974DEFUN (bgp_rpki_stop,
975 bgp_rpki_stop_cmd,
976 "rpki stop",
977 RPKI_OUTPUT_STRING
978 "start rpki support\n")
979{
980 if (is_running())
981 stop();
982
983 return CMD_SUCCESS;
984}
985
986DEFPY (rpki_polling_period,
987 rpki_polling_period_cmd,
988 "rpki polling_period (1-86400)$pp",
989 RPKI_OUTPUT_STRING
990 "Set polling period\n"
991 "Polling period value\n")
992{
993 polling_period = pp;
994 return CMD_SUCCESS;
995}
996
997DEFUN (no_rpki_polling_period,
998 no_rpki_polling_period_cmd,
999 "no rpki polling_period",
1000 NO_STR
1001 RPKI_OUTPUT_STRING
1002 "Set polling period back to default\n")
1003{
1004 polling_period = POLLING_PERIOD_DEFAULT;
1005 return CMD_SUCCESS;
1006}
1007
1008DEFPY (rpki_expire_interval,
1009 rpki_expire_interval_cmd,
1010 "rpki expire_interval (600-172800)$tmp",
1011 RPKI_OUTPUT_STRING
1012 "Set expire interval\n"
1013 "Expire interval value\n")
1014{
6f577f58 1015 if ((unsigned int)tmp >= polling_period) {
dabecd7c
MR
1016 expire_interval = tmp;
1017 return CMD_SUCCESS;
1018 }
1019
1020 vty_out(vty, "%% Expiry interval must be polling period or larger\n");
1021 return CMD_WARNING_CONFIG_FAILED;
1022}
1023
1024DEFUN (no_rpki_expire_interval,
1025 no_rpki_expire_interval_cmd,
1026 "no rpki expire_interval",
1027 NO_STR
1028 RPKI_OUTPUT_STRING
1029 "Set expire interval back to default\n")
1030{
1031 expire_interval = polling_period * 2;
1032 return CMD_SUCCESS;
1033}
1034
1035DEFPY (rpki_retry_interval,
1036 rpki_retry_interval_cmd,
1037 "rpki retry_interval (1-7200)$tmp",
1038 RPKI_OUTPUT_STRING
1039 "Set retry interval\n"
1040 "retry interval value\n")
1041{
1042 retry_interval = tmp;
1043 return CMD_SUCCESS;
1044}
1045
1046DEFUN (no_rpki_retry_interval,
1047 no_rpki_retry_interval_cmd,
1048 "no rpki retry_interval",
1049 NO_STR
1050 RPKI_OUTPUT_STRING
1051 "Set retry interval back to default\n")
1052{
1053 retry_interval = RETRY_INTERVAL_DEFAULT;
1054 return CMD_SUCCESS;
1055}
1056
dabecd7c
MR
1057DEFPY (rpki_cache,
1058 rpki_cache_cmd,
3efd0893 1059 "rpki cache <A.B.C.D|WORD><TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY SSH_PUBKEY [SERVER_PUBKEY]> preference (1-255)",
dabecd7c
MR
1060 RPKI_OUTPUT_STRING
1061 "Install a cache server to current group\n"
1062 "IP address of cache server\n Hostname of cache server\n"
1063 "TCP port number\n"
1064 "SSH port number\n"
1065 "SSH user name\n"
1066 "Path to own SSH private key\n"
1067 "Path to own SSH public key\n"
1068 "Path to Public key of cache server\n"
1069 "Preference of the cache server\n"
1070 "Preference value\n")
1071{
3f54c705 1072 int return_value;
a2ed7b2b
MR
1073 struct listnode *cache_node;
1074 struct cache *current_cache;
1075
1076 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, current_cache)) {
1077 if (current_cache->preference == preference) {
1078 vty_out(vty,
1079 "Cache with preference %ld is already configured\n",
1080 preference);
1081 return CMD_WARNING;
1082 }
1083 }
1084
dabecd7c
MR
1085
1086 // use ssh connection
1087 if (ssh_uname) {
1088#if defined(FOUND_SSH)
996c9314
LB
1089 return_value =
1090 add_ssh_cache(cache, sshport, ssh_uname, ssh_privkey,
1091 ssh_pubkey, server_pubkey, preference);
dabecd7c 1092#else
3f54c705 1093 return_value = SUCCESS;
dabecd7c 1094 vty_out(vty,
3efd0893 1095 "ssh sockets are not supported. Please recompile rtrlib and frr with ssh support. If you want to use it\n");
dabecd7c
MR
1096#endif
1097 } else { // use tcp connection
1098 return_value = add_tcp_cache(cache, tcpport, preference);
1099 }
1100
1101 if (return_value == ERROR) {
1102 vty_out(vty, "Could not create new rpki cache\n");
1103 return CMD_WARNING;
1104 }
1105
1106 return CMD_SUCCESS;
1107}
1108
1109DEFPY (no_rpki_cache,
1110 no_rpki_cache_cmd,
1111 "no rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport> preference (1-255)$preference",
1112 NO_STR
1113 RPKI_OUTPUT_STRING
1114 "Remove a cache server\n"
1115 "IP address of cache server\n Hostname of cache server\n"
1116 "TCP port number\n"
1117 "SSH port number\n"
1118 "Preference of the cache server\n"
1119 "Preference value\n")
1120{
1121 struct cache *cache_p = find_cache(preference);
1122
222487fe 1123 if (!cache_p) {
dabecd7c
MR
1124 vty_out(vty, "Could not find cache %ld\n", preference);
1125 return CMD_WARNING;
1126 }
1127
8add1719
MR
1128 if (rtr_is_running && listcount(cache_list) == 1) {
1129 stop();
1130 } else if (rtr_is_running) {
dabecd7c
MR
1131 if (rtr_mgr_remove_group(rtr_config, preference) == RTR_ERROR) {
1132 vty_out(vty, "Could not remove cache %ld", preference);
dabecd7c
MR
1133
1134 vty_out(vty, "\n");
1135 return CMD_WARNING;
1136 }
1137 }
1138
1139 listnode_delete(cache_list, cache_p);
1140 free_cache(cache_p);
1141
1142 return CMD_SUCCESS;
1143}
1144
1145DEFUN (show_rpki_prefix_table,
1146 show_rpki_prefix_table_cmd,
1147 "show rpki prefix-table",
1148 SHOW_STR
1149 RPKI_OUTPUT_STRING
08f9cfb8 1150 "Show validated prefixes which were received from RPKI Cache\n")
dabecd7c
MR
1151{
1152 struct listnode *cache_node;
1153 struct cache *cache;
1154
1155 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
996c9314 1156 vty_out(vty, "host: %s port: %s\n",
dabecd7c
MR
1157 cache->tr_config.tcp_config->host,
1158 cache->tr_config.tcp_config->port);
1159 }
1160 if (is_synchronized())
1161 print_prefix_table(vty);
1162 else
1163 vty_out(vty, "No connection to RPKI cache server.\n");
1164
1165 return CMD_SUCCESS;
1166}
1167
02334bb2
DA
1168DEFPY(show_rpki_as_number, show_rpki_as_number_cmd,
1169 "show rpki as-number (1-4294967295)$by_asn",
1170 SHOW_STR RPKI_OUTPUT_STRING
1171 "Lookup by ASN in prefix table\n"
1172 "AS Number\n")
1173{
1174 if (!is_synchronized()) {
1175 vty_out(vty, "No Connection to RPKI cache server.\n");
1176 return CMD_WARNING;
1177 }
1178
1179 print_prefix_table_by_asn(vty, by_asn);
1180 return CMD_SUCCESS;
1181}
1182
5d799192
MR
1183DEFPY (show_rpki_prefix,
1184 show_rpki_prefix_cmd,
1185 "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn]",
1186 SHOW_STR
1187 RPKI_OUTPUT_STRING
1188 "Lookup IP prefix and optionally ASN in prefix table\n"
1189 "IPv4 prefix\n"
1190 "IPv6 prefix\n"
1191 "AS Number\n")
1192{
1193
1194 if (!is_synchronized()) {
f79f7a7b 1195 vty_out(vty, "No Connection to RPKI cache server.\n");
5d799192
MR
1196 return CMD_WARNING;
1197 }
1198
1199 struct lrtr_ip_addr addr;
1200 char addr_str[INET6_ADDRSTRLEN];
1201 size_t addr_len = strchr(prefix_str, '/') - prefix_str;
1202
1203 memset(addr_str, 0, sizeof(addr_str));
1204 memcpy(addr_str, prefix_str, addr_len);
1205
1206 if (lrtr_ip_str_to_addr(addr_str, &addr) != 0) {
1207 vty_out(vty, "Invalid IP prefix\n");
1208 return CMD_WARNING;
1209 }
1210
1211 struct pfx_record *matches = NULL;
1212 unsigned int match_count = 0;
1213 enum pfxv_state result;
1214
1215 if (pfx_table_validate_r(rtr_config->pfx_table, &matches, &match_count,
1216 asn, &addr, prefix->prefixlen, &result)
1217 != PFX_SUCCESS) {
1218 vty_out(vty, "Prefix lookup failed");
1219 return CMD_WARNING;
1220 }
1221
1222 vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
1223 for (size_t i = 0; i < match_count; ++i) {
1224 const struct pfx_record *record = &matches[i];
1225
1226 if (record->max_len >= prefix->prefixlen
c17140fd
DS
1227 && ((asn != 0 && (uint32_t)asn == record->asn)
1228 || asn == 0)) {
5d799192
MR
1229 print_record(&matches[i], vty);
1230 }
1231 }
1232
1233 return CMD_SUCCESS;
1234}
1235
dabecd7c
MR
1236DEFUN (show_rpki_cache_server,
1237 show_rpki_cache_server_cmd,
1238 "show rpki cache-server",
1239 SHOW_STR
1240 RPKI_OUTPUT_STRING
08f9cfb8 1241 "SHOW configured cache server\n")
dabecd7c
MR
1242{
1243 struct listnode *cache_node;
1244 struct cache *cache;
1245
1246 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
745ae9c0
MR
1247 if (cache->type == TCP) {
1248 vty_out(vty, "host: %s port: %s\n",
1249 cache->tr_config.tcp_config->host,
1250 cache->tr_config.tcp_config->port);
1251
fef6fafa 1252#if defined(FOUND_SSH)
745ae9c0
MR
1253 } else if (cache->type == SSH) {
1254 vty_out(vty,
3efd0893 1255 "host: %s port: %d username: %s server_hostkey_path: %s client_privkey_path: %s\n",
745ae9c0
MR
1256 cache->tr_config.ssh_config->host,
1257 cache->tr_config.ssh_config->port,
1258 cache->tr_config.ssh_config->username,
1259 cache->tr_config.ssh_config
1260 ->server_hostkey_path,
1261 cache->tr_config.ssh_config
1262 ->client_privkey_path);
fef6fafa 1263#endif
745ae9c0 1264 }
dabecd7c
MR
1265 }
1266
1267 return CMD_SUCCESS;
1268}
1269
1270DEFUN (show_rpki_cache_connection,
1271 show_rpki_cache_connection_cmd,
1272 "show rpki cache-connection",
1273 SHOW_STR
1274 RPKI_OUTPUT_STRING
08f9cfb8 1275 "Show to which RPKI Cache Servers we have a connection\n")
dabecd7c 1276{
708b8053
DS
1277 if (!is_synchronized()) {
1278 vty_out(vty, "No connection to RPKI cache server.\n");
1279
1280 return CMD_SUCCESS;
1281 }
1282
1283 struct listnode *cache_node;
1284 struct cache *cache;
1285 struct rtr_mgr_group *group = get_connected_group();
1286
1287 if (!group) {
1288 vty_out(vty, "Cannot find a connected group.\n");
1289 return CMD_SUCCESS;
1290 }
1291 vty_out(vty, "Connected to group %d\n", group->preference);
1292 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
1293 if (cache->preference == group->preference) {
1294 struct tr_tcp_config *tcp_config;
acd4a9f4 1295#if defined(FOUND_SSH)
708b8053 1296 struct tr_ssh_config *ssh_config;
acd4a9f4 1297#endif
dabecd7c 1298
708b8053
DS
1299 switch (cache->type) {
1300 case TCP:
1301 tcp_config = cache->tr_config.tcp_config;
1302 vty_out(vty, "rpki tcp cache %s %s pref %hhu\n",
1303 tcp_config->host, tcp_config->port,
1304 cache->preference);
1305 break;
dabecd7c
MR
1306
1307#if defined(FOUND_SSH)
708b8053
DS
1308 case SSH:
1309 ssh_config = cache->tr_config.ssh_config;
1310 vty_out(vty, "rpki ssh cache %s %u pref %hhu\n",
1311 ssh_config->host, ssh_config->port,
1312 cache->preference);
1313 break;
dabecd7c
MR
1314#endif
1315
708b8053
DS
1316 default:
1317 break;
dabecd7c
MR
1318 }
1319 }
dabecd7c
MR
1320 }
1321
1322 return CMD_SUCCESS;
1323}
1324
791ded4a 1325static int config_on_exit(struct vty *vty)
dabecd7c 1326{
61a484a9 1327 reset(false);
791ded4a 1328 return 1;
dabecd7c
MR
1329}
1330
1331DEFUN (rpki_reset,
1332 rpki_reset_cmd,
1333 "rpki reset",
1334 RPKI_OUTPUT_STRING
1335 "reset rpki\n")
1336{
1337 return reset(true) == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1338}
1339
1340DEFUN (debug_rpki,
1341 debug_rpki_cmd,
1342 "debug rpki",
1343 DEBUG_STR
08f9cfb8 1344 "Enable debugging for rpki\n")
dabecd7c
MR
1345{
1346 rpki_debug = 1;
1347 return CMD_SUCCESS;
1348}
1349
1350DEFUN (no_debug_rpki,
1351 no_debug_rpki_cmd,
1352 "no debug rpki",
1353 NO_STR
1354 DEBUG_STR
08f9cfb8 1355 "Disable debugging for rpki\n")
dabecd7c
MR
1356{
1357 rpki_debug = 0;
1358 return CMD_SUCCESS;
1359}
1360
1361DEFUN (match_rpki,
1362 match_rpki_cmd,
1363 "match rpki <valid|invalid|notfound>",
1364 MATCH_STR
1365 RPKI_OUTPUT_STRING
1366 "Valid prefix\n"
1367 "Invalid prefix\n"
1368 "Prefix not found\n")
1369{
1370 VTY_DECLVAR_CONTEXT(route_map_index, index);
cda7187d 1371 enum rmap_compile_rets ret;
dabecd7c 1372
e2c8d6ce
NT
1373 ret = route_map_add_match(index, "rpki", argv[2]->arg,
1374 RMAP_EVENT_MATCH_ADDED);
69337c34
DS
1375 switch (ret) {
1376 case RMAP_RULE_MISSING:
1377 vty_out(vty, "%% BGP Can't find rule.\n");
1378 return CMD_WARNING_CONFIG_FAILED;
1379 case RMAP_COMPILE_ERROR:
1380 vty_out(vty, "%% BGP Argument is malformed.\n");
1381 return CMD_WARNING_CONFIG_FAILED;
1382 case RMAP_COMPILE_SUCCESS:
1383 return CMD_SUCCESS;
1384 break;
dabecd7c 1385 }
69337c34 1386
dabecd7c
MR
1387 return CMD_SUCCESS;
1388}
1389
1390DEFUN (no_match_rpki,
1391 no_match_rpki_cmd,
1392 "no match rpki <valid|invalid|notfound>",
1393 NO_STR
1394 MATCH_STR
1395 RPKI_OUTPUT_STRING
1396 "Valid prefix\n"
1397 "Invalid prefix\n"
1398 "Prefix not found\n")
1399{
1400 VTY_DECLVAR_CONTEXT(route_map_index, index);
cda7187d 1401 enum rmap_compile_rets ret;
dabecd7c 1402
909f3d56 1403 ret = route_map_delete_match(index, "rpki", argv[3]->arg,
1404 RMAP_EVENT_MATCH_DELETED);
69337c34
DS
1405 switch (ret) {
1406 case RMAP_RULE_MISSING:
1407 vty_out(vty, "%% BGP Can't find rule.\n");
1408 return CMD_WARNING_CONFIG_FAILED;
1409 break;
1410 case RMAP_COMPILE_ERROR:
1411 vty_out(vty, "%% BGP Argument is malformed.\n");
dabecd7c 1412 return CMD_WARNING_CONFIG_FAILED;
69337c34
DS
1413 break;
1414 case RMAP_COMPILE_SUCCESS:
1415 return CMD_SUCCESS;
1416 break;
dabecd7c
MR
1417 }
1418
1419 return CMD_SUCCESS;
1420}
1421
dabecd7c
MR
1422static void install_cli_commands(void)
1423{
996c9314 1424 // TODO: make config write work
612c2c15 1425 install_node(&rpki_node);
dabecd7c 1426 install_default(RPKI_NODE);
dabecd7c 1427 install_element(CONFIG_NODE, &rpki_cmd);
9593708d 1428 install_element(ENABLE_NODE, &rpki_cmd);
dabecd7c
MR
1429
1430 install_element(ENABLE_NODE, &bgp_rpki_start_cmd);
1431 install_element(ENABLE_NODE, &bgp_rpki_stop_cmd);
1432
1433 /* Install rpki reset command */
1434 install_element(RPKI_NODE, &rpki_reset_cmd);
1435
1436 /* Install rpki polling period commands */
1437 install_element(RPKI_NODE, &rpki_polling_period_cmd);
1438 install_element(RPKI_NODE, &no_rpki_polling_period_cmd);
1439
1440 /* Install rpki expire interval commands */
1441 install_element(RPKI_NODE, &rpki_expire_interval_cmd);
1442 install_element(RPKI_NODE, &no_rpki_expire_interval_cmd);
1443
1444 /* Install rpki retry interval commands */
1445 install_element(RPKI_NODE, &rpki_retry_interval_cmd);
1446 install_element(RPKI_NODE, &no_rpki_retry_interval_cmd);
1447
dabecd7c
MR
1448 /* Install rpki cache commands */
1449 install_element(RPKI_NODE, &rpki_cache_cmd);
1450 install_element(RPKI_NODE, &no_rpki_cache_cmd);
1451
1452 /* Install show commands */
9593708d 1453 install_element(VIEW_NODE, &show_rpki_prefix_table_cmd);
1454 install_element(VIEW_NODE, &show_rpki_cache_connection_cmd);
1455 install_element(VIEW_NODE, &show_rpki_cache_server_cmd);
1456 install_element(VIEW_NODE, &show_rpki_prefix_cmd);
02334bb2 1457 install_element(VIEW_NODE, &show_rpki_as_number_cmd);
dabecd7c
MR
1458
1459 /* Install debug commands */
1460 install_element(CONFIG_NODE, &debug_rpki_cmd);
1461 install_element(ENABLE_NODE, &debug_rpki_cmd);
1462 install_element(CONFIG_NODE, &no_debug_rpki_cmd);
1463 install_element(ENABLE_NODE, &no_debug_rpki_cmd);
1464
1465 /* Install route match */
1466 route_map_install_match(&route_match_rpki_cmd);
1467 install_element(RMAP_NODE, &match_rpki_cmd);
1468 install_element(RMAP_NODE, &no_match_rpki_cmd);
1469}
1470
1471FRR_MODULE_SETUP(.name = "bgpd_rpki", .version = "0.3.6",
1472 .description = "Enable RPKI support for FRR.",
996c9314 1473 .init = bgp_rpki_module_init)