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