]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_rpki.c
zebra: fix FPM node reusing VTY_NODE
[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 146static struct cmd_node rpki_node = {
f4b8291f 147 .name = "rpki",
62b346ee 148 .node = RPKI_NODE,
24389580 149 .parent_node = CONFIG_NODE,
62b346ee 150 .prompt = "%s(config-rpki)# ",
612c2c15 151 .config_write = config_write,
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
31a2af32 404 struct list *matches = list_new();
1dacdd8b 405
31a2af32
MR
406 matches->del =
407 (void (*)(void *))bgp_unlock_node;
1dacdd8b 408
31a2af32
MR
409 bgp_table_range_lookup(
410 peer->bgp->rib[afi][safi], prefix,
411 rec.max_len, matches);
1dacdd8b
MR
412
413
31a2af32
MR
414 struct bgp_node *bgp_node;
415 struct listnode *bgp_listnode;
1dacdd8b 416
31a2af32
MR
417 for (ALL_LIST_ELEMENTS_RO(matches, bgp_listnode,
418 bgp_node))
419 revalidate_bgp_node(bgp_node, afi,
420 safi);
1dacdd8b 421
6a154c88 422 list_delete(&matches);
31a2af32 423 }
1dacdd8b
MR
424 }
425 }
426
45206fe2 427 prefix_free(&prefix);
1dacdd8b
MR
428 return 0;
429}
430
431static void revalidate_bgp_node(struct bgp_node *bgp_node, afi_t afi,
432 safi_t safi)
433{
434 struct bgp_adj_in *ain;
435
436 for (ain = bgp_node->adj_in; ain; ain = ain->next) {
437 int ret;
2b964e86
DS
438 struct bgp_path_info *path =
439 bgp_node_get_bgp_path_info(bgp_node);
1dacdd8b
MR
440 mpls_label_t *label = NULL;
441 uint32_t num_labels = 0;
442
9b6d8fcf
DS
443 if (path && path->extra) {
444 label = path->extra->label;
445 num_labels = path->extra->num_labels;
1dacdd8b 446 }
b54892e0
DS
447 ret = bgp_update(ain->peer, bgp_node_get_prefix(bgp_node),
448 ain->addpath_rx_id, ain->attr, afi, safi,
449 ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, label,
450 num_labels, 1, NULL);
1dacdd8b 451
31a2af32 452 if (ret < 0)
1dacdd8b 453 return;
1dacdd8b
MR
454 }
455}
456
457static void revalidate_all_routes(void)
458{
459 struct bgp *bgp;
460 struct listnode *node;
1dacdd8b
MR
461
462 for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp)) {
31a2af32
MR
463 struct peer *peer;
464 struct listnode *peer_listnode;
1dacdd8b 465
31a2af32
MR
466 for (ALL_LIST_ELEMENTS_RO(bgp->peer, peer_listnode, peer)) {
467
468 for (size_t i = 0; i < 2; i++) {
469 safi_t safi;
470 afi_t afi = (i == 0) ? AFI_IP : AFI_IP6;
471
472 for (safi = SAFI_UNICAST; safi < SAFI_MAX;
473 safi++) {
474 if (!peer->bgp->rib[afi][safi])
475 continue;
1dacdd8b 476
31a2af32 477 bgp_soft_reconfig_in(peer, afi, safi);
1dacdd8b
MR
478 }
479 }
480 }
481 }
482}
483
484static void rpki_update_cb_sync_rtr(struct pfx_table *p __attribute__((unused)),
485 const struct pfx_record rec,
486 const bool added __attribute__((unused)))
487{
798df969 488 if (rtr_is_stopping
4ce82676 489 || atomic_load_explicit(&rtr_update_overflow, memory_order_seq_cst))
1dacdd8b
MR
490 return;
491
492 int retval =
493 write(rpki_sync_socket_rtr, &rec, sizeof(struct pfx_record));
4ce82676
MR
494 if (retval == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
495 atomic_store_explicit(&rtr_update_overflow, 1,
496 memory_order_seq_cst);
497
498 else if (retval != sizeof(struct pfx_record))
1dacdd8b
MR
499 RPKI_DEBUG("Could not write to rpki_sync_socket_rtr");
500}
501
502static void rpki_init_sync_socket(void)
503{
504 int fds[2];
4ce82676 505 const char *msg;
1dacdd8b
MR
506
507 RPKI_DEBUG("initializing sync socket");
508 if (socketpair(PF_LOCAL, SOCK_DGRAM, 0, fds) != 0) {
4ce82676
MR
509 msg = "could not open rpki sync socketpair";
510 goto err;
1dacdd8b
MR
511 }
512 rpki_sync_socket_rtr = fds[0];
513 rpki_sync_socket_bgpd = fds[1];
4ce82676
MR
514
515 if (set_nonblocking(rpki_sync_socket_rtr) != 0) {
516 msg = "could not set rpki_sync_socket_rtr to non blocking";
517 goto err;
518 }
519
520 if (set_nonblocking(rpki_sync_socket_bgpd) != 0) {
521 msg = "could not set rpki_sync_socket_bgpd to non blocking";
522 goto err;
523 }
524
525
1dacdd8b
MR
526 thread_add_read(bm->master, bgpd_sync_callback, NULL,
527 rpki_sync_socket_bgpd, NULL);
4ce82676
MR
528
529 return;
530
531err:
532 zlog_err("RPKI: %s", msg);
533 abort();
534
1dacdd8b
MR
535}
536
dabecd7c
MR
537static int bgp_rpki_init(struct thread_master *master)
538{
539 rpki_debug = 0;
540 rtr_is_running = 0;
1dacdd8b 541 rtr_is_stopping = 0;
dabecd7c
MR
542
543 cache_list = list_new();
996c9314 544 cache_list->del = (void (*)(void *)) & free_cache;
dabecd7c
MR
545
546 polling_period = POLLING_PERIOD_DEFAULT;
547 expire_interval = EXPIRE_INTERVAL_DEFAULT;
548 retry_interval = RETRY_INTERVAL_DEFAULT;
dabecd7c 549 install_cli_commands();
1dacdd8b 550 rpki_init_sync_socket();
dabecd7c
MR
551 return 0;
552}
553
554static int bgp_rpki_fini(void)
555{
556 stop();
6a154c88 557 list_delete(&cache_list);
dabecd7c 558
1dacdd8b
MR
559 close(rpki_sync_socket_rtr);
560 close(rpki_sync_socket_bgpd);
561
dabecd7c
MR
562 return 0;
563}
564
565static int bgp_rpki_module_init(void)
566{
996c9314 567 lrtr_set_alloc_functions(malloc_wrapper, realloc_wrapper, free_wrapper);
dabecd7c
MR
568
569 hook_register(frr_late_init, bgp_rpki_init);
570 hook_register(frr_early_fini, &bgp_rpki_fini);
571
572 return 0;
573}
574
575static int start(void)
576{
dabecd7c
MR
577 int ret;
578
1dacdd8b 579 rtr_is_stopping = 0;
4ce82676 580 rtr_update_overflow = 0;
1dacdd8b 581
dabecd7c
MR
582 if (list_isempty(cache_list)) {
583 RPKI_DEBUG(
584 "No caches were found in config. Prefix validation is off.");
585 return ERROR;
586 }
587 RPKI_DEBUG("Init rtr_mgr.");
588 int groups_len = listcount(cache_list);
589 struct rtr_mgr_group *groups = get_groups();
590
1dacdd8b 591 RPKI_DEBUG("Polling period: %d", polling_period);
dabecd7c 592 ret = rtr_mgr_init(&rtr_config, groups, groups_len, polling_period,
1dacdd8b
MR
593 expire_interval, retry_interval,
594 rpki_update_cb_sync_rtr, NULL, NULL, NULL);
dabecd7c
MR
595 if (ret == RTR_ERROR) {
596 RPKI_DEBUG("Init rtr_mgr failed.");
597 return ERROR;
598 }
599
600 RPKI_DEBUG("Starting rtr_mgr.");
601 ret = rtr_mgr_start(rtr_config);
602 if (ret == RTR_ERROR) {
603 RPKI_DEBUG("Starting rtr_mgr failed.");
604 rtr_mgr_free(rtr_config);
605 return ERROR;
606 }
607 rtr_is_running = 1;
dabecd7c
MR
608
609 XFREE(MTYPE_BGP_RPKI_CACHE_GROUP, groups);
610
611 return SUCCESS;
612}
613
614static void stop(void)
615{
1dacdd8b 616 rtr_is_stopping = 1;
dabecd7c
MR
617 if (rtr_is_running) {
618 rtr_mgr_stop(rtr_config);
619 rtr_mgr_free(rtr_config);
620 rtr_is_running = 0;
621 }
622}
623
624static int reset(bool force)
625{
626 if (rtr_is_running && !force)
627 return SUCCESS;
628
629 RPKI_DEBUG("Resetting RPKI Session");
630 stop();
631 return start();
632}
633
634static struct rtr_mgr_group *get_connected_group(void)
635{
18b91526 636 if (!cache_list || list_isempty(cache_list))
dabecd7c
MR
637 return NULL;
638
639 return rtr_mgr_get_first_group(rtr_config);
640}
641
02334bb2
DA
642static void print_prefix_table_by_asn(struct vty *vty, as_t as)
643{
644 unsigned int number_of_ipv4_prefixes = 0;
645 unsigned int number_of_ipv6_prefixes = 0;
646 struct rtr_mgr_group *group = get_connected_group();
647 struct rpki_for_each_record_arg arg;
648
649 arg.vty = vty;
650 arg.as = as;
651
652 if (!group) {
653 vty_out(vty, "Cannot find a connected group.\n");
654 return;
655 }
656
657 struct pfx_table *pfx_table = group->sockets[0]->pfx_table;
658
659 vty_out(vty, "RPKI/RTR prefix table\n");
660 vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
661
662 arg.prefix_amount = &number_of_ipv4_prefixes;
663 pfx_table_for_each_ipv4_record(pfx_table, print_record_by_asn, &arg);
664
665 arg.prefix_amount = &number_of_ipv6_prefixes;
666 pfx_table_for_each_ipv6_record(pfx_table, print_record_by_asn, &arg);
667
668 vty_out(vty, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes);
669 vty_out(vty, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes);
670}
671
dabecd7c
MR
672static void print_prefix_table(struct vty *vty)
673{
674 struct rpki_for_each_record_arg arg;
675
676 unsigned int number_of_ipv4_prefixes = 0;
677 unsigned int number_of_ipv6_prefixes = 0;
678 struct rtr_mgr_group *group = get_connected_group();
679
680 arg.vty = vty;
681
682 if (!group)
683 return;
684
685 struct pfx_table *pfx_table = group->sockets[0]->pfx_table;
686
687 vty_out(vty, "RPKI/RTR prefix table\n");
688 vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
689
690 arg.prefix_amount = &number_of_ipv4_prefixes;
5d799192 691 pfx_table_for_each_ipv4_record(pfx_table, print_record_cb, &arg);
dabecd7c
MR
692
693 arg.prefix_amount = &number_of_ipv6_prefixes;
5d799192 694 pfx_table_for_each_ipv6_record(pfx_table, print_record_cb, &arg);
dabecd7c
MR
695
696 vty_out(vty, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes);
697 vty_out(vty, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes);
698}
699
700static int rpki_validate_prefix(struct peer *peer, struct attr *attr,
898c4e66 701 const struct prefix *prefix)
dabecd7c
MR
702{
703 struct assegment *as_segment;
704 as_t as_number = 0;
705 struct lrtr_ip_addr ip_addr_prefix;
706 enum pfxv_state result;
707 char buf[BUFSIZ];
708 const char *prefix_string;
709
710 if (!is_synchronized())
711 return 0;
712
713 // No aspath means route comes from iBGP
714 if (!attr->aspath || !attr->aspath->segments) {
715 // Set own as number
716 as_number = peer->bgp->as;
717 } else {
718 as_segment = attr->aspath->segments;
719 // Find last AsSegment
720 while (as_segment->next)
721 as_segment = as_segment->next;
722
723 if (as_segment->type == AS_SEQUENCE) {
724 // Get rightmost asn
725 as_number = as_segment->as[as_segment->length - 1];
996c9314
LB
726 } else if (as_segment->type == AS_CONFED_SEQUENCE
727 || as_segment->type == AS_CONFED_SET) {
dabecd7c
MR
728 // Set own as number
729 as_number = peer->bgp->as;
730 } else {
731 // RFC says: "Take distinguished value NONE as asn"
732 // which means state is unknown
733 return RPKI_NOTFOUND;
734 }
735 }
736
737 // Get the prefix in requested format
738 switch (prefix->family) {
739 case AF_INET:
740 ip_addr_prefix.ver = LRTR_IPV4;
741 ip_addr_prefix.u.addr4.addr = ntohl(prefix->u.prefix4.s_addr);
742 break;
743
dabecd7c
MR
744 case AF_INET6:
745 ip_addr_prefix.ver = LRTR_IPV6;
746 ipv6_addr_to_host_byte_order(prefix->u.prefix6.s6_addr32,
747 ip_addr_prefix.u.addr6.addr);
748 break;
dabecd7c
MR
749
750 default:
751 return 0;
752 }
753
754 // Do the actual validation
755 rtr_mgr_validate(rtr_config, as_number, &ip_addr_prefix,
756 prefix->prefixlen, &result);
757
758 // Print Debug output
7c3f0950 759 prefix_string = prefix2str(prefix, buf, sizeof(buf));
dabecd7c
MR
760 switch (result) {
761 case BGP_PFXV_STATE_VALID:
762 RPKI_DEBUG(
7c3f0950
DS
763 "Validating Prefix %s from asn %u Result: VALID",
764 prefix_string, as_number);
dabecd7c
MR
765 return RPKI_VALID;
766 case BGP_PFXV_STATE_NOT_FOUND:
767 RPKI_DEBUG(
7c3f0950
DS
768 "Validating Prefix %s from asn %u Result: NOT FOUND",
769 prefix_string, as_number);
dabecd7c
MR
770 return RPKI_NOTFOUND;
771 case BGP_PFXV_STATE_INVALID:
772 RPKI_DEBUG(
7c3f0950
DS
773 "Validating Prefix %s from asn %u Result: INVALID",
774 prefix_string, as_number);
dabecd7c
MR
775 return RPKI_INVALID;
776 default:
777 RPKI_DEBUG(
7c3f0950
DS
778 "Validating Prefix %s from asn %u Result: CANNOT VALIDATE",
779 prefix_string, as_number);
dabecd7c
MR
780 break;
781 }
782 return 0;
783}
784
785static int add_cache(struct cache *cache)
786{
787 uint8_t preference = cache->preference;
788 struct rtr_mgr_group group;
789
790 group.preference = preference;
791 group.sockets_len = 1;
792 group.sockets = &cache->rtr_socket;
793
92110aab
MR
794 if (rtr_is_running) {
795 init_tr_socket(cache);
796
797 if (rtr_mgr_add_group(rtr_config, &group) != RTR_SUCCESS) {
798 free_tr_socket(cache);
799 return ERROR;
800 }
dabecd7c
MR
801 }
802
6893064b
MR
803 listnode_add(cache_list, cache);
804
dabecd7c
MR
805 return SUCCESS;
806}
807
996c9314 808static int add_tcp_cache(const char *host, const char *port,
dabecd7c
MR
809 const uint8_t preference)
810{
811 struct rtr_socket *rtr_socket;
812 struct tr_tcp_config *tcp_config =
813 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_tcp_config));
814 struct tr_socket *tr_socket =
815 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
816 struct cache *cache =
817 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
818
819 tcp_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
820 tcp_config->port = XSTRDUP(MTYPE_BGP_RPKI_CACHE, port);
821 tcp_config->bindaddr = NULL;
822
823 rtr_socket = create_rtr_socket(tr_socket);
824
825 cache->type = TCP;
826 cache->tr_socket = tr_socket;
827 cache->tr_config.tcp_config = tcp_config;
828 cache->rtr_socket = rtr_socket;
829 cache->preference = preference;
830
6893064b
MR
831 int ret = add_cache(cache);
832 if (ret != SUCCESS) {
833 free_cache(cache);
834 }
835
836 return ret;
dabecd7c
MR
837}
838
839#if defined(FOUND_SSH)
996c9314
LB
840static int add_ssh_cache(const char *host, const unsigned int port,
841 const char *username, const char *client_privkey_path,
dabecd7c
MR
842 const char *client_pubkey_path,
843 const char *server_pubkey_path,
844 const uint8_t preference)
845{
846 struct tr_ssh_config *ssh_config =
847 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_ssh_config));
848 struct cache *cache =
849 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
850 struct tr_socket *tr_socket =
851 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
852 struct rtr_socket *rtr_socket;
853
854 ssh_config->port = port;
855 ssh_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
856 ssh_config->bindaddr = NULL;
857
858 ssh_config->username = XSTRDUP(MTYPE_BGP_RPKI_CACHE, username);
996c9314
LB
859 ssh_config->client_privkey_path =
860 XSTRDUP(MTYPE_BGP_RPKI_CACHE, client_privkey_path);
dabecd7c
MR
861 ssh_config->server_hostkey_path =
862 XSTRDUP(MTYPE_BGP_RPKI_CACHE, server_pubkey_path);
863
864 rtr_socket = create_rtr_socket(tr_socket);
865
866 cache->type = SSH;
867 cache->tr_socket = tr_socket;
868 cache->tr_config.ssh_config = ssh_config;
869 cache->rtr_socket = rtr_socket;
870 cache->preference = preference;
871
6893064b
MR
872 int ret = add_cache(cache);
873 if (ret != SUCCESS) {
874 free_cache(cache);
875 }
876
877 return ret;
dabecd7c
MR
878}
879#endif
880
881static void free_cache(struct cache *cache)
882{
883 if (cache->type == TCP) {
996c9314
LB
884 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->host);
885 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->port);
dabecd7c
MR
886 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config);
887 }
888#if defined(FOUND_SSH)
889 else {
996c9314 890 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config->host);
dabecd7c
MR
891 XFREE(MTYPE_BGP_RPKI_CACHE,
892 cache->tr_config.ssh_config->username);
893 XFREE(MTYPE_BGP_RPKI_CACHE,
894 cache->tr_config.ssh_config->client_privkey_path);
895 XFREE(MTYPE_BGP_RPKI_CACHE,
896 cache->tr_config.ssh_config->server_hostkey_path);
897 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config);
898 }
899#endif
900 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_socket);
901 XFREE(MTYPE_BGP_RPKI_CACHE, cache->rtr_socket);
902 XFREE(MTYPE_BGP_RPKI_CACHE, cache);
903}
904
905static int config_write(struct vty *vty)
906{
907 struct listnode *cache_node;
908 struct cache *cache;
909
910 if (listcount(cache_list)) {
911 if (rpki_debug)
912 vty_out(vty, "debug rpki\n");
913
914 vty_out(vty, "!\n");
915 vty_out(vty, "rpki\n");
916 vty_out(vty, " rpki polling_period %d\n", polling_period);
dabecd7c
MR
917 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
918 switch (cache->type) {
919 struct tr_tcp_config *tcp_config;
acd4a9f4 920#if defined(FOUND_SSH)
dabecd7c 921 struct tr_ssh_config *ssh_config;
acd4a9f4 922#endif
dabecd7c
MR
923 case TCP:
924 tcp_config = cache->tr_config.tcp_config;
996c9314
LB
925 vty_out(vty, " rpki cache %s %s ",
926 tcp_config->host, tcp_config->port);
dabecd7c
MR
927 break;
928#if defined(FOUND_SSH)
929 case SSH:
930 ssh_config = cache->tr_config.ssh_config;
996c9314
LB
931 vty_out(vty, " rpki cache %s %u %s %s %s ",
932 ssh_config->host, ssh_config->port,
dabecd7c
MR
933 ssh_config->username,
934 ssh_config->client_privkey_path,
996c9314 935 ssh_config->server_hostkey_path != NULL
dabecd7c
MR
936 ? ssh_config
937 ->server_hostkey_path
938 : " ");
939 break;
940#endif
941 default:
942 break;
943 }
944
945 vty_out(vty, "preference %hhu\n", cache->preference);
946 }
947 vty_out(vty, " exit\n");
948 return 1;
949 } else {
950 return 0;
951 }
952}
953
954DEFUN_NOSH (rpki,
955 rpki_cmd,
956 "rpki",
957 "Enable rpki and enter rpki configuration mode\n")
958{
959 vty->node = RPKI_NODE;
960 return CMD_SUCCESS;
961}
962
963DEFUN (bgp_rpki_start,
964 bgp_rpki_start_cmd,
965 "rpki start",
966 RPKI_OUTPUT_STRING
967 "start rpki support\n")
968{
969 if (listcount(cache_list) == 0)
996c9314
LB
970 vty_out(vty,
971 "Could not start rpki because no caches are configured\n");
dabecd7c
MR
972
973 if (!is_running()) {
974 if (start() == ERROR) {
975 RPKI_DEBUG("RPKI failed to start");
976 return CMD_WARNING;
977 }
978 }
979 return CMD_SUCCESS;
980}
981
982DEFUN (bgp_rpki_stop,
983 bgp_rpki_stop_cmd,
984 "rpki stop",
985 RPKI_OUTPUT_STRING
986 "start rpki support\n")
987{
988 if (is_running())
989 stop();
990
991 return CMD_SUCCESS;
992}
993
994DEFPY (rpki_polling_period,
995 rpki_polling_period_cmd,
996 "rpki polling_period (1-86400)$pp",
997 RPKI_OUTPUT_STRING
998 "Set polling period\n"
999 "Polling period value\n")
1000{
1001 polling_period = pp;
1002 return CMD_SUCCESS;
1003}
1004
1005DEFUN (no_rpki_polling_period,
1006 no_rpki_polling_period_cmd,
1007 "no rpki polling_period",
1008 NO_STR
1009 RPKI_OUTPUT_STRING
1010 "Set polling period back to default\n")
1011{
1012 polling_period = POLLING_PERIOD_DEFAULT;
1013 return CMD_SUCCESS;
1014}
1015
1016DEFPY (rpki_expire_interval,
1017 rpki_expire_interval_cmd,
1018 "rpki expire_interval (600-172800)$tmp",
1019 RPKI_OUTPUT_STRING
1020 "Set expire interval\n"
1021 "Expire interval value\n")
1022{
6f577f58 1023 if ((unsigned int)tmp >= polling_period) {
dabecd7c
MR
1024 expire_interval = tmp;
1025 return CMD_SUCCESS;
1026 }
1027
1028 vty_out(vty, "%% Expiry interval must be polling period or larger\n");
1029 return CMD_WARNING_CONFIG_FAILED;
1030}
1031
1032DEFUN (no_rpki_expire_interval,
1033 no_rpki_expire_interval_cmd,
1034 "no rpki expire_interval",
1035 NO_STR
1036 RPKI_OUTPUT_STRING
1037 "Set expire interval back to default\n")
1038{
1039 expire_interval = polling_period * 2;
1040 return CMD_SUCCESS;
1041}
1042
1043DEFPY (rpki_retry_interval,
1044 rpki_retry_interval_cmd,
1045 "rpki retry_interval (1-7200)$tmp",
1046 RPKI_OUTPUT_STRING
1047 "Set retry interval\n"
1048 "retry interval value\n")
1049{
1050 retry_interval = tmp;
1051 return CMD_SUCCESS;
1052}
1053
1054DEFUN (no_rpki_retry_interval,
1055 no_rpki_retry_interval_cmd,
1056 "no rpki retry_interval",
1057 NO_STR
1058 RPKI_OUTPUT_STRING
1059 "Set retry interval back to default\n")
1060{
1061 retry_interval = RETRY_INTERVAL_DEFAULT;
1062 return CMD_SUCCESS;
1063}
1064
dd783f3e
MR
1065#if (CONFDATE > 20200901)
1066CPP_NOTICE("bgpd: time to remove rpki timeout")
1067CPP_NOTICE("bgpd: this includes rpki_timeout and rpki_synchronisation_timeout")
1068#endif
1069
1070DEFPY_HIDDEN (rpki_timeout,
dabecd7c
MR
1071 rpki_timeout_cmd,
1072 "rpki timeout (1-4294967295)$to_arg",
1073 RPKI_OUTPUT_STRING
1074 "Set timeout\n"
1075 "Timeout value\n")
1076{
dd783f3e
MR
1077 vty_out(vty,
1078 "This config option is deprecated, and is scheduled for removal.\n");
1079 vty_out(vty,
1080 "This functionality has also already been removed because it caused bugs and was pointless\n");
dabecd7c
MR
1081 return CMD_SUCCESS;
1082}
1083
dd783f3e 1084DEFUN_HIDDEN (no_rpki_timeout,
dabecd7c
MR
1085 no_rpki_timeout_cmd,
1086 "no rpki timeout",
1087 NO_STR
1088 RPKI_OUTPUT_STRING
1089 "Set timeout back to default\n")
1090{
dd783f3e
MR
1091 vty_out(vty,
1092 "This config option is deprecated, and is scheduled for removal.\n");
1093 vty_out(vty,
1094 "This functionality has also already been removed because it caused bugs and was pointless\n");
dabecd7c
MR
1095 return CMD_SUCCESS;
1096}
1097
dd783f3e 1098DEFPY_HIDDEN (rpki_synchronisation_timeout,
dabecd7c
MR
1099 rpki_synchronisation_timeout_cmd,
1100 "rpki initial-synchronisation-timeout (1-4294967295)$ito_arg",
1101 RPKI_OUTPUT_STRING
1102 "Set a timeout for the initial synchronisation of prefix validation data\n"
1103 "Timeout value\n")
1104{
dd783f3e
MR
1105 vty_out(vty,
1106 "This config option is deprecated, and is scheduled for removal.\n");
1107 vty_out(vty,
1108 "This functionality has also already been removed because it caused bugs and was pointless\n");
dabecd7c
MR
1109 return CMD_SUCCESS;
1110}
1111
dd783f3e 1112DEFUN_HIDDEN (no_rpki_synchronisation_timeout,
dabecd7c
MR
1113 no_rpki_synchronisation_timeout_cmd,
1114 "no rpki initial-synchronisation-timeout",
1115 NO_STR
1116 RPKI_OUTPUT_STRING
1117 "Set the initial synchronisation timeout back to default (30 sec.)\n")
1118{
dd783f3e
MR
1119 vty_out(vty,
1120 "This config option is deprecated, and is scheduled for removal.\n");
1121 vty_out(vty,
1122 "This functionality has also already been removed because it caused bugs and was pointless\n");
dabecd7c
MR
1123 return CMD_SUCCESS;
1124}
1125
1126DEFPY (rpki_cache,
1127 rpki_cache_cmd,
1128 "rpki cache <A.B.C.D|WORD>"
1129 "<TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY SSH_PUBKEY [SERVER_PUBKEY]> "
1130 "preference (1-255)",
1131 RPKI_OUTPUT_STRING
1132 "Install a cache server to current group\n"
1133 "IP address of cache server\n Hostname of cache server\n"
1134 "TCP port number\n"
1135 "SSH port number\n"
1136 "SSH user name\n"
1137 "Path to own SSH private key\n"
1138 "Path to own SSH public key\n"
1139 "Path to Public key of cache server\n"
1140 "Preference of the cache server\n"
1141 "Preference value\n")
1142{
3f54c705 1143 int return_value;
a2ed7b2b
MR
1144 struct listnode *cache_node;
1145 struct cache *current_cache;
1146
1147 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, current_cache)) {
1148 if (current_cache->preference == preference) {
1149 vty_out(vty,
1150 "Cache with preference %ld is already configured\n",
1151 preference);
1152 return CMD_WARNING;
1153 }
1154 }
1155
dabecd7c
MR
1156
1157 // use ssh connection
1158 if (ssh_uname) {
1159#if defined(FOUND_SSH)
996c9314
LB
1160 return_value =
1161 add_ssh_cache(cache, sshport, ssh_uname, ssh_privkey,
1162 ssh_pubkey, server_pubkey, preference);
dabecd7c 1163#else
3f54c705 1164 return_value = SUCCESS;
dabecd7c
MR
1165 vty_out(vty,
1166 "ssh sockets are not supported. "
1167 "Please recompile rtrlib and frr with ssh support. "
0e43d16b 1168 "If you want to use it\n");
dabecd7c
MR
1169#endif
1170 } else { // use tcp connection
1171 return_value = add_tcp_cache(cache, tcpport, preference);
1172 }
1173
1174 if (return_value == ERROR) {
1175 vty_out(vty, "Could not create new rpki cache\n");
1176 return CMD_WARNING;
1177 }
1178
1179 return CMD_SUCCESS;
1180}
1181
1182DEFPY (no_rpki_cache,
1183 no_rpki_cache_cmd,
1184 "no rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport> preference (1-255)$preference",
1185 NO_STR
1186 RPKI_OUTPUT_STRING
1187 "Remove a cache server\n"
1188 "IP address of cache server\n Hostname of cache server\n"
1189 "TCP port number\n"
1190 "SSH port number\n"
1191 "Preference of the cache server\n"
1192 "Preference value\n")
1193{
1194 struct cache *cache_p = find_cache(preference);
1195
222487fe 1196 if (!cache_p) {
dabecd7c
MR
1197 vty_out(vty, "Could not find cache %ld\n", preference);
1198 return CMD_WARNING;
1199 }
1200
8add1719
MR
1201 if (rtr_is_running && listcount(cache_list) == 1) {
1202 stop();
1203 } else if (rtr_is_running) {
dabecd7c
MR
1204 if (rtr_mgr_remove_group(rtr_config, preference) == RTR_ERROR) {
1205 vty_out(vty, "Could not remove cache %ld", preference);
dabecd7c
MR
1206
1207 vty_out(vty, "\n");
1208 return CMD_WARNING;
1209 }
1210 }
1211
1212 listnode_delete(cache_list, cache_p);
1213 free_cache(cache_p);
1214
1215 return CMD_SUCCESS;
1216}
1217
1218DEFUN (show_rpki_prefix_table,
1219 show_rpki_prefix_table_cmd,
1220 "show rpki prefix-table",
1221 SHOW_STR
1222 RPKI_OUTPUT_STRING
08f9cfb8 1223 "Show validated prefixes which were received from RPKI Cache\n")
dabecd7c
MR
1224{
1225 struct listnode *cache_node;
1226 struct cache *cache;
1227
1228 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
996c9314 1229 vty_out(vty, "host: %s port: %s\n",
dabecd7c
MR
1230 cache->tr_config.tcp_config->host,
1231 cache->tr_config.tcp_config->port);
1232 }
1233 if (is_synchronized())
1234 print_prefix_table(vty);
1235 else
1236 vty_out(vty, "No connection to RPKI cache server.\n");
1237
1238 return CMD_SUCCESS;
1239}
1240
02334bb2
DA
1241DEFPY(show_rpki_as_number, show_rpki_as_number_cmd,
1242 "show rpki as-number (1-4294967295)$by_asn",
1243 SHOW_STR RPKI_OUTPUT_STRING
1244 "Lookup by ASN in prefix table\n"
1245 "AS Number\n")
1246{
1247 if (!is_synchronized()) {
1248 vty_out(vty, "No Connection to RPKI cache server.\n");
1249 return CMD_WARNING;
1250 }
1251
1252 print_prefix_table_by_asn(vty, by_asn);
1253 return CMD_SUCCESS;
1254}
1255
5d799192
MR
1256DEFPY (show_rpki_prefix,
1257 show_rpki_prefix_cmd,
1258 "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn]",
1259 SHOW_STR
1260 RPKI_OUTPUT_STRING
1261 "Lookup IP prefix and optionally ASN in prefix table\n"
1262 "IPv4 prefix\n"
1263 "IPv6 prefix\n"
1264 "AS Number\n")
1265{
1266
1267 if (!is_synchronized()) {
f79f7a7b 1268 vty_out(vty, "No Connection to RPKI cache server.\n");
5d799192
MR
1269 return CMD_WARNING;
1270 }
1271
1272 struct lrtr_ip_addr addr;
1273 char addr_str[INET6_ADDRSTRLEN];
1274 size_t addr_len = strchr(prefix_str, '/') - prefix_str;
1275
1276 memset(addr_str, 0, sizeof(addr_str));
1277 memcpy(addr_str, prefix_str, addr_len);
1278
1279 if (lrtr_ip_str_to_addr(addr_str, &addr) != 0) {
1280 vty_out(vty, "Invalid IP prefix\n");
1281 return CMD_WARNING;
1282 }
1283
1284 struct pfx_record *matches = NULL;
1285 unsigned int match_count = 0;
1286 enum pfxv_state result;
1287
1288 if (pfx_table_validate_r(rtr_config->pfx_table, &matches, &match_count,
1289 asn, &addr, prefix->prefixlen, &result)
1290 != PFX_SUCCESS) {
1291 vty_out(vty, "Prefix lookup failed");
1292 return CMD_WARNING;
1293 }
1294
1295 vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
1296 for (size_t i = 0; i < match_count; ++i) {
1297 const struct pfx_record *record = &matches[i];
1298
1299 if (record->max_len >= prefix->prefixlen
c17140fd
DS
1300 && ((asn != 0 && (uint32_t)asn == record->asn)
1301 || asn == 0)) {
5d799192
MR
1302 print_record(&matches[i], vty);
1303 }
1304 }
1305
1306 return CMD_SUCCESS;
1307}
1308
dabecd7c
MR
1309DEFUN (show_rpki_cache_server,
1310 show_rpki_cache_server_cmd,
1311 "show rpki cache-server",
1312 SHOW_STR
1313 RPKI_OUTPUT_STRING
08f9cfb8 1314 "SHOW configured cache server\n")
dabecd7c
MR
1315{
1316 struct listnode *cache_node;
1317 struct cache *cache;
1318
1319 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
745ae9c0
MR
1320 if (cache->type == TCP) {
1321 vty_out(vty, "host: %s port: %s\n",
1322 cache->tr_config.tcp_config->host,
1323 cache->tr_config.tcp_config->port);
1324
fef6fafa 1325#if defined(FOUND_SSH)
745ae9c0
MR
1326 } else if (cache->type == SSH) {
1327 vty_out(vty,
1328 "host: %s port: %d username: %s "
1329 "server_hostkey_path: %s client_privkey_path: %s\n",
1330 cache->tr_config.ssh_config->host,
1331 cache->tr_config.ssh_config->port,
1332 cache->tr_config.ssh_config->username,
1333 cache->tr_config.ssh_config
1334 ->server_hostkey_path,
1335 cache->tr_config.ssh_config
1336 ->client_privkey_path);
fef6fafa 1337#endif
745ae9c0 1338 }
dabecd7c
MR
1339 }
1340
1341 return CMD_SUCCESS;
1342}
1343
1344DEFUN (show_rpki_cache_connection,
1345 show_rpki_cache_connection_cmd,
1346 "show rpki cache-connection",
1347 SHOW_STR
1348 RPKI_OUTPUT_STRING
08f9cfb8 1349 "Show to which RPKI Cache Servers we have a connection\n")
dabecd7c
MR
1350{
1351 if (is_synchronized()) {
1352 struct listnode *cache_node;
1353 struct cache *cache;
1354 struct rtr_mgr_group *group = get_connected_group();
1355
1356 if (!group) {
1357 vty_out(vty, "Cannot find a connected group.\n");
1358 return CMD_SUCCESS;
1359 }
1360 vty_out(vty, "Connected to group %d\n", group->preference);
996c9314 1361 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
dabecd7c
MR
1362 if (cache->preference == group->preference) {
1363 struct tr_tcp_config *tcp_config;
acd4a9f4 1364#if defined(FOUND_SSH)
dabecd7c 1365 struct tr_ssh_config *ssh_config;
acd4a9f4 1366#endif
dabecd7c
MR
1367
1368 switch (cache->type) {
1369 case TCP:
1370 tcp_config =
996c9314 1371 cache->tr_config.tcp_config;
dabecd7c
MR
1372 vty_out(vty,
1373 "rpki tcp cache %s %s pref %hhu\n",
1374 tcp_config->host,
1375 tcp_config->port,
1376 cache->preference);
1377 break;
1378
1379#if defined(FOUND_SSH)
1380 case SSH:
1381 ssh_config =
996c9314 1382 cache->tr_config.ssh_config;
dabecd7c
MR
1383 vty_out(vty,
1384 "rpki ssh cache %s %u pref %hhu\n",
1385 ssh_config->host,
1386 ssh_config->port,
1387 cache->preference);
1388 break;
1389#endif
1390
1391 default:
1392 break;
1393 }
1394 }
1395 }
1396 } else {
1397 vty_out(vty, "No connection to RPKI cache server.\n");
1398 }
1399
1400 return CMD_SUCCESS;
1401}
1402
1403DEFUN_NOSH (rpki_exit,
1404 rpki_exit_cmd,
1405 "exit",
08f9cfb8 1406 "Exit rpki configuration and restart rpki session\n")
dabecd7c 1407{
61a484a9 1408 reset(false);
dabecd7c
MR
1409
1410 vty->node = CONFIG_NODE;
61a484a9 1411 return CMD_SUCCESS;
dabecd7c
MR
1412}
1413
1414DEFUN_NOSH (rpki_quit,
1415 rpki_quit_cmd,
1416 "quit",
08f9cfb8 1417 "Exit rpki configuration mode\n")
dabecd7c
MR
1418{
1419 return rpki_exit(self, vty, argc, argv);
1420}
1421
1422DEFUN_NOSH (rpki_end,
1423 rpki_end_cmd,
1424 "end",
08f9cfb8 1425 "End rpki configuration, restart rpki session and change to enable mode.\n")
dabecd7c
MR
1426{
1427 int ret = reset(false);
1428
f344c66e 1429 vty_config_exit(vty);
dabecd7c
MR
1430 vty->node = ENABLE_NODE;
1431 return ret == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1432}
1433
1434DEFUN (rpki_reset,
1435 rpki_reset_cmd,
1436 "rpki reset",
1437 RPKI_OUTPUT_STRING
1438 "reset rpki\n")
1439{
1440 return reset(true) == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1441}
1442
1443DEFUN (debug_rpki,
1444 debug_rpki_cmd,
1445 "debug rpki",
1446 DEBUG_STR
08f9cfb8 1447 "Enable debugging for rpki\n")
dabecd7c
MR
1448{
1449 rpki_debug = 1;
1450 return CMD_SUCCESS;
1451}
1452
1453DEFUN (no_debug_rpki,
1454 no_debug_rpki_cmd,
1455 "no debug rpki",
1456 NO_STR
1457 DEBUG_STR
08f9cfb8 1458 "Disable debugging for rpki\n")
dabecd7c
MR
1459{
1460 rpki_debug = 0;
1461 return CMD_SUCCESS;
1462}
1463
1464DEFUN (match_rpki,
1465 match_rpki_cmd,
1466 "match rpki <valid|invalid|notfound>",
1467 MATCH_STR
1468 RPKI_OUTPUT_STRING
1469 "Valid prefix\n"
1470 "Invalid prefix\n"
1471 "Prefix not found\n")
1472{
1473 VTY_DECLVAR_CONTEXT(route_map_index, index);
cda7187d 1474 enum rmap_compile_rets ret;
dabecd7c 1475
e2c8d6ce
NT
1476 ret = route_map_add_match(index, "rpki", argv[2]->arg,
1477 RMAP_EVENT_MATCH_ADDED);
69337c34
DS
1478 switch (ret) {
1479 case RMAP_RULE_MISSING:
1480 vty_out(vty, "%% BGP Can't find rule.\n");
1481 return CMD_WARNING_CONFIG_FAILED;
1482 case RMAP_COMPILE_ERROR:
1483 vty_out(vty, "%% BGP Argument is malformed.\n");
1484 return CMD_WARNING_CONFIG_FAILED;
1485 case RMAP_COMPILE_SUCCESS:
1486 return CMD_SUCCESS;
1487 break;
dabecd7c 1488 }
69337c34 1489
dabecd7c
MR
1490 return CMD_SUCCESS;
1491}
1492
1493DEFUN (no_match_rpki,
1494 no_match_rpki_cmd,
1495 "no match rpki <valid|invalid|notfound>",
1496 NO_STR
1497 MATCH_STR
1498 RPKI_OUTPUT_STRING
1499 "Valid prefix\n"
1500 "Invalid prefix\n"
1501 "Prefix not found\n")
1502{
1503 VTY_DECLVAR_CONTEXT(route_map_index, index);
cda7187d 1504 enum rmap_compile_rets ret;
dabecd7c 1505
909f3d56 1506 ret = route_map_delete_match(index, "rpki", argv[3]->arg,
1507 RMAP_EVENT_MATCH_DELETED);
69337c34
DS
1508 switch (ret) {
1509 case RMAP_RULE_MISSING:
1510 vty_out(vty, "%% BGP Can't find rule.\n");
1511 return CMD_WARNING_CONFIG_FAILED;
1512 break;
1513 case RMAP_COMPILE_ERROR:
1514 vty_out(vty, "%% BGP Argument is malformed.\n");
dabecd7c 1515 return CMD_WARNING_CONFIG_FAILED;
69337c34
DS
1516 break;
1517 case RMAP_COMPILE_SUCCESS:
1518 return CMD_SUCCESS;
1519 break;
dabecd7c
MR
1520 }
1521
1522 return CMD_SUCCESS;
1523}
1524
1525static void overwrite_exit_commands(void)
1526{
1527 unsigned int i;
1528 vector cmd_vector = rpki_node.cmd_vector;
1529
1530 for (i = 0; i < cmd_vector->active; ++i) {
1531 struct cmd_element *cmd = vector_lookup(cmd_vector, i);
1532
996c9314
LB
1533 if (strcmp(cmd->string, "exit") == 0
1534 || strcmp(cmd->string, "quit") == 0
1535 || strcmp(cmd->string, "end") == 0) {
dabecd7c
MR
1536 uninstall_element(RPKI_NODE, cmd);
1537 }
1538 }
1539
1540 install_element(RPKI_NODE, &rpki_exit_cmd);
1541 install_element(RPKI_NODE, &rpki_quit_cmd);
1542 install_element(RPKI_NODE, &rpki_end_cmd);
1543}
1544
1545static void install_cli_commands(void)
1546{
996c9314 1547 // TODO: make config write work
612c2c15 1548 install_node(&rpki_node);
dabecd7c
MR
1549 install_default(RPKI_NODE);
1550 overwrite_exit_commands();
1551 install_element(CONFIG_NODE, &rpki_cmd);
9593708d 1552 install_element(ENABLE_NODE, &rpki_cmd);
dabecd7c
MR
1553
1554 install_element(ENABLE_NODE, &bgp_rpki_start_cmd);
1555 install_element(ENABLE_NODE, &bgp_rpki_stop_cmd);
1556
1557 /* Install rpki reset command */
1558 install_element(RPKI_NODE, &rpki_reset_cmd);
1559
1560 /* Install rpki polling period commands */
1561 install_element(RPKI_NODE, &rpki_polling_period_cmd);
1562 install_element(RPKI_NODE, &no_rpki_polling_period_cmd);
1563
1564 /* Install rpki expire interval commands */
1565 install_element(RPKI_NODE, &rpki_expire_interval_cmd);
1566 install_element(RPKI_NODE, &no_rpki_expire_interval_cmd);
1567
1568 /* Install rpki retry interval commands */
1569 install_element(RPKI_NODE, &rpki_retry_interval_cmd);
1570 install_element(RPKI_NODE, &no_rpki_retry_interval_cmd);
1571
1572 /* Install rpki timeout commands */
1573 install_element(RPKI_NODE, &rpki_timeout_cmd);
1574 install_element(RPKI_NODE, &no_rpki_timeout_cmd);
1575
1576 /* Install rpki synchronisation timeout commands */
1577 install_element(RPKI_NODE, &rpki_synchronisation_timeout_cmd);
1578 install_element(RPKI_NODE, &no_rpki_synchronisation_timeout_cmd);
1579
1580 /* Install rpki cache commands */
1581 install_element(RPKI_NODE, &rpki_cache_cmd);
1582 install_element(RPKI_NODE, &no_rpki_cache_cmd);
1583
1584 /* Install show commands */
9593708d 1585 install_element(VIEW_NODE, &show_rpki_prefix_table_cmd);
1586 install_element(VIEW_NODE, &show_rpki_cache_connection_cmd);
1587 install_element(VIEW_NODE, &show_rpki_cache_server_cmd);
1588 install_element(VIEW_NODE, &show_rpki_prefix_cmd);
02334bb2 1589 install_element(VIEW_NODE, &show_rpki_as_number_cmd);
dabecd7c
MR
1590
1591 /* Install debug commands */
1592 install_element(CONFIG_NODE, &debug_rpki_cmd);
1593 install_element(ENABLE_NODE, &debug_rpki_cmd);
1594 install_element(CONFIG_NODE, &no_debug_rpki_cmd);
1595 install_element(ENABLE_NODE, &no_debug_rpki_cmd);
1596
1597 /* Install route match */
1598 route_map_install_match(&route_match_rpki_cmd);
1599 install_element(RMAP_NODE, &match_rpki_cmd);
1600 install_element(RMAP_NODE, &no_match_rpki_cmd);
1601}
1602
1603FRR_MODULE_SETUP(.name = "bgpd_rpki", .version = "0.3.6",
1604 .description = "Enable RPKI support for FRR.",
996c9314 1605 .init = bgp_rpki_module_init)