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