]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_rpki.c
tools: add source code string mangler
[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;
705 char buf[BUFSIZ];
706 const char *prefix_string;
707
708 if (!is_synchronized())
709 return 0;
710
711 // No aspath means route comes from iBGP
712 if (!attr->aspath || !attr->aspath->segments) {
713 // Set own as number
714 as_number = peer->bgp->as;
715 } else {
716 as_segment = attr->aspath->segments;
717 // Find last AsSegment
718 while (as_segment->next)
719 as_segment = as_segment->next;
720
721 if (as_segment->type == AS_SEQUENCE) {
722 // Get rightmost asn
723 as_number = as_segment->as[as_segment->length - 1];
996c9314
LB
724 } else if (as_segment->type == AS_CONFED_SEQUENCE
725 || as_segment->type == AS_CONFED_SET) {
dabecd7c
MR
726 // Set own as number
727 as_number = peer->bgp->as;
728 } else {
729 // RFC says: "Take distinguished value NONE as asn"
730 // which means state is unknown
731 return RPKI_NOTFOUND;
732 }
733 }
734
735 // Get the prefix in requested format
736 switch (prefix->family) {
737 case AF_INET:
738 ip_addr_prefix.ver = LRTR_IPV4;
739 ip_addr_prefix.u.addr4.addr = ntohl(prefix->u.prefix4.s_addr);
740 break;
741
dabecd7c
MR
742 case AF_INET6:
743 ip_addr_prefix.ver = LRTR_IPV6;
744 ipv6_addr_to_host_byte_order(prefix->u.prefix6.s6_addr32,
745 ip_addr_prefix.u.addr6.addr);
746 break;
dabecd7c
MR
747
748 default:
749 return 0;
750 }
751
752 // Do the actual validation
753 rtr_mgr_validate(rtr_config, as_number, &ip_addr_prefix,
754 prefix->prefixlen, &result);
755
756 // Print Debug output
7c3f0950 757 prefix_string = prefix2str(prefix, buf, sizeof(buf));
dabecd7c
MR
758 switch (result) {
759 case BGP_PFXV_STATE_VALID:
760 RPKI_DEBUG(
7c3f0950
DS
761 "Validating Prefix %s from asn %u Result: VALID",
762 prefix_string, as_number);
dabecd7c
MR
763 return RPKI_VALID;
764 case BGP_PFXV_STATE_NOT_FOUND:
765 RPKI_DEBUG(
7c3f0950
DS
766 "Validating Prefix %s from asn %u Result: NOT FOUND",
767 prefix_string, as_number);
dabecd7c
MR
768 return RPKI_NOTFOUND;
769 case BGP_PFXV_STATE_INVALID:
770 RPKI_DEBUG(
7c3f0950
DS
771 "Validating Prefix %s from asn %u Result: INVALID",
772 prefix_string, as_number);
dabecd7c
MR
773 return RPKI_INVALID;
774 default:
775 RPKI_DEBUG(
7c3f0950
DS
776 "Validating Prefix %s from asn %u Result: CANNOT VALIDATE",
777 prefix_string, as_number);
dabecd7c
MR
778 break;
779 }
780 return 0;
781}
782
783static int add_cache(struct cache *cache)
784{
785 uint8_t preference = cache->preference;
786 struct rtr_mgr_group group;
787
788 group.preference = preference;
789 group.sockets_len = 1;
790 group.sockets = &cache->rtr_socket;
791
92110aab
MR
792 if (rtr_is_running) {
793 init_tr_socket(cache);
794
795 if (rtr_mgr_add_group(rtr_config, &group) != RTR_SUCCESS) {
796 free_tr_socket(cache);
797 return ERROR;
798 }
dabecd7c
MR
799 }
800
6893064b
MR
801 listnode_add(cache_list, cache);
802
dabecd7c
MR
803 return SUCCESS;
804}
805
996c9314 806static int add_tcp_cache(const char *host, const char *port,
dabecd7c
MR
807 const uint8_t preference)
808{
809 struct rtr_socket *rtr_socket;
810 struct tr_tcp_config *tcp_config =
a633498e 811 XCALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_tcp_config));
dabecd7c
MR
812 struct tr_socket *tr_socket =
813 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
814 struct cache *cache =
815 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
816
817 tcp_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
818 tcp_config->port = XSTRDUP(MTYPE_BGP_RPKI_CACHE, port);
819 tcp_config->bindaddr = NULL;
820
821 rtr_socket = create_rtr_socket(tr_socket);
822
823 cache->type = TCP;
824 cache->tr_socket = tr_socket;
825 cache->tr_config.tcp_config = tcp_config;
826 cache->rtr_socket = rtr_socket;
827 cache->preference = preference;
828
6893064b
MR
829 int ret = add_cache(cache);
830 if (ret != SUCCESS) {
831 free_cache(cache);
832 }
833
834 return ret;
dabecd7c
MR
835}
836
837#if defined(FOUND_SSH)
996c9314
LB
838static int add_ssh_cache(const char *host, const unsigned int port,
839 const char *username, const char *client_privkey_path,
dabecd7c
MR
840 const char *client_pubkey_path,
841 const char *server_pubkey_path,
842 const uint8_t preference)
843{
844 struct tr_ssh_config *ssh_config =
a633498e 845 XCALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_ssh_config));
dabecd7c
MR
846 struct cache *cache =
847 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
848 struct tr_socket *tr_socket =
849 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
850 struct rtr_socket *rtr_socket;
851
852 ssh_config->port = port;
853 ssh_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
854 ssh_config->bindaddr = NULL;
855
856 ssh_config->username = XSTRDUP(MTYPE_BGP_RPKI_CACHE, username);
996c9314
LB
857 ssh_config->client_privkey_path =
858 XSTRDUP(MTYPE_BGP_RPKI_CACHE, client_privkey_path);
dabecd7c
MR
859 ssh_config->server_hostkey_path =
860 XSTRDUP(MTYPE_BGP_RPKI_CACHE, server_pubkey_path);
861
862 rtr_socket = create_rtr_socket(tr_socket);
863
864 cache->type = SSH;
865 cache->tr_socket = tr_socket;
866 cache->tr_config.ssh_config = ssh_config;
867 cache->rtr_socket = rtr_socket;
868 cache->preference = preference;
869
6893064b
MR
870 int ret = add_cache(cache);
871 if (ret != SUCCESS) {
872 free_cache(cache);
873 }
874
875 return ret;
dabecd7c
MR
876}
877#endif
878
879static void free_cache(struct cache *cache)
880{
881 if (cache->type == TCP) {
996c9314
LB
882 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->host);
883 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->port);
dabecd7c
MR
884 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config);
885 }
886#if defined(FOUND_SSH)
887 else {
996c9314 888 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config->host);
dabecd7c
MR
889 XFREE(MTYPE_BGP_RPKI_CACHE,
890 cache->tr_config.ssh_config->username);
891 XFREE(MTYPE_BGP_RPKI_CACHE,
892 cache->tr_config.ssh_config->client_privkey_path);
893 XFREE(MTYPE_BGP_RPKI_CACHE,
894 cache->tr_config.ssh_config->server_hostkey_path);
895 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config);
896 }
897#endif
898 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_socket);
899 XFREE(MTYPE_BGP_RPKI_CACHE, cache->rtr_socket);
900 XFREE(MTYPE_BGP_RPKI_CACHE, cache);
901}
902
903static int config_write(struct vty *vty)
904{
905 struct listnode *cache_node;
906 struct cache *cache;
907
908 if (listcount(cache_list)) {
909 if (rpki_debug)
910 vty_out(vty, "debug rpki\n");
911
912 vty_out(vty, "!\n");
913 vty_out(vty, "rpki\n");
914 vty_out(vty, " rpki polling_period %d\n", polling_period);
dabecd7c
MR
915 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
916 switch (cache->type) {
917 struct tr_tcp_config *tcp_config;
acd4a9f4 918#if defined(FOUND_SSH)
dabecd7c 919 struct tr_ssh_config *ssh_config;
acd4a9f4 920#endif
dabecd7c
MR
921 case TCP:
922 tcp_config = cache->tr_config.tcp_config;
996c9314
LB
923 vty_out(vty, " rpki cache %s %s ",
924 tcp_config->host, tcp_config->port);
dabecd7c
MR
925 break;
926#if defined(FOUND_SSH)
927 case SSH:
928 ssh_config = cache->tr_config.ssh_config;
996c9314
LB
929 vty_out(vty, " rpki cache %s %u %s %s %s ",
930 ssh_config->host, ssh_config->port,
dabecd7c
MR
931 ssh_config->username,
932 ssh_config->client_privkey_path,
996c9314 933 ssh_config->server_hostkey_path != NULL
dabecd7c
MR
934 ? ssh_config
935 ->server_hostkey_path
936 : " ");
937 break;
938#endif
939 default:
940 break;
941 }
942
943 vty_out(vty, "preference %hhu\n", cache->preference);
944 }
945 vty_out(vty, " exit\n");
946 return 1;
947 } else {
948 return 0;
949 }
950}
951
952DEFUN_NOSH (rpki,
953 rpki_cmd,
954 "rpki",
955 "Enable rpki and enter rpki configuration mode\n")
956{
957 vty->node = RPKI_NODE;
958 return CMD_SUCCESS;
959}
960
961DEFUN (bgp_rpki_start,
962 bgp_rpki_start_cmd,
963 "rpki start",
964 RPKI_OUTPUT_STRING
965 "start rpki support\n")
966{
967 if (listcount(cache_list) == 0)
996c9314
LB
968 vty_out(vty,
969 "Could not start rpki because no caches are configured\n");
dabecd7c
MR
970
971 if (!is_running()) {
972 if (start() == ERROR) {
973 RPKI_DEBUG("RPKI failed to start");
974 return CMD_WARNING;
975 }
976 }
977 return CMD_SUCCESS;
978}
979
980DEFUN (bgp_rpki_stop,
981 bgp_rpki_stop_cmd,
982 "rpki stop",
983 RPKI_OUTPUT_STRING
984 "start rpki support\n")
985{
986 if (is_running())
987 stop();
988
989 return CMD_SUCCESS;
990}
991
992DEFPY (rpki_polling_period,
993 rpki_polling_period_cmd,
994 "rpki polling_period (1-86400)$pp",
995 RPKI_OUTPUT_STRING
996 "Set polling period\n"
997 "Polling period value\n")
998{
999 polling_period = pp;
1000 return CMD_SUCCESS;
1001}
1002
1003DEFUN (no_rpki_polling_period,
1004 no_rpki_polling_period_cmd,
1005 "no rpki polling_period",
1006 NO_STR
1007 RPKI_OUTPUT_STRING
1008 "Set polling period back to default\n")
1009{
1010 polling_period = POLLING_PERIOD_DEFAULT;
1011 return CMD_SUCCESS;
1012}
1013
1014DEFPY (rpki_expire_interval,
1015 rpki_expire_interval_cmd,
1016 "rpki expire_interval (600-172800)$tmp",
1017 RPKI_OUTPUT_STRING
1018 "Set expire interval\n"
1019 "Expire interval value\n")
1020{
6f577f58 1021 if ((unsigned int)tmp >= polling_period) {
dabecd7c
MR
1022 expire_interval = tmp;
1023 return CMD_SUCCESS;
1024 }
1025
1026 vty_out(vty, "%% Expiry interval must be polling period or larger\n");
1027 return CMD_WARNING_CONFIG_FAILED;
1028}
1029
1030DEFUN (no_rpki_expire_interval,
1031 no_rpki_expire_interval_cmd,
1032 "no rpki expire_interval",
1033 NO_STR
1034 RPKI_OUTPUT_STRING
1035 "Set expire interval back to default\n")
1036{
1037 expire_interval = polling_period * 2;
1038 return CMD_SUCCESS;
1039}
1040
1041DEFPY (rpki_retry_interval,
1042 rpki_retry_interval_cmd,
1043 "rpki retry_interval (1-7200)$tmp",
1044 RPKI_OUTPUT_STRING
1045 "Set retry interval\n"
1046 "retry interval value\n")
1047{
1048 retry_interval = tmp;
1049 return CMD_SUCCESS;
1050}
1051
1052DEFUN (no_rpki_retry_interval,
1053 no_rpki_retry_interval_cmd,
1054 "no rpki retry_interval",
1055 NO_STR
1056 RPKI_OUTPUT_STRING
1057 "Set retry interval back to default\n")
1058{
1059 retry_interval = RETRY_INTERVAL_DEFAULT;
1060 return CMD_SUCCESS;
1061}
1062
dd783f3e
MR
1063#if (CONFDATE > 20200901)
1064CPP_NOTICE("bgpd: time to remove rpki timeout")
1065CPP_NOTICE("bgpd: this includes rpki_timeout and rpki_synchronisation_timeout")
1066#endif
1067
1068DEFPY_HIDDEN (rpki_timeout,
dabecd7c
MR
1069 rpki_timeout_cmd,
1070 "rpki timeout (1-4294967295)$to_arg",
1071 RPKI_OUTPUT_STRING
1072 "Set timeout\n"
1073 "Timeout value\n")
1074{
dd783f3e
MR
1075 vty_out(vty,
1076 "This config option is deprecated, and is scheduled for removal.\n");
1077 vty_out(vty,
1078 "This functionality has also already been removed because it caused bugs and was pointless\n");
dabecd7c
MR
1079 return CMD_SUCCESS;
1080}
1081
dd783f3e 1082DEFUN_HIDDEN (no_rpki_timeout,
dabecd7c
MR
1083 no_rpki_timeout_cmd,
1084 "no rpki timeout",
1085 NO_STR
1086 RPKI_OUTPUT_STRING
1087 "Set timeout back to default\n")
1088{
dd783f3e
MR
1089 vty_out(vty,
1090 "This config option is deprecated, and is scheduled for removal.\n");
1091 vty_out(vty,
1092 "This functionality has also already been removed because it caused bugs and was pointless\n");
dabecd7c
MR
1093 return CMD_SUCCESS;
1094}
1095
dd783f3e 1096DEFPY_HIDDEN (rpki_synchronisation_timeout,
dabecd7c
MR
1097 rpki_synchronisation_timeout_cmd,
1098 "rpki initial-synchronisation-timeout (1-4294967295)$ito_arg",
1099 RPKI_OUTPUT_STRING
1100 "Set a timeout for the initial synchronisation of prefix validation data\n"
1101 "Timeout value\n")
1102{
dd783f3e
MR
1103 vty_out(vty,
1104 "This config option is deprecated, and is scheduled for removal.\n");
1105 vty_out(vty,
1106 "This functionality has also already been removed because it caused bugs and was pointless\n");
dabecd7c
MR
1107 return CMD_SUCCESS;
1108}
1109
dd783f3e 1110DEFUN_HIDDEN (no_rpki_synchronisation_timeout,
dabecd7c
MR
1111 no_rpki_synchronisation_timeout_cmd,
1112 "no rpki initial-synchronisation-timeout",
1113 NO_STR
1114 RPKI_OUTPUT_STRING
1115 "Set the initial synchronisation timeout back to default (30 sec.)\n")
1116{
dd783f3e
MR
1117 vty_out(vty,
1118 "This config option is deprecated, and is scheduled for removal.\n");
1119 vty_out(vty,
1120 "This functionality has also already been removed because it caused bugs and was pointless\n");
dabecd7c
MR
1121 return CMD_SUCCESS;
1122}
1123
1124DEFPY (rpki_cache,
1125 rpki_cache_cmd,
1126 "rpki cache <A.B.C.D|WORD>"
1127 "<TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY SSH_PUBKEY [SERVER_PUBKEY]> "
1128 "preference (1-255)",
1129 RPKI_OUTPUT_STRING
1130 "Install a cache server to current group\n"
1131 "IP address of cache server\n Hostname of cache server\n"
1132 "TCP port number\n"
1133 "SSH port number\n"
1134 "SSH user name\n"
1135 "Path to own SSH private key\n"
1136 "Path to own SSH public key\n"
1137 "Path to Public key of cache server\n"
1138 "Preference of the cache server\n"
1139 "Preference value\n")
1140{
3f54c705 1141 int return_value;
a2ed7b2b
MR
1142 struct listnode *cache_node;
1143 struct cache *current_cache;
1144
1145 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, current_cache)) {
1146 if (current_cache->preference == preference) {
1147 vty_out(vty,
1148 "Cache with preference %ld is already configured\n",
1149 preference);
1150 return CMD_WARNING;
1151 }
1152 }
1153
dabecd7c
MR
1154
1155 // use ssh connection
1156 if (ssh_uname) {
1157#if defined(FOUND_SSH)
996c9314
LB
1158 return_value =
1159 add_ssh_cache(cache, sshport, ssh_uname, ssh_privkey,
1160 ssh_pubkey, server_pubkey, preference);
dabecd7c 1161#else
3f54c705 1162 return_value = SUCCESS;
dabecd7c
MR
1163 vty_out(vty,
1164 "ssh sockets are not supported. "
1165 "Please recompile rtrlib and frr with ssh support. "
0e43d16b 1166 "If you want to use it\n");
dabecd7c
MR
1167#endif
1168 } else { // use tcp connection
1169 return_value = add_tcp_cache(cache, tcpport, preference);
1170 }
1171
1172 if (return_value == ERROR) {
1173 vty_out(vty, "Could not create new rpki cache\n");
1174 return CMD_WARNING;
1175 }
1176
1177 return CMD_SUCCESS;
1178}
1179
1180DEFPY (no_rpki_cache,
1181 no_rpki_cache_cmd,
1182 "no rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport> preference (1-255)$preference",
1183 NO_STR
1184 RPKI_OUTPUT_STRING
1185 "Remove a cache server\n"
1186 "IP address of cache server\n Hostname of cache server\n"
1187 "TCP port number\n"
1188 "SSH port number\n"
1189 "Preference of the cache server\n"
1190 "Preference value\n")
1191{
1192 struct cache *cache_p = find_cache(preference);
1193
222487fe 1194 if (!cache_p) {
dabecd7c
MR
1195 vty_out(vty, "Could not find cache %ld\n", preference);
1196 return CMD_WARNING;
1197 }
1198
8add1719
MR
1199 if (rtr_is_running && listcount(cache_list) == 1) {
1200 stop();
1201 } else if (rtr_is_running) {
dabecd7c
MR
1202 if (rtr_mgr_remove_group(rtr_config, preference) == RTR_ERROR) {
1203 vty_out(vty, "Could not remove cache %ld", preference);
dabecd7c
MR
1204
1205 vty_out(vty, "\n");
1206 return CMD_WARNING;
1207 }
1208 }
1209
1210 listnode_delete(cache_list, cache_p);
1211 free_cache(cache_p);
1212
1213 return CMD_SUCCESS;
1214}
1215
1216DEFUN (show_rpki_prefix_table,
1217 show_rpki_prefix_table_cmd,
1218 "show rpki prefix-table",
1219 SHOW_STR
1220 RPKI_OUTPUT_STRING
08f9cfb8 1221 "Show validated prefixes which were received from RPKI Cache\n")
dabecd7c
MR
1222{
1223 struct listnode *cache_node;
1224 struct cache *cache;
1225
1226 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
996c9314 1227 vty_out(vty, "host: %s port: %s\n",
dabecd7c
MR
1228 cache->tr_config.tcp_config->host,
1229 cache->tr_config.tcp_config->port);
1230 }
1231 if (is_synchronized())
1232 print_prefix_table(vty);
1233 else
1234 vty_out(vty, "No connection to RPKI cache server.\n");
1235
1236 return CMD_SUCCESS;
1237}
1238
02334bb2
DA
1239DEFPY(show_rpki_as_number, show_rpki_as_number_cmd,
1240 "show rpki as-number (1-4294967295)$by_asn",
1241 SHOW_STR RPKI_OUTPUT_STRING
1242 "Lookup by ASN in prefix table\n"
1243 "AS Number\n")
1244{
1245 if (!is_synchronized()) {
1246 vty_out(vty, "No Connection to RPKI cache server.\n");
1247 return CMD_WARNING;
1248 }
1249
1250 print_prefix_table_by_asn(vty, by_asn);
1251 return CMD_SUCCESS;
1252}
1253
5d799192
MR
1254DEFPY (show_rpki_prefix,
1255 show_rpki_prefix_cmd,
1256 "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn]",
1257 SHOW_STR
1258 RPKI_OUTPUT_STRING
1259 "Lookup IP prefix and optionally ASN in prefix table\n"
1260 "IPv4 prefix\n"
1261 "IPv6 prefix\n"
1262 "AS Number\n")
1263{
1264
1265 if (!is_synchronized()) {
f79f7a7b 1266 vty_out(vty, "No Connection to RPKI cache server.\n");
5d799192
MR
1267 return CMD_WARNING;
1268 }
1269
1270 struct lrtr_ip_addr addr;
1271 char addr_str[INET6_ADDRSTRLEN];
1272 size_t addr_len = strchr(prefix_str, '/') - prefix_str;
1273
1274 memset(addr_str, 0, sizeof(addr_str));
1275 memcpy(addr_str, prefix_str, addr_len);
1276
1277 if (lrtr_ip_str_to_addr(addr_str, &addr) != 0) {
1278 vty_out(vty, "Invalid IP prefix\n");
1279 return CMD_WARNING;
1280 }
1281
1282 struct pfx_record *matches = NULL;
1283 unsigned int match_count = 0;
1284 enum pfxv_state result;
1285
1286 if (pfx_table_validate_r(rtr_config->pfx_table, &matches, &match_count,
1287 asn, &addr, prefix->prefixlen, &result)
1288 != PFX_SUCCESS) {
1289 vty_out(vty, "Prefix lookup failed");
1290 return CMD_WARNING;
1291 }
1292
1293 vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
1294 for (size_t i = 0; i < match_count; ++i) {
1295 const struct pfx_record *record = &matches[i];
1296
1297 if (record->max_len >= prefix->prefixlen
c17140fd
DS
1298 && ((asn != 0 && (uint32_t)asn == record->asn)
1299 || asn == 0)) {
5d799192
MR
1300 print_record(&matches[i], vty);
1301 }
1302 }
1303
1304 return CMD_SUCCESS;
1305}
1306
dabecd7c
MR
1307DEFUN (show_rpki_cache_server,
1308 show_rpki_cache_server_cmd,
1309 "show rpki cache-server",
1310 SHOW_STR
1311 RPKI_OUTPUT_STRING
08f9cfb8 1312 "SHOW configured cache server\n")
dabecd7c
MR
1313{
1314 struct listnode *cache_node;
1315 struct cache *cache;
1316
1317 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
745ae9c0
MR
1318 if (cache->type == TCP) {
1319 vty_out(vty, "host: %s port: %s\n",
1320 cache->tr_config.tcp_config->host,
1321 cache->tr_config.tcp_config->port);
1322
fef6fafa 1323#if defined(FOUND_SSH)
745ae9c0
MR
1324 } else if (cache->type == SSH) {
1325 vty_out(vty,
1326 "host: %s port: %d username: %s "
1327 "server_hostkey_path: %s client_privkey_path: %s\n",
1328 cache->tr_config.ssh_config->host,
1329 cache->tr_config.ssh_config->port,
1330 cache->tr_config.ssh_config->username,
1331 cache->tr_config.ssh_config
1332 ->server_hostkey_path,
1333 cache->tr_config.ssh_config
1334 ->client_privkey_path);
fef6fafa 1335#endif
745ae9c0 1336 }
dabecd7c
MR
1337 }
1338
1339 return CMD_SUCCESS;
1340}
1341
1342DEFUN (show_rpki_cache_connection,
1343 show_rpki_cache_connection_cmd,
1344 "show rpki cache-connection",
1345 SHOW_STR
1346 RPKI_OUTPUT_STRING
08f9cfb8 1347 "Show to which RPKI Cache Servers we have a connection\n")
dabecd7c
MR
1348{
1349 if (is_synchronized()) {
1350 struct listnode *cache_node;
1351 struct cache *cache;
1352 struct rtr_mgr_group *group = get_connected_group();
1353
1354 if (!group) {
1355 vty_out(vty, "Cannot find a connected group.\n");
1356 return CMD_SUCCESS;
1357 }
1358 vty_out(vty, "Connected to group %d\n", group->preference);
996c9314 1359 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
dabecd7c
MR
1360 if (cache->preference == group->preference) {
1361 struct tr_tcp_config *tcp_config;
acd4a9f4 1362#if defined(FOUND_SSH)
dabecd7c 1363 struct tr_ssh_config *ssh_config;
acd4a9f4 1364#endif
dabecd7c
MR
1365
1366 switch (cache->type) {
1367 case TCP:
1368 tcp_config =
996c9314 1369 cache->tr_config.tcp_config;
dabecd7c
MR
1370 vty_out(vty,
1371 "rpki tcp cache %s %s pref %hhu\n",
1372 tcp_config->host,
1373 tcp_config->port,
1374 cache->preference);
1375 break;
1376
1377#if defined(FOUND_SSH)
1378 case SSH:
1379 ssh_config =
996c9314 1380 cache->tr_config.ssh_config;
dabecd7c
MR
1381 vty_out(vty,
1382 "rpki ssh cache %s %u pref %hhu\n",
1383 ssh_config->host,
1384 ssh_config->port,
1385 cache->preference);
1386 break;
1387#endif
1388
1389 default:
1390 break;
1391 }
1392 }
1393 }
1394 } else {
1395 vty_out(vty, "No connection to RPKI cache server.\n");
1396 }
1397
1398 return CMD_SUCCESS;
1399}
1400
791ded4a 1401static int config_on_exit(struct vty *vty)
dabecd7c 1402{
61a484a9 1403 reset(false);
791ded4a 1404 return 1;
dabecd7c
MR
1405}
1406
1407DEFUN (rpki_reset,
1408 rpki_reset_cmd,
1409 "rpki reset",
1410 RPKI_OUTPUT_STRING
1411 "reset rpki\n")
1412{
1413 return reset(true) == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1414}
1415
1416DEFUN (debug_rpki,
1417 debug_rpki_cmd,
1418 "debug rpki",
1419 DEBUG_STR
08f9cfb8 1420 "Enable debugging for rpki\n")
dabecd7c
MR
1421{
1422 rpki_debug = 1;
1423 return CMD_SUCCESS;
1424}
1425
1426DEFUN (no_debug_rpki,
1427 no_debug_rpki_cmd,
1428 "no debug rpki",
1429 NO_STR
1430 DEBUG_STR
08f9cfb8 1431 "Disable debugging for rpki\n")
dabecd7c
MR
1432{
1433 rpki_debug = 0;
1434 return CMD_SUCCESS;
1435}
1436
1437DEFUN (match_rpki,
1438 match_rpki_cmd,
1439 "match rpki <valid|invalid|notfound>",
1440 MATCH_STR
1441 RPKI_OUTPUT_STRING
1442 "Valid prefix\n"
1443 "Invalid prefix\n"
1444 "Prefix not found\n")
1445{
1446 VTY_DECLVAR_CONTEXT(route_map_index, index);
cda7187d 1447 enum rmap_compile_rets ret;
dabecd7c 1448
e2c8d6ce
NT
1449 ret = route_map_add_match(index, "rpki", argv[2]->arg,
1450 RMAP_EVENT_MATCH_ADDED);
69337c34
DS
1451 switch (ret) {
1452 case RMAP_RULE_MISSING:
1453 vty_out(vty, "%% BGP Can't find rule.\n");
1454 return CMD_WARNING_CONFIG_FAILED;
1455 case RMAP_COMPILE_ERROR:
1456 vty_out(vty, "%% BGP Argument is malformed.\n");
1457 return CMD_WARNING_CONFIG_FAILED;
1458 case RMAP_COMPILE_SUCCESS:
1459 return CMD_SUCCESS;
1460 break;
dabecd7c 1461 }
69337c34 1462
dabecd7c
MR
1463 return CMD_SUCCESS;
1464}
1465
1466DEFUN (no_match_rpki,
1467 no_match_rpki_cmd,
1468 "no match rpki <valid|invalid|notfound>",
1469 NO_STR
1470 MATCH_STR
1471 RPKI_OUTPUT_STRING
1472 "Valid prefix\n"
1473 "Invalid prefix\n"
1474 "Prefix not found\n")
1475{
1476 VTY_DECLVAR_CONTEXT(route_map_index, index);
cda7187d 1477 enum rmap_compile_rets ret;
dabecd7c 1478
909f3d56 1479 ret = route_map_delete_match(index, "rpki", argv[3]->arg,
1480 RMAP_EVENT_MATCH_DELETED);
69337c34
DS
1481 switch (ret) {
1482 case RMAP_RULE_MISSING:
1483 vty_out(vty, "%% BGP Can't find rule.\n");
1484 return CMD_WARNING_CONFIG_FAILED;
1485 break;
1486 case RMAP_COMPILE_ERROR:
1487 vty_out(vty, "%% BGP Argument is malformed.\n");
dabecd7c 1488 return CMD_WARNING_CONFIG_FAILED;
69337c34
DS
1489 break;
1490 case RMAP_COMPILE_SUCCESS:
1491 return CMD_SUCCESS;
1492 break;
dabecd7c
MR
1493 }
1494
1495 return CMD_SUCCESS;
1496}
1497
dabecd7c
MR
1498static void install_cli_commands(void)
1499{
996c9314 1500 // TODO: make config write work
612c2c15 1501 install_node(&rpki_node);
dabecd7c 1502 install_default(RPKI_NODE);
dabecd7c 1503 install_element(CONFIG_NODE, &rpki_cmd);
9593708d 1504 install_element(ENABLE_NODE, &rpki_cmd);
dabecd7c
MR
1505
1506 install_element(ENABLE_NODE, &bgp_rpki_start_cmd);
1507 install_element(ENABLE_NODE, &bgp_rpki_stop_cmd);
1508
1509 /* Install rpki reset command */
1510 install_element(RPKI_NODE, &rpki_reset_cmd);
1511
1512 /* Install rpki polling period commands */
1513 install_element(RPKI_NODE, &rpki_polling_period_cmd);
1514 install_element(RPKI_NODE, &no_rpki_polling_period_cmd);
1515
1516 /* Install rpki expire interval commands */
1517 install_element(RPKI_NODE, &rpki_expire_interval_cmd);
1518 install_element(RPKI_NODE, &no_rpki_expire_interval_cmd);
1519
1520 /* Install rpki retry interval commands */
1521 install_element(RPKI_NODE, &rpki_retry_interval_cmd);
1522 install_element(RPKI_NODE, &no_rpki_retry_interval_cmd);
1523
1524 /* Install rpki timeout commands */
1525 install_element(RPKI_NODE, &rpki_timeout_cmd);
1526 install_element(RPKI_NODE, &no_rpki_timeout_cmd);
1527
1528 /* Install rpki synchronisation timeout commands */
1529 install_element(RPKI_NODE, &rpki_synchronisation_timeout_cmd);
1530 install_element(RPKI_NODE, &no_rpki_synchronisation_timeout_cmd);
1531
1532 /* Install rpki cache commands */
1533 install_element(RPKI_NODE, &rpki_cache_cmd);
1534 install_element(RPKI_NODE, &no_rpki_cache_cmd);
1535
1536 /* Install show commands */
9593708d 1537 install_element(VIEW_NODE, &show_rpki_prefix_table_cmd);
1538 install_element(VIEW_NODE, &show_rpki_cache_connection_cmd);
1539 install_element(VIEW_NODE, &show_rpki_cache_server_cmd);
1540 install_element(VIEW_NODE, &show_rpki_prefix_cmd);
02334bb2 1541 install_element(VIEW_NODE, &show_rpki_as_number_cmd);
dabecd7c
MR
1542
1543 /* Install debug commands */
1544 install_element(CONFIG_NODE, &debug_rpki_cmd);
1545 install_element(ENABLE_NODE, &debug_rpki_cmd);
1546 install_element(CONFIG_NODE, &no_debug_rpki_cmd);
1547 install_element(ENABLE_NODE, &no_debug_rpki_cmd);
1548
1549 /* Install route match */
1550 route_map_install_match(&route_match_rpki_cmd);
1551 install_element(RMAP_NODE, &match_rpki_cmd);
1552 install_element(RMAP_NODE, &no_match_rpki_cmd);
1553}
1554
1555FRR_MODULE_SETUP(.name = "bgpd_rpki", .version = "0.3.6",
1556 .description = "Enable RPKI support for FRR.",
996c9314 1557 .init = bgp_rpki_module_init)