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