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