]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_rpki.c
*: remove cmd_node->vtysh
[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);
107static void overwrite_exit_commands(void);
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);
1dacdd8b
MR
130static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
131 safi_t safi);
4ce82676 132static void revalidate_all_routes(void);
dabecd7c
MR
133
134static struct rtr_mgr_config *rtr_config;
135static struct list *cache_list;
136static int rtr_is_running;
1dacdd8b 137static int rtr_is_stopping;
4ce82676 138static _Atomic int rtr_update_overflow;
dabecd7c
MR
139static int rpki_debug;
140static unsigned int polling_period;
141static unsigned int expire_interval;
142static unsigned int retry_interval;
1dacdd8b
MR
143static int rpki_sync_socket_rtr;
144static int rpki_sync_socket_bgpd;
dabecd7c 145
62b346ee
DL
146static struct cmd_node rpki_node = {
147 .node = RPKI_NODE,
148 .prompt = "%s(config-rpki)# ",
62b346ee 149};
364deb04 150static const struct route_map_rule_cmd route_match_rpki_cmd = {
996c9314 151 "rpki", route_match, route_match_compile, route_match_free};
dabecd7c
MR
152
153static void *malloc_wrapper(size_t size)
154{
155 return XMALLOC(MTYPE_BGP_RPKI_CACHE, size);
156}
157
158static void *realloc_wrapper(void *ptr, size_t size)
159{
160 return XREALLOC(MTYPE_BGP_RPKI_CACHE, ptr, size);
161}
162
163static void free_wrapper(void *ptr)
164{
165 XFREE(MTYPE_BGP_RPKI_CACHE, ptr);
166}
167
92110aab
MR
168static void init_tr_socket(struct cache *cache)
169{
170 if (cache->type == TCP)
171 tr_tcp_init(cache->tr_config.tcp_config,
172 cache->tr_socket);
173#if defined(FOUND_SSH)
174 else
175 tr_ssh_init(cache->tr_config.ssh_config,
176 cache->tr_socket);
177#endif
178}
179
180static void free_tr_socket(struct cache *cache)
181{
182 if (cache->type == TCP)
183 tr_tcp_init(cache->tr_config.tcp_config,
184 cache->tr_socket);
185#if defined(FOUND_SSH)
186 else
187 tr_ssh_init(cache->tr_config.ssh_config,
188 cache->tr_socket);
189#endif
190}
191
dabecd7c 192static int rpki_validate_prefix(struct peer *peer, struct attr *attr,
898c4e66 193 const struct prefix *prefix);
dabecd7c 194
1dacdd8b
MR
195static void ipv6_addr_to_network_byte_order(const uint32_t *src, uint32_t *dest)
196{
197 int i;
198
199 for (i = 0; i < 4; i++)
200 dest[i] = htonl(src[i]);
201}
202
e4234602
MR
203static void ipv6_addr_to_host_byte_order(const uint32_t *src, uint32_t *dest)
204{
205 int i;
206
207 for (i = 0; i < 4; i++)
208 dest[i] = ntohl(src[i]);
209}
210
b68885f9
LK
211static enum route_map_cmd_result_t route_match(void *rule,
212 const struct prefix *prefix,
213 route_map_object_t type,
214 void *object)
dabecd7c
MR
215{
216 int *rpki_status = rule;
9b6d8fcf 217 struct bgp_path_info *path;
dabecd7c
MR
218
219 if (type == RMAP_BGP) {
9b6d8fcf 220 path = object;
dabecd7c 221
9b6d8fcf 222 if (rpki_validate_prefix(path->peer, path->attr, prefix)
dabecd7c
MR
223 == *rpki_status) {
224 return RMAP_MATCH;
225 }
226 }
227 return RMAP_NOMATCH;
228}
229
230static void *route_match_compile(const char *arg)
231{
232 int *rpki_status;
233
0b2c4b35 234 rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
dabecd7c
MR
235
236 if (strcmp(arg, "valid") == 0)
237 *rpki_status = RPKI_VALID;
238 else if (strcmp(arg, "invalid") == 0)
239 *rpki_status = RPKI_INVALID;
240 else
241 *rpki_status = RPKI_NOTFOUND;
242
243 return rpki_status;
244}
245
246static void route_match_free(void *rule)
247{
248 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
249}
250
251static struct rtr_socket *create_rtr_socket(struct tr_socket *tr_socket)
252{
253 struct rtr_socket *rtr_socket =
254 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct rtr_socket));
255 rtr_socket->tr_socket = tr_socket;
256 return rtr_socket;
257}
258
259static struct cache *find_cache(const uint8_t preference)
260{
261 struct listnode *cache_node;
262 struct cache *cache;
263
264 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
265 if (cache->preference == preference)
266 return cache;
267 }
268 return NULL;
269}
270
5d799192 271static void print_record(const struct pfx_record *record, struct vty *vty)
dabecd7c
MR
272{
273 char ip[INET6_ADDRSTRLEN];
5d799192
MR
274
275 lrtr_ip_addr_to_str(&record->prefix, ip, sizeof(ip));
276 vty_out(vty, "%-40s %3u - %3u %10u\n", ip, record->min_len,
277 record->max_len, record->asn);
278}
279
02334bb2
DA
280static void print_record_by_asn(const struct pfx_record *record, void *data)
281{
282 struct rpki_for_each_record_arg *arg = data;
283 struct vty *vty = arg->vty;
284
285 if (record->asn == arg->as) {
286 (*arg->prefix_amount)++;
287 print_record(record, vty);
288 }
289}
290
5d799192
MR
291static void print_record_cb(const struct pfx_record *record, void *data)
292{
dabecd7c
MR
293 struct rpki_for_each_record_arg *arg = data;
294 struct vty *vty = arg->vty;
295
a220aec6 296 (*arg->prefix_amount)++;
dabecd7c 297
5d799192 298 print_record(record, vty);
dabecd7c
MR
299}
300
301static struct rtr_mgr_group *get_groups(void)
302{
303 struct listnode *cache_node;
304 struct rtr_mgr_group *rtr_mgr_groups;
305 struct cache *cache;
306
307 int group_count = listcount(cache_list);
308
309 if (group_count == 0)
310 return NULL;
311
312 rtr_mgr_groups = XMALLOC(MTYPE_BGP_RPKI_CACHE_GROUP,
313 group_count * sizeof(struct rtr_mgr_group));
314
315 size_t i = 0;
316
317 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
318 rtr_mgr_groups[i].sockets = &cache->rtr_socket;
319 rtr_mgr_groups[i].sockets_len = 1;
320 rtr_mgr_groups[i].preference = cache->preference;
321
92110aab 322 init_tr_socket(cache);
dabecd7c
MR
323
324 i++;
325 }
326
327 return rtr_mgr_groups;
328}
329
330inline int is_synchronized(void)
331{
332 return rtr_is_running && rtr_mgr_conf_in_sync(rtr_config);
333}
334
335inline int is_running(void)
336{
337 return rtr_is_running;
338}
339
1dacdd8b
MR
340static struct prefix *pfx_record_to_prefix(struct pfx_record *record)
341{
342 struct prefix *prefix = prefix_new();
343
344 prefix->prefixlen = record->min_len;
345
346 if (record->prefix.ver == LRTR_IPV4) {
347 prefix->family = AF_INET;
348 prefix->u.prefix4.s_addr = htonl(record->prefix.u.addr4.addr);
349 } else {
350 prefix->family = AF_INET6;
351 ipv6_addr_to_network_byte_order(record->prefix.u.addr6.addr,
352 prefix->u.prefix6.s6_addr32);
353 }
354
355 return prefix;
356}
357
358static int bgpd_sync_callback(struct thread *thread)
359{
360 struct bgp *bgp;
361 struct listnode *node;
362 struct prefix *prefix;
363 struct pfx_record rec;
364
365 thread_add_read(bm->master, bgpd_sync_callback, NULL,
366 rpki_sync_socket_bgpd, NULL);
4ce82676
MR
367
368 if (atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst)) {
369 while (read(rpki_sync_socket_bgpd, &rec,
370 sizeof(struct pfx_record))
371 != -1)
372 ;
373
374 atomic_store_explicit(&rtr_update_overflow, 0,
375 memory_order_seq_cst);
376 revalidate_all_routes();
377 return 0;
378 }
379
1dacdd8b
MR
380 int retval =
381 read(rpki_sync_socket_bgpd, &rec, sizeof(struct pfx_record));
382 if (retval != sizeof(struct pfx_record)) {
383 RPKI_DEBUG("Could not read from rpki_sync_socket_bgpd");
384 return retval;
385 }
386 prefix = pfx_record_to_prefix(&rec);
387
388 afi_t afi = (rec.prefix.ver == LRTR_IPV4) ? AFI_IP : AFI_IP6;
389
390 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
31a2af32
MR
391 struct peer *peer;
392 struct listnode *peer_listnode;
1dacdd8b 393
31a2af32
MR
394 for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
395 safi_t safi;
396
397 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
398 if (!peer->bgp->rib[afi][safi])
399 continue;
1dacdd8b 400
31a2af32 401 struct list *matches = list_new();
1dacdd8b 402
31a2af32
MR
403 matches->del =
404 (void (*)(void *))bgp_unlock_node;
1dacdd8b 405
31a2af32
MR
406 bgp_table_range_lookup(
407 peer->bgp->rib[afi][safi], prefix,
408 rec.max_len, matches);
1dacdd8b
MR
409
410
31a2af32
MR
411 struct bgp_node *bgp_node;
412 struct listnode *bgp_listnode;
1dacdd8b 413
31a2af32
MR
414 for (ALL_LIST_ELEMENTS_RO(matches, bgp_listnode,
415 bgp_node))
416 revalidate_bgp_node(bgp_node, afi,
417 safi);
1dacdd8b 418
6a154c88 419 list_delete(&matches);
31a2af32 420 }
1dacdd8b
MR
421 }
422 }
423
45206fe2 424 prefix_free(&prefix);
1dacdd8b
MR
425 return 0;
426}
427
428static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
429 safi_t safi)
430{
431 struct bgp_adj_in *ain;
432
433 for (ain = bgp_node->adj_in; ain; ain = ain->next) {
434 int ret;
2b964e86
DS
435 struct bgp_path_info *path =
436 bgp_node_get_bgp_path_info(bgp_node);
1dacdd8b
MR
437 mpls_label_t *label = NULL;
438 uint32_t num_labels = 0;
439
9b6d8fcf
DS
440 if (path && path->extra) {
441 label = path->extra->label;
442 num_labels = path->extra->num_labels;
1dacdd8b 443 }
b54892e0
DS
444 ret = bgp_update(ain->peer, bgp_node_get_prefix(bgp_node),
445 ain->addpath_rx_id, ain->attr, afi, safi,
446 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, label,
447 num_labels, 1, NULL);
1dacdd8b 448
31a2af32 449 if (ret < 0)
1dacdd8b 450 return;
1dacdd8b
MR
451 }
452}
453
454static void revalidate_all_routes(void)
455{
456 struct bgp *bgp;
457 struct listnode *node;
1dacdd8b
MR
458
459 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
31a2af32
MR
460 struct peer *peer;
461 struct listnode *peer_listnode;
1dacdd8b 462
31a2af32
MR
463 for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
464
465 for (size_t i = 0; i < 2; i++) {
466 safi_t safi;
467 afi_t afi = (i == 0) ? AFI_IP : AFI_IP6;
468
469 for (safi = SAFI_UNICAST; safi < SAFI_MAX;
470 safi++) {
471 if (!peer->bgp->rib[afi][safi])
472 continue;
1dacdd8b 473
31a2af32 474 bgp_soft_reconfig_in(peer, afi, safi);
1dacdd8b
MR
475 }
476 }
477 }
478 }
479}
480
481static void rpki_update_cb_sync_rtr(struct pfx_table *p __attribute__((unused)),
482 const struct pfx_record rec,
483 const bool added __attribute__((unused)))
484{
798df969 485 if (rtr_is_stopping
4ce82676 486 || atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst))
1dacdd8b
MR
487 return;
488
489 int retval =
490 write(rpki_sync_socket_rtr, &rec, sizeof(struct pfx_record));
4ce82676
MR
491 if (retval == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
492 atomic_store_explicit(&rtr_update_overflow, 1,
493 memory_order_seq_cst);
494
495 else if (retval != sizeof(struct pfx_record))
1dacdd8b
MR
496 RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
497}
498
499static void rpki_init_sync_socket(void)
500{
501 int fds[2];
4ce82676 502 const char *msg;
1dacdd8b
MR
503
504 RPKI_DEBUG("initializing sync socket");
505 if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, fds) != 0) {
4ce82676
MR
506 msg = "could not open rpki sync socketpair";
507 goto err;
1dacdd8b
MR
508 }
509 rpki_sync_socket_rtr = fds[0];
510 rpki_sync_socket_bgpd = fds[1];
4ce82676
MR
511
512 if (set_nonblocking(rpki_sync_socket_rtr) != 0) {
513 msg = "could not set rpki_sync_socket_rtr to non blocking";
514 goto err;
515 }
516
517 if (set_nonblocking(rpki_sync_socket_bgpd) != 0) {
518 msg = "could not set rpki_sync_socket_bgpd to non blocking";
519 goto err;
520 }
521
522
1dacdd8b
MR
523 thread_add_read(bm->master, bgpd_sync_callback, NULL,
524 rpki_sync_socket_bgpd, NULL);
4ce82676
MR
525
526 return;
527
528err:
529 zlog_err("RPKI: %s", msg);
530 abort();
531
1dacdd8b
MR
532}
533
dabecd7c
MR
534static int bgp_rpki_init(struct thread_master *master)
535{
536 rpki_debug = 0;
537 rtr_is_running = 0;
1dacdd8b 538 rtr_is_stopping = 0;
dabecd7c
MR
539
540 cache_list = list_new();
996c9314 541 cache_list->del = (void (*)(void *)) & free_cache;
dabecd7c
MR
542
543 polling_period = POLLING_PERIOD_DEFAULT;
544 expire_interval = EXPIRE_INTERVAL_DEFAULT;
545 retry_interval = RETRY_INTERVAL_DEFAULT;
dabecd7c 546 install_cli_commands();
1dacdd8b 547 rpki_init_sync_socket();
dabecd7c
MR
548 return 0;
549}
550
551static int bgp_rpki_fini(void)
552{
553 stop();
6a154c88 554 list_delete(&cache_list);
dabecd7c 555
1dacdd8b
MR
556 close(rpki_sync_socket_rtr);
557 close(rpki_sync_socket_bgpd);
558
dabecd7c
MR
559 return 0;
560}
561
562static int bgp_rpki_module_init(void)
563{
996c9314 564 lrtr_set_alloc_functions(malloc_wrapper, realloc_wrapper, free_wrapper);
dabecd7c
MR
565
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;
704 char buf[BUFSIZ];
705 const char *prefix_string;
706
707 if (!is_synchronized())
708 return 0;
709
710 // No aspath means route comes from iBGP
711 if (!attr->aspath || !attr->aspath->segments) {
712 // Set own as number
713 as_number = peer->bgp->as;
714 } else {
715 as_segment = attr->aspath->segments;
716 // Find last AsSegment
717 while (as_segment->next)
718 as_segment = as_segment->next;
719
720 if (as_segment->type == AS_SEQUENCE) {
721 // Get rightmost asn
722 as_number = as_segment->as[as_segment->length - 1];
996c9314
LB
723 } else if (as_segment->type == AS_CONFED_SEQUENCE
724 || as_segment->type == AS_CONFED_SET) {
dabecd7c
MR
725 // Set own as number
726 as_number = peer->bgp->as;
727 } else {
728 // RFC says: "Take distinguished value NONE as asn"
729 // which means state is unknown
730 return RPKI_NOTFOUND;
731 }
732 }
733
734 // Get the prefix in requested format
735 switch (prefix->family) {
736 case AF_INET:
737 ip_addr_prefix.ver = LRTR_IPV4;
738 ip_addr_prefix.u.addr4.addr = ntohl(prefix->u.prefix4.s_addr);
739 break;
740
dabecd7c
MR
741 case AF_INET6:
742 ip_addr_prefix.ver = LRTR_IPV6;
743 ipv6_addr_to_host_byte_order(prefix->u.prefix6.s6_addr32,
744 ip_addr_prefix.u.addr6.addr);
745 break;
dabecd7c
MR
746
747 default:
748 return 0;
749 }
750
751 // Do the actual validation
752 rtr_mgr_validate(rtr_config, as_number, &ip_addr_prefix,
753 prefix->prefixlen, &result);
754
755 // Print Debug output
7c3f0950 756 prefix_string = prefix2str(prefix, buf, sizeof(buf));
dabecd7c
MR
757 switch (result) {
758 case BGP_PFXV_STATE_VALID:
759 RPKI_DEBUG(
7c3f0950
DS
760 "Validating Prefix %s from asn %u Result: VALID",
761 prefix_string, as_number);
dabecd7c
MR
762 return RPKI_VALID;
763 case BGP_PFXV_STATE_NOT_FOUND:
764 RPKI_DEBUG(
7c3f0950
DS
765 "Validating Prefix %s from asn %u Result: NOT FOUND",
766 prefix_string, as_number);
dabecd7c
MR
767 return RPKI_NOTFOUND;
768 case BGP_PFXV_STATE_INVALID:
769 RPKI_DEBUG(
7c3f0950
DS
770 "Validating Prefix %s from asn %u Result: INVALID",
771 prefix_string, as_number);
dabecd7c
MR
772 return RPKI_INVALID;
773 default:
774 RPKI_DEBUG(
7c3f0950
DS
775 "Validating Prefix %s from asn %u Result: CANNOT VALIDATE",
776 prefix_string, as_number);
dabecd7c
MR
777 break;
778 }
779 return 0;
780}
781
782static int add_cache(struct cache *cache)
783{
784 uint8_t preference = cache->preference;
785 struct rtr_mgr_group group;
786
787 group.preference = preference;
788 group.sockets_len = 1;
789 group.sockets = &cache->rtr_socket;
790
92110aab
MR
791 if (rtr_is_running) {
792 init_tr_socket(cache);
793
794 if (rtr_mgr_add_group(rtr_config, &group) != RTR_SUCCESS) {
795 free_tr_socket(cache);
796 return ERROR;
797 }
dabecd7c
MR
798 }
799
6893064b
MR
800 listnode_add(cache_list, cache);
801
dabecd7c
MR
802 return SUCCESS;
803}
804
996c9314 805static int add_tcp_cache(const char *host, const char *port,
dabecd7c
MR
806 const uint8_t preference)
807{
808 struct rtr_socket *rtr_socket;
809 struct tr_tcp_config *tcp_config =
810 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_tcp_config));
811 struct tr_socket *tr_socket =
812 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
813 struct cache *cache =
814 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
815
816 tcp_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
817 tcp_config->port = XSTRDUP(MTYPE_BGP_RPKI_CACHE, port);
818 tcp_config->bindaddr = NULL;
819
820 rtr_socket = create_rtr_socket(tr_socket);
821
822 cache->type = TCP;
823 cache->tr_socket = tr_socket;
824 cache->tr_config.tcp_config = tcp_config;
825 cache->rtr_socket = rtr_socket;
826 cache->preference = preference;
827
6893064b
MR
828 int ret = add_cache(cache);
829 if (ret != SUCCESS) {
830 free_cache(cache);
831 }
832
833 return ret;
dabecd7c
MR
834}
835
836#if defined(FOUND_SSH)
996c9314
LB
837static int add_ssh_cache(const char *host, const unsigned int port,
838 const char *username, const char *client_privkey_path,
dabecd7c
MR
839 const char *client_pubkey_path,
840 const char *server_pubkey_path,
841 const uint8_t preference)
842{
843 struct tr_ssh_config *ssh_config =
844 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_ssh_config));
845 struct cache *cache =
846 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
847 struct tr_socket *tr_socket =
848 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
849 struct rtr_socket *rtr_socket;
850
851 ssh_config->port = port;
852 ssh_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
853 ssh_config->bindaddr = NULL;
854
855 ssh_config->username = XSTRDUP(MTYPE_BGP_RPKI_CACHE, username);
996c9314
LB
856 ssh_config->client_privkey_path =
857 XSTRDUP(MTYPE_BGP_RPKI_CACHE, client_privkey_path);
dabecd7c
MR
858 ssh_config->server_hostkey_path =
859 XSTRDUP(MTYPE_BGP_RPKI_CACHE, server_pubkey_path);
860
861 rtr_socket = create_rtr_socket(tr_socket);
862
863 cache->type = SSH;
864 cache->tr_socket = tr_socket;
865 cache->tr_config.ssh_config = ssh_config;
866 cache->rtr_socket = rtr_socket;
867 cache->preference = preference;
868
6893064b
MR
869 int ret = add_cache(cache);
870 if (ret != SUCCESS) {
871 free_cache(cache);
872 }
873
874 return ret;
dabecd7c
MR
875}
876#endif
877
878static void free_cache(struct cache *cache)
879{
880 if (cache->type == TCP) {
996c9314
LB
881 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->host);
882 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->port);
dabecd7c
MR
883 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config);
884 }
885#if defined(FOUND_SSH)
886 else {
996c9314 887 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config->host);
dabecd7c
MR
888 XFREE(MTYPE_BGP_RPKI_CACHE,
889 cache->tr_config.ssh_config->username);
890 XFREE(MTYPE_BGP_RPKI_CACHE,
891 cache->tr_config.ssh_config->client_privkey_path);
892 XFREE(MTYPE_BGP_RPKI_CACHE,
893 cache->tr_config.ssh_config->server_hostkey_path);
894 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config);
895 }
896#endif
897 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_socket);
898 XFREE(MTYPE_BGP_RPKI_CACHE, cache->rtr_socket);
899 XFREE(MTYPE_BGP_RPKI_CACHE, cache);
900}
901
902static int config_write(struct vty *vty)
903{
904 struct listnode *cache_node;
905 struct cache *cache;
906
907 if (listcount(cache_list)) {
908 if (rpki_debug)
909 vty_out(vty, "debug rpki\n");
910
911 vty_out(vty, "!\n");
912 vty_out(vty, "rpki\n");
913 vty_out(vty, " rpki polling_period %d\n", polling_period);
dabecd7c
MR
914 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
915 switch (cache->type) {
916 struct tr_tcp_config *tcp_config;
acd4a9f4 917#if defined(FOUND_SSH)
dabecd7c 918 struct tr_ssh_config *ssh_config;
acd4a9f4 919#endif
dabecd7c
MR
920 case TCP:
921 tcp_config = cache->tr_config.tcp_config;
996c9314
LB
922 vty_out(vty, " rpki cache %s %s ",
923 tcp_config->host, tcp_config->port);
dabecd7c
MR
924 break;
925#if defined(FOUND_SSH)
926 case SSH:
927 ssh_config = cache->tr_config.ssh_config;
996c9314
LB
928 vty_out(vty, " rpki cache %s %u %s %s %s ",
929 ssh_config->host, ssh_config->port,
dabecd7c
MR
930 ssh_config->username,
931 ssh_config->client_privkey_path,
996c9314 932 ssh_config->server_hostkey_path != NULL
dabecd7c
MR
933 ? ssh_config
934 ->server_hostkey_path
935 : " ");
936 break;
937#endif
938 default:
939 break;
940 }
941
942 vty_out(vty, "preference %hhu\n", cache->preference);
943 }
944 vty_out(vty, " exit\n");
945 return 1;
946 } else {
947 return 0;
948 }
949}
950
951DEFUN_NOSH (rpki,
952 rpki_cmd,
953 "rpki",
954 "Enable rpki and enter rpki configuration mode\n")
955{
956 vty->node = RPKI_NODE;
957 return CMD_SUCCESS;
958}
959
960DEFUN (bgp_rpki_start,
961 bgp_rpki_start_cmd,
962 "rpki start",
963 RPKI_OUTPUT_STRING
964 "start rpki support\n")
965{
966 if (listcount(cache_list) == 0)
996c9314
LB
967 vty_out(vty,
968 "Could not start rpki because no caches are configured\n");
dabecd7c
MR
969
970 if (!is_running()) {
971 if (start() == ERROR) {
972 RPKI_DEBUG("RPKI failed to start");
973 return CMD_WARNING;
974 }
975 }
976 return CMD_SUCCESS;
977}
978
979DEFUN (bgp_rpki_stop,
980 bgp_rpki_stop_cmd,
981 "rpki stop",
982 RPKI_OUTPUT_STRING
983 "start rpki support\n")
984{
985 if (is_running())
986 stop();
987
988 return CMD_SUCCESS;
989}
990
991DEFPY (rpki_polling_period,
992 rpki_polling_period_cmd,
993 "rpki polling_period (1-86400)$pp",
994 RPKI_OUTPUT_STRING
995 "Set polling period\n"
996 "Polling period value\n")
997{
998 polling_period = pp;
999 return CMD_SUCCESS;
1000}
1001
1002DEFUN (no_rpki_polling_period,
1003 no_rpki_polling_period_cmd,
1004 "no rpki polling_period",
1005 NO_STR
1006 RPKI_OUTPUT_STRING
1007 "Set polling period back to default\n")
1008{
1009 polling_period = POLLING_PERIOD_DEFAULT;
1010 return CMD_SUCCESS;
1011}
1012
1013DEFPY (rpki_expire_interval,
1014 rpki_expire_interval_cmd,
1015 "rpki expire_interval (600-172800)$tmp",
1016 RPKI_OUTPUT_STRING
1017 "Set expire interval\n"
1018 "Expire interval value\n")
1019{
6f577f58 1020 if ((unsigned int)tmp >= polling_period) {
dabecd7c
MR
1021 expire_interval = tmp;
1022 return CMD_SUCCESS;
1023 }
1024
1025 vty_out(vty, "%% Expiry interval must be polling period or larger\n");
1026 return CMD_WARNING_CONFIG_FAILED;
1027}
1028
1029DEFUN (no_rpki_expire_interval,
1030 no_rpki_expire_interval_cmd,
1031 "no rpki expire_interval",
1032 NO_STR
1033 RPKI_OUTPUT_STRING
1034 "Set expire interval back to default\n")
1035{
1036 expire_interval = polling_period * 2;
1037 return CMD_SUCCESS;
1038}
1039
1040DEFPY (rpki_retry_interval,
1041 rpki_retry_interval_cmd,
1042 "rpki retry_interval (1-7200)$tmp",
1043 RPKI_OUTPUT_STRING
1044 "Set retry interval\n"
1045 "retry interval value\n")
1046{
1047 retry_interval = tmp;
1048 return CMD_SUCCESS;
1049}
1050
1051DEFUN (no_rpki_retry_interval,
1052 no_rpki_retry_interval_cmd,
1053 "no rpki retry_interval",
1054 NO_STR
1055 RPKI_OUTPUT_STRING
1056 "Set retry interval back to default\n")
1057{
1058 retry_interval = RETRY_INTERVAL_DEFAULT;
1059 return CMD_SUCCESS;
1060}
1061
dd783f3e
MR
1062#if (CONFDATE > 20200901)
1063CPP_NOTICE("bgpd: time to remove rpki timeout")
1064CPP_NOTICE("bgpd: this includes rpki_timeout and rpki_synchronisation_timeout")
1065#endif
1066
1067DEFPY_HIDDEN (rpki_timeout,
dabecd7c
MR
1068 rpki_timeout_cmd,
1069 "rpki timeout (1-4294967295)$to_arg",
1070 RPKI_OUTPUT_STRING
1071 "Set timeout\n"
1072 "Timeout value\n")
1073{
dd783f3e
MR
1074 vty_out(vty,
1075 "This config option is deprecated, and is scheduled for removal.\n");
1076 vty_out(vty,
1077 "This functionality has also already been removed because it caused bugs and was pointless\n");
dabecd7c
MR
1078 return CMD_SUCCESS;
1079}
1080
dd783f3e 1081DEFUN_HIDDEN (no_rpki_timeout,
dabecd7c
MR
1082 no_rpki_timeout_cmd,
1083 "no rpki timeout",
1084 NO_STR
1085 RPKI_OUTPUT_STRING
1086 "Set timeout back to default\n")
1087{
dd783f3e
MR
1088 vty_out(vty,
1089 "This config option is deprecated, and is scheduled for removal.\n");
1090 vty_out(vty,
1091 "This functionality has also already been removed because it caused bugs and was pointless\n");
dabecd7c
MR
1092 return CMD_SUCCESS;
1093}
1094
dd783f3e 1095DEFPY_HIDDEN (rpki_synchronisation_timeout,
dabecd7c
MR
1096 rpki_synchronisation_timeout_cmd,
1097 "rpki initial-synchronisation-timeout (1-4294967295)$ito_arg",
1098 RPKI_OUTPUT_STRING
1099 "Set a timeout for the initial synchronisation of prefix validation data\n"
1100 "Timeout value\n")
1101{
dd783f3e
MR
1102 vty_out(vty,
1103 "This config option is deprecated, and is scheduled for removal.\n");
1104 vty_out(vty,
1105 "This functionality has also already been removed because it caused bugs and was pointless\n");
dabecd7c
MR
1106 return CMD_SUCCESS;
1107}
1108
dd783f3e 1109DEFUN_HIDDEN (no_rpki_synchronisation_timeout,
dabecd7c
MR
1110 no_rpki_synchronisation_timeout_cmd,
1111 "no rpki initial-synchronisation-timeout",
1112 NO_STR
1113 RPKI_OUTPUT_STRING
1114 "Set the initial synchronisation timeout back to default (30 sec.)\n")
1115{
dd783f3e
MR
1116 vty_out(vty,
1117 "This config option is deprecated, and is scheduled for removal.\n");
1118 vty_out(vty,
1119 "This functionality has also already been removed because it caused bugs and was pointless\n");
dabecd7c
MR
1120 return CMD_SUCCESS;
1121}
1122
1123DEFPY (rpki_cache,
1124 rpki_cache_cmd,
1125 "rpki cache <A.B.C.D|WORD>"
1126 "<TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY SSH_PUBKEY [SERVER_PUBKEY]> "
1127 "preference (1-255)",
1128 RPKI_OUTPUT_STRING
1129 "Install a cache server to current group\n"
1130 "IP address of cache server\n Hostname of cache server\n"
1131 "TCP port number\n"
1132 "SSH port number\n"
1133 "SSH user name\n"
1134 "Path to own SSH private key\n"
1135 "Path to own SSH public key\n"
1136 "Path to Public key of cache server\n"
1137 "Preference of the cache server\n"
1138 "Preference value\n")
1139{
3f54c705 1140 int return_value;
a2ed7b2b
MR
1141 struct listnode *cache_node;
1142 struct cache *current_cache;
1143
1144 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, current_cache)) {
1145 if (current_cache->preference == preference) {
1146 vty_out(vty,
1147 "Cache with preference %ld is already configured\n",
1148 preference);
1149 return CMD_WARNING;
1150 }
1151 }
1152
dabecd7c
MR
1153
1154 // use ssh connection
1155 if (ssh_uname) {
1156#if defined(FOUND_SSH)
996c9314
LB
1157 return_value =
1158 add_ssh_cache(cache, sshport, ssh_uname, ssh_privkey,
1159 ssh_pubkey, server_pubkey, preference);
dabecd7c 1160#else
3f54c705 1161 return_value = SUCCESS;
dabecd7c
MR
1162 vty_out(vty,
1163 "ssh sockets are not supported. "
1164 "Please recompile rtrlib and frr with ssh support. "
0e43d16b 1165 "If you want to use it\n");
dabecd7c
MR
1166#endif
1167 } else { // use tcp connection
1168 return_value = add_tcp_cache(cache, tcpport, preference);
1169 }
1170
1171 if (return_value == ERROR) {
1172 vty_out(vty, "Could not create new rpki cache\n");
1173 return CMD_WARNING;
1174 }
1175
1176 return CMD_SUCCESS;
1177}
1178
1179DEFPY (no_rpki_cache,
1180 no_rpki_cache_cmd,
1181 "no rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport> preference (1-255)$preference",
1182 NO_STR
1183 RPKI_OUTPUT_STRING
1184 "Remove a cache server\n"
1185 "IP address of cache server\n Hostname of cache server\n"
1186 "TCP port number\n"
1187 "SSH port number\n"
1188 "Preference of the cache server\n"
1189 "Preference value\n")
1190{
1191 struct cache *cache_p = find_cache(preference);
1192
222487fe 1193 if (!cache_p) {
dabecd7c
MR
1194 vty_out(vty, "Could not find cache %ld\n", preference);
1195 return CMD_WARNING;
1196 }
1197
8add1719
MR
1198 if (rtr_is_running && listcount(cache_list) == 1) {
1199 stop();
1200 } else if (rtr_is_running) {
dabecd7c
MR
1201 if (rtr_mgr_remove_group(rtr_config, preference) == RTR_ERROR) {
1202 vty_out(vty, "Could not remove cache %ld", preference);
dabecd7c
MR
1203
1204 vty_out(vty, "\n");
1205 return CMD_WARNING;
1206 }
1207 }
1208
1209 listnode_delete(cache_list, cache_p);
1210 free_cache(cache_p);
1211
1212 return CMD_SUCCESS;
1213}
1214
1215DEFUN (show_rpki_prefix_table,
1216 show_rpki_prefix_table_cmd,
1217 "show rpki prefix-table",
1218 SHOW_STR
1219 RPKI_OUTPUT_STRING
08f9cfb8 1220 "Show validated prefixes which were received from RPKI Cache\n")
dabecd7c
MR
1221{
1222 struct listnode *cache_node;
1223 struct cache *cache;
1224
1225 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
996c9314 1226 vty_out(vty, "host: %s port: %s\n",
dabecd7c
MR
1227 cache->tr_config.tcp_config->host,
1228 cache->tr_config.tcp_config->port);
1229 }
1230 if (is_synchronized())
1231 print_prefix_table(vty);
1232 else
1233 vty_out(vty, "No connection to RPKI cache server.\n");
1234
1235 return CMD_SUCCESS;
1236}
1237
02334bb2
DA
1238DEFPY(show_rpki_as_number, show_rpki_as_number_cmd,
1239 "show rpki as-number (1-4294967295)$by_asn",
1240 SHOW_STR RPKI_OUTPUT_STRING
1241 "Lookup by ASN in prefix table\n"
1242 "AS Number\n")
1243{
1244 if (!is_synchronized()) {
1245 vty_out(vty, "No Connection to RPKI cache server.\n");
1246 return CMD_WARNING;
1247 }
1248
1249 print_prefix_table_by_asn(vty, by_asn);
1250 return CMD_SUCCESS;
1251}
1252
5d799192
MR
1253DEFPY (show_rpki_prefix,
1254 show_rpki_prefix_cmd,
1255 "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn]",
1256 SHOW_STR
1257 RPKI_OUTPUT_STRING
1258 "Lookup IP prefix and optionally ASN in prefix table\n"
1259 "IPv4 prefix\n"
1260 "IPv6 prefix\n"
1261 "AS Number\n")
1262{
1263
1264 if (!is_synchronized()) {
f79f7a7b 1265 vty_out(vty, "No Connection to RPKI cache server.\n");
5d799192
MR
1266 return CMD_WARNING;
1267 }
1268
1269 struct lrtr_ip_addr addr;
1270 char addr_str[INET6_ADDRSTRLEN];
1271 size_t addr_len = strchr(prefix_str, '/') - prefix_str;
1272
1273 memset(addr_str, 0, sizeof(addr_str));
1274 memcpy(addr_str, prefix_str, addr_len);
1275
1276 if (lrtr_ip_str_to_addr(addr_str, &addr) != 0) {
1277 vty_out(vty, "Invalid IP prefix\n");
1278 return CMD_WARNING;
1279 }
1280
1281 struct pfx_record *matches = NULL;
1282 unsigned int match_count = 0;
1283 enum pfxv_state result;
1284
1285 if (pfx_table_validate_r(rtr_config->pfx_table, &matches, &match_count,
1286 asn, &addr, prefix->prefixlen, &result)
1287 != PFX_SUCCESS) {
1288 vty_out(vty, "Prefix lookup failed");
1289 return CMD_WARNING;
1290 }
1291
1292 vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
1293 for (size_t i = 0; i < match_count; ++i) {
1294 const struct pfx_record *record = &matches[i];
1295
1296 if (record->max_len >= prefix->prefixlen
c17140fd
DS
1297 && ((asn != 0 && (uint32_t)asn == record->asn)
1298 || asn == 0)) {
5d799192
MR
1299 print_record(&matches[i], vty);
1300 }
1301 }
1302
1303 return CMD_SUCCESS;
1304}
1305
dabecd7c
MR
1306DEFUN (show_rpki_cache_server,
1307 show_rpki_cache_server_cmd,
1308 "show rpki cache-server",
1309 SHOW_STR
1310 RPKI_OUTPUT_STRING
08f9cfb8 1311 "SHOW configured cache server\n")
dabecd7c
MR
1312{
1313 struct listnode *cache_node;
1314 struct cache *cache;
1315
1316 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
745ae9c0
MR
1317 if (cache->type == TCP) {
1318 vty_out(vty, "host: %s port: %s\n",
1319 cache->tr_config.tcp_config->host,
1320 cache->tr_config.tcp_config->port);
1321
fef6fafa 1322#if defined(FOUND_SSH)
745ae9c0
MR
1323 } else if (cache->type == SSH) {
1324 vty_out(vty,
1325 "host: %s port: %d username: %s "
1326 "server_hostkey_path: %s client_privkey_path: %s\n",
1327 cache->tr_config.ssh_config->host,
1328 cache->tr_config.ssh_config->port,
1329 cache->tr_config.ssh_config->username,
1330 cache->tr_config.ssh_config
1331 ->server_hostkey_path,
1332 cache->tr_config.ssh_config
1333 ->client_privkey_path);
fef6fafa 1334#endif
745ae9c0 1335 }
dabecd7c
MR
1336 }
1337
1338 return CMD_SUCCESS;
1339}
1340
1341DEFUN (show_rpki_cache_connection,
1342 show_rpki_cache_connection_cmd,
1343 "show rpki cache-connection",
1344 SHOW_STR
1345 RPKI_OUTPUT_STRING
08f9cfb8 1346 "Show to which RPKI Cache Servers we have a connection\n")
dabecd7c
MR
1347{
1348 if (is_synchronized()) {
1349 struct listnode *cache_node;
1350 struct cache *cache;
1351 struct rtr_mgr_group *group = get_connected_group();
1352
1353 if (!group) {
1354 vty_out(vty, "Cannot find a connected group.\n");
1355 return CMD_SUCCESS;
1356 }
1357 vty_out(vty, "Connected to group %d\n", group->preference);
996c9314 1358 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
dabecd7c
MR
1359 if (cache->preference == group->preference) {
1360 struct tr_tcp_config *tcp_config;
acd4a9f4 1361#if defined(FOUND_SSH)
dabecd7c 1362 struct tr_ssh_config *ssh_config;
acd4a9f4 1363#endif
dabecd7c
MR
1364
1365 switch (cache->type) {
1366 case TCP:
1367 tcp_config =
996c9314 1368 cache->tr_config.tcp_config;
dabecd7c
MR
1369 vty_out(vty,
1370 "rpki tcp cache %s %s pref %hhu\n",
1371 tcp_config->host,
1372 tcp_config->port,
1373 cache->preference);
1374 break;
1375
1376#if defined(FOUND_SSH)
1377 case SSH:
1378 ssh_config =
996c9314 1379 cache->tr_config.ssh_config;
dabecd7c
MR
1380 vty_out(vty,
1381 "rpki ssh cache %s %u pref %hhu\n",
1382 ssh_config->host,
1383 ssh_config->port,
1384 cache->preference);
1385 break;
1386#endif
1387
1388 default:
1389 break;
1390 }
1391 }
1392 }
1393 } else {
1394 vty_out(vty, "No connection to RPKI cache server.\n");
1395 }
1396
1397 return CMD_SUCCESS;
1398}
1399
1400DEFUN_NOSH (rpki_exit,
1401 rpki_exit_cmd,
1402 "exit",
08f9cfb8 1403 "Exit rpki configuration and restart rpki session\n")
dabecd7c 1404{
61a484a9 1405 reset(false);
dabecd7c
MR
1406
1407 vty->node = CONFIG_NODE;
61a484a9 1408 return CMD_SUCCESS;
dabecd7c
MR
1409}
1410
1411DEFUN_NOSH (rpki_quit,
1412 rpki_quit_cmd,
1413 "quit",
08f9cfb8 1414 "Exit rpki configuration mode\n")
dabecd7c
MR
1415{
1416 return rpki_exit(self, vty, argc, argv);
1417}
1418
1419DEFUN_NOSH (rpki_end,
1420 rpki_end_cmd,
1421 "end",
08f9cfb8 1422 "End rpki configuration, restart rpki session and change to enable mode.\n")
dabecd7c
MR
1423{
1424 int ret = reset(false);
1425
f344c66e 1426 vty_config_exit(vty);
dabecd7c
MR
1427 vty->node = ENABLE_NODE;
1428 return ret == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1429}
1430
1431DEFUN (rpki_reset,
1432 rpki_reset_cmd,
1433 "rpki reset",
1434 RPKI_OUTPUT_STRING
1435 "reset rpki\n")
1436{
1437 return reset(true) == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1438}
1439
1440DEFUN (debug_rpki,
1441 debug_rpki_cmd,
1442 "debug rpki",
1443 DEBUG_STR
08f9cfb8 1444 "Enable debugging for rpki\n")
dabecd7c
MR
1445{
1446 rpki_debug = 1;
1447 return CMD_SUCCESS;
1448}
1449
1450DEFUN (no_debug_rpki,
1451 no_debug_rpki_cmd,
1452 "no debug rpki",
1453 NO_STR
1454 DEBUG_STR
08f9cfb8 1455 "Disable debugging for rpki\n")
dabecd7c
MR
1456{
1457 rpki_debug = 0;
1458 return CMD_SUCCESS;
1459}
1460
1461DEFUN (match_rpki,
1462 match_rpki_cmd,
1463 "match rpki <valid|invalid|notfound>",
1464 MATCH_STR
1465 RPKI_OUTPUT_STRING
1466 "Valid prefix\n"
1467 "Invalid prefix\n"
1468 "Prefix not found\n")
1469{
1470 VTY_DECLVAR_CONTEXT(route_map_index, index);
cda7187d 1471 enum rmap_compile_rets ret;
dabecd7c 1472
e2c8d6ce
NT
1473 ret = route_map_add_match(index, "rpki", argv[2]->arg,
1474 RMAP_EVENT_MATCH_ADDED);
69337c34
DS
1475 switch (ret) {
1476 case RMAP_RULE_MISSING:
1477 vty_out(vty, "%% BGP Can't find rule.\n");
1478 return CMD_WARNING_CONFIG_FAILED;
1479 case RMAP_COMPILE_ERROR:
1480 vty_out(vty, "%% BGP Argument is malformed.\n");
1481 return CMD_WARNING_CONFIG_FAILED;
1482 case RMAP_COMPILE_SUCCESS:
1483 return CMD_SUCCESS;
1484 break;
dabecd7c 1485 }
69337c34 1486
dabecd7c
MR
1487 return CMD_SUCCESS;
1488}
1489
1490DEFUN (no_match_rpki,
1491 no_match_rpki_cmd,
1492 "no match rpki <valid|invalid|notfound>",
1493 NO_STR
1494 MATCH_STR
1495 RPKI_OUTPUT_STRING
1496 "Valid prefix\n"
1497 "Invalid prefix\n"
1498 "Prefix not found\n")
1499{
1500 VTY_DECLVAR_CONTEXT(route_map_index, index);
cda7187d 1501 enum rmap_compile_rets ret;
dabecd7c 1502
909f3d56 1503 ret = route_map_delete_match(index, "rpki", argv[3]->arg,
1504 RMAP_EVENT_MATCH_DELETED);
69337c34
DS
1505 switch (ret) {
1506 case RMAP_RULE_MISSING:
1507 vty_out(vty, "%% BGP Can't find rule.\n");
1508 return CMD_WARNING_CONFIG_FAILED;
1509 break;
1510 case RMAP_COMPILE_ERROR:
1511 vty_out(vty, "%% BGP Argument is malformed.\n");
dabecd7c 1512 return CMD_WARNING_CONFIG_FAILED;
69337c34
DS
1513 break;
1514 case RMAP_COMPILE_SUCCESS:
1515 return CMD_SUCCESS;
1516 break;
dabecd7c
MR
1517 }
1518
1519 return CMD_SUCCESS;
1520}
1521
1522static void overwrite_exit_commands(void)
1523{
1524 unsigned int i;
1525 vector cmd_vector = rpki_node.cmd_vector;
1526
1527 for (i = 0; i < cmd_vector->active; ++i) {
1528 struct cmd_element *cmd = vector_lookup(cmd_vector, i);
1529
996c9314
LB
1530 if (strcmp(cmd->string, "exit") == 0
1531 || strcmp(cmd->string, "quit") == 0
1532 || strcmp(cmd->string, "end") == 0) {
dabecd7c
MR
1533 uninstall_element(RPKI_NODE, cmd);
1534 }
1535 }
1536
1537 install_element(RPKI_NODE, &rpki_exit_cmd);
1538 install_element(RPKI_NODE, &rpki_quit_cmd);
1539 install_element(RPKI_NODE, &rpki_end_cmd);
1540}
1541
1542static void install_cli_commands(void)
1543{
996c9314 1544 // TODO: make config write work
dabecd7c
MR
1545 install_node(&rpki_node, &config_write);
1546 install_default(RPKI_NODE);
1547 overwrite_exit_commands();
1548 install_element(CONFIG_NODE, &rpki_cmd);
9593708d 1549 install_element(ENABLE_NODE, &rpki_cmd);
dabecd7c
MR
1550
1551 install_element(ENABLE_NODE, &bgp_rpki_start_cmd);
1552 install_element(ENABLE_NODE, &bgp_rpki_stop_cmd);
1553
1554 /* Install rpki reset command */
1555 install_element(RPKI_NODE, &rpki_reset_cmd);
1556
1557 /* Install rpki polling period commands */
1558 install_element(RPKI_NODE, &rpki_polling_period_cmd);
1559 install_element(RPKI_NODE, &no_rpki_polling_period_cmd);
1560
1561 /* Install rpki expire interval commands */
1562 install_element(RPKI_NODE, &rpki_expire_interval_cmd);
1563 install_element(RPKI_NODE, &no_rpki_expire_interval_cmd);
1564
1565 /* Install rpki retry interval commands */
1566 install_element(RPKI_NODE, &rpki_retry_interval_cmd);
1567 install_element(RPKI_NODE, &no_rpki_retry_interval_cmd);
1568
1569 /* Install rpki timeout commands */
1570 install_element(RPKI_NODE, &rpki_timeout_cmd);
1571 install_element(RPKI_NODE, &no_rpki_timeout_cmd);
1572
1573 /* Install rpki synchronisation timeout commands */
1574 install_element(RPKI_NODE, &rpki_synchronisation_timeout_cmd);
1575 install_element(RPKI_NODE, &no_rpki_synchronisation_timeout_cmd);
1576
1577 /* Install rpki cache commands */
1578 install_element(RPKI_NODE, &rpki_cache_cmd);
1579 install_element(RPKI_NODE, &no_rpki_cache_cmd);
1580
1581 /* Install show commands */
9593708d 1582 install_element(VIEW_NODE, &show_rpki_prefix_table_cmd);
1583 install_element(VIEW_NODE, &show_rpki_cache_connection_cmd);
1584 install_element(VIEW_NODE, &show_rpki_cache_server_cmd);
1585 install_element(VIEW_NODE, &show_rpki_prefix_cmd);
02334bb2 1586 install_element(VIEW_NODE, &show_rpki_as_number_cmd);
dabecd7c
MR
1587
1588 /* Install debug commands */
1589 install_element(CONFIG_NODE, &debug_rpki_cmd);
1590 install_element(ENABLE_NODE, &debug_rpki_cmd);
1591 install_element(CONFIG_NODE, &no_debug_rpki_cmd);
1592 install_element(ENABLE_NODE, &no_debug_rpki_cmd);
1593
1594 /* Install route match */
1595 route_map_install_match(&route_match_rpki_cmd);
1596 install_element(RMAP_NODE, &match_rpki_cmd);
1597 install_element(RMAP_NODE, &no_match_rpki_cmd);
1598}
1599
1600FRR_MODULE_SETUP(.name = "bgpd_rpki", .version = "0.3.6",
1601 .description = "Enable RPKI support for FRR.",
996c9314 1602 .init = bgp_rpki_module_init)