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