]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_rpki.c
Merge pull request #4688 from qlyoung/alpine-docker-rpki
[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);
2789041a
LK
132static route_map_result_t route_match(void *rule, const struct prefix *prefix,
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
2789041a
LK
216static route_map_result_t route_match(void *rule, const struct prefix *prefix,
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
7c3f0950 740 prefix_string = prefix2str(prefix, buf, sizeof(buf));
dabecd7c
MR
741 switch (result) {
742 case BGP_PFXV_STATE_VALID:
743 RPKI_DEBUG(
7c3f0950
DS
744 "Validating Prefix %s from asn %u Result: VALID",
745 prefix_string, as_number);
dabecd7c
MR
746 return RPKI_VALID;
747 case BGP_PFXV_STATE_NOT_FOUND:
748 RPKI_DEBUG(
7c3f0950
DS
749 "Validating Prefix %s from asn %u Result: NOT FOUND",
750 prefix_string, as_number);
dabecd7c
MR
751 return RPKI_NOTFOUND;
752 case BGP_PFXV_STATE_INVALID:
753 RPKI_DEBUG(
7c3f0950
DS
754 "Validating Prefix %s from asn %u Result: INVALID",
755 prefix_string, as_number);
dabecd7c
MR
756 return RPKI_INVALID;
757 default:
758 RPKI_DEBUG(
7c3f0950
DS
759 "Validating Prefix %s from asn %u Result: CANNOT VALIDATE",
760 prefix_string, as_number);
dabecd7c
MR
761 break;
762 }
763 return 0;
764}
765
766static int add_cache(struct cache *cache)
767{
768 uint8_t preference = cache->preference;
769 struct rtr_mgr_group group;
770
771 group.preference = preference;
772 group.sockets_len = 1;
773 group.sockets = &cache->rtr_socket;
774
775 listnode_add(cache_list, cache);
776
92110aab
MR
777 if (rtr_is_running) {
778 init_tr_socket(cache);
779
780 if (rtr_mgr_add_group(rtr_config, &group) != RTR_SUCCESS) {
781 free_tr_socket(cache);
782 return ERROR;
783 }
dabecd7c
MR
784 }
785
786 return SUCCESS;
787}
788
996c9314 789static int add_tcp_cache(const char *host, const char *port,
dabecd7c
MR
790 const uint8_t preference)
791{
792 struct rtr_socket *rtr_socket;
793 struct tr_tcp_config *tcp_config =
794 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_tcp_config));
795 struct tr_socket *tr_socket =
796 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
797 struct cache *cache =
798 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
799
800 tcp_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
801 tcp_config->port = XSTRDUP(MTYPE_BGP_RPKI_CACHE, port);
802 tcp_config->bindaddr = NULL;
803
804 rtr_socket = create_rtr_socket(tr_socket);
805
806 cache->type = TCP;
807 cache->tr_socket = tr_socket;
808 cache->tr_config.tcp_config = tcp_config;
809 cache->rtr_socket = rtr_socket;
810 cache->preference = preference;
811
812 return add_cache(cache);
813}
814
815#if defined(FOUND_SSH)
996c9314
LB
816static int add_ssh_cache(const char *host, const unsigned int port,
817 const char *username, const char *client_privkey_path,
dabecd7c
MR
818 const char *client_pubkey_path,
819 const char *server_pubkey_path,
820 const uint8_t preference)
821{
822 struct tr_ssh_config *ssh_config =
823 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_ssh_config));
824 struct cache *cache =
825 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
826 struct tr_socket *tr_socket =
827 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
828 struct rtr_socket *rtr_socket;
829
830 ssh_config->port = port;
831 ssh_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
832 ssh_config->bindaddr = NULL;
833
834 ssh_config->username = XSTRDUP(MTYPE_BGP_RPKI_CACHE, username);
996c9314
LB
835 ssh_config->client_privkey_path =
836 XSTRDUP(MTYPE_BGP_RPKI_CACHE, client_privkey_path);
dabecd7c
MR
837 ssh_config->server_hostkey_path =
838 XSTRDUP(MTYPE_BGP_RPKI_CACHE, server_pubkey_path);
839
840 rtr_socket = create_rtr_socket(tr_socket);
841
842 cache->type = SSH;
843 cache->tr_socket = tr_socket;
844 cache->tr_config.ssh_config = ssh_config;
845 cache->rtr_socket = rtr_socket;
846 cache->preference = preference;
847
848 return add_cache(cache);
849}
850#endif
851
852static void free_cache(struct cache *cache)
853{
854 if (cache->type == TCP) {
996c9314
LB
855 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->host);
856 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->port);
dabecd7c
MR
857 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config);
858 }
859#if defined(FOUND_SSH)
860 else {
996c9314 861 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config->host);
dabecd7c
MR
862 XFREE(MTYPE_BGP_RPKI_CACHE,
863 cache->tr_config.ssh_config->username);
864 XFREE(MTYPE_BGP_RPKI_CACHE,
865 cache->tr_config.ssh_config->client_privkey_path);
866 XFREE(MTYPE_BGP_RPKI_CACHE,
867 cache->tr_config.ssh_config->server_hostkey_path);
868 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config);
869 }
870#endif
871 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_socket);
872 XFREE(MTYPE_BGP_RPKI_CACHE, cache->rtr_socket);
873 XFREE(MTYPE_BGP_RPKI_CACHE, cache);
874}
875
876static int config_write(struct vty *vty)
877{
878 struct listnode *cache_node;
879 struct cache *cache;
880
881 if (listcount(cache_list)) {
882 if (rpki_debug)
883 vty_out(vty, "debug rpki\n");
884
885 vty_out(vty, "!\n");
886 vty_out(vty, "rpki\n");
887 vty_out(vty, " rpki polling_period %d\n", polling_period);
888 vty_out(vty, " rpki timeout %d\n", timeout);
889 vty_out(vty, " rpki initial-synchronisation-timeout %d\n",
890 initial_synchronisation_timeout);
891 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
892 switch (cache->type) {
893 struct tr_tcp_config *tcp_config;
acd4a9f4 894#if defined(FOUND_SSH)
dabecd7c 895 struct tr_ssh_config *ssh_config;
acd4a9f4 896#endif
dabecd7c
MR
897 case TCP:
898 tcp_config = cache->tr_config.tcp_config;
996c9314
LB
899 vty_out(vty, " rpki cache %s %s ",
900 tcp_config->host, tcp_config->port);
dabecd7c
MR
901 break;
902#if defined(FOUND_SSH)
903 case SSH:
904 ssh_config = cache->tr_config.ssh_config;
996c9314
LB
905 vty_out(vty, " rpki cache %s %u %s %s %s ",
906 ssh_config->host, ssh_config->port,
dabecd7c
MR
907 ssh_config->username,
908 ssh_config->client_privkey_path,
996c9314 909 ssh_config->server_hostkey_path != NULL
dabecd7c
MR
910 ? ssh_config
911 ->server_hostkey_path
912 : " ");
913 break;
914#endif
915 default:
916 break;
917 }
918
919 vty_out(vty, "preference %hhu\n", cache->preference);
920 }
921 vty_out(vty, " exit\n");
922 return 1;
923 } else {
924 return 0;
925 }
926}
927
928DEFUN_NOSH (rpki,
929 rpki_cmd,
930 "rpki",
931 "Enable rpki and enter rpki configuration mode\n")
932{
933 vty->node = RPKI_NODE;
934 return CMD_SUCCESS;
935}
936
937DEFUN (bgp_rpki_start,
938 bgp_rpki_start_cmd,
939 "rpki start",
940 RPKI_OUTPUT_STRING
941 "start rpki support\n")
942{
943 if (listcount(cache_list) == 0)
996c9314
LB
944 vty_out(vty,
945 "Could not start rpki because no caches are configured\n");
dabecd7c
MR
946
947 if (!is_running()) {
948 if (start() == ERROR) {
949 RPKI_DEBUG("RPKI failed to start");
950 return CMD_WARNING;
951 }
952 }
953 return CMD_SUCCESS;
954}
955
956DEFUN (bgp_rpki_stop,
957 bgp_rpki_stop_cmd,
958 "rpki stop",
959 RPKI_OUTPUT_STRING
960 "start rpki support\n")
961{
962 if (is_running())
963 stop();
964
965 return CMD_SUCCESS;
966}
967
968DEFPY (rpki_polling_period,
969 rpki_polling_period_cmd,
970 "rpki polling_period (1-86400)$pp",
971 RPKI_OUTPUT_STRING
972 "Set polling period\n"
973 "Polling period value\n")
974{
975 polling_period = pp;
976 return CMD_SUCCESS;
977}
978
979DEFUN (no_rpki_polling_period,
980 no_rpki_polling_period_cmd,
981 "no rpki polling_period",
982 NO_STR
983 RPKI_OUTPUT_STRING
984 "Set polling period back to default\n")
985{
986 polling_period = POLLING_PERIOD_DEFAULT;
987 return CMD_SUCCESS;
988}
989
990DEFPY (rpki_expire_interval,
991 rpki_expire_interval_cmd,
992 "rpki expire_interval (600-172800)$tmp",
993 RPKI_OUTPUT_STRING
994 "Set expire interval\n"
995 "Expire interval value\n")
996{
6f577f58 997 if ((unsigned int)tmp >= polling_period) {
dabecd7c
MR
998 expire_interval = tmp;
999 return CMD_SUCCESS;
1000 }
1001
1002 vty_out(vty, "%% Expiry interval must be polling period or larger\n");
1003 return CMD_WARNING_CONFIG_FAILED;
1004}
1005
1006DEFUN (no_rpki_expire_interval,
1007 no_rpki_expire_interval_cmd,
1008 "no rpki expire_interval",
1009 NO_STR
1010 RPKI_OUTPUT_STRING
1011 "Set expire interval back to default\n")
1012{
1013 expire_interval = polling_period * 2;
1014 return CMD_SUCCESS;
1015}
1016
1017DEFPY (rpki_retry_interval,
1018 rpki_retry_interval_cmd,
1019 "rpki retry_interval (1-7200)$tmp",
1020 RPKI_OUTPUT_STRING
1021 "Set retry interval\n"
1022 "retry interval value\n")
1023{
1024 retry_interval = tmp;
1025 return CMD_SUCCESS;
1026}
1027
1028DEFUN (no_rpki_retry_interval,
1029 no_rpki_retry_interval_cmd,
1030 "no rpki retry_interval",
1031 NO_STR
1032 RPKI_OUTPUT_STRING
1033 "Set retry interval back to default\n")
1034{
1035 retry_interval = RETRY_INTERVAL_DEFAULT;
1036 return CMD_SUCCESS;
1037}
1038
1039DEFPY (rpki_timeout,
1040 rpki_timeout_cmd,
1041 "rpki timeout (1-4294967295)$to_arg",
1042 RPKI_OUTPUT_STRING
1043 "Set timeout\n"
1044 "Timeout value\n")
1045{
1046 timeout = to_arg;
1047 return CMD_SUCCESS;
1048}
1049
1050DEFUN (no_rpki_timeout,
1051 no_rpki_timeout_cmd,
1052 "no rpki timeout",
1053 NO_STR
1054 RPKI_OUTPUT_STRING
1055 "Set timeout back to default\n")
1056{
1057 timeout = TIMEOUT_DEFAULT;
1058 return CMD_SUCCESS;
1059}
1060
1061DEFPY (rpki_synchronisation_timeout,
1062 rpki_synchronisation_timeout_cmd,
1063 "rpki initial-synchronisation-timeout (1-4294967295)$ito_arg",
1064 RPKI_OUTPUT_STRING
1065 "Set a timeout for the initial synchronisation of prefix validation data\n"
1066 "Timeout value\n")
1067{
1068 initial_synchronisation_timeout = ito_arg;
1069 return CMD_SUCCESS;
1070}
1071
1072DEFUN (no_rpki_synchronisation_timeout,
1073 no_rpki_synchronisation_timeout_cmd,
1074 "no rpki initial-synchronisation-timeout",
1075 NO_STR
1076 RPKI_OUTPUT_STRING
1077 "Set the initial synchronisation timeout back to default (30 sec.)\n")
1078{
1079 initial_synchronisation_timeout =
1080 INITIAL_SYNCHRONISATION_TIMEOUT_DEFAULT;
1081 return CMD_SUCCESS;
1082}
1083
1084DEFPY (rpki_cache,
1085 rpki_cache_cmd,
1086 "rpki cache <A.B.C.D|WORD>"
1087 "<TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY SSH_PUBKEY [SERVER_PUBKEY]> "
1088 "preference (1-255)",
1089 RPKI_OUTPUT_STRING
1090 "Install a cache server to current group\n"
1091 "IP address of cache server\n Hostname of cache server\n"
1092 "TCP port number\n"
1093 "SSH port number\n"
1094 "SSH user name\n"
1095 "Path to own SSH private key\n"
1096 "Path to own SSH public key\n"
1097 "Path to Public key of cache server\n"
1098 "Preference of the cache server\n"
1099 "Preference value\n")
1100{
3f54c705 1101 int return_value;
dabecd7c
MR
1102
1103 // use ssh connection
1104 if (ssh_uname) {
1105#if defined(FOUND_SSH)
996c9314
LB
1106 return_value =
1107 add_ssh_cache(cache, sshport, ssh_uname, ssh_privkey,
1108 ssh_pubkey, server_pubkey, preference);
dabecd7c 1109#else
3f54c705 1110 return_value = SUCCESS;
dabecd7c
MR
1111 vty_out(vty,
1112 "ssh sockets are not supported. "
1113 "Please recompile rtrlib and frr with ssh support. "
0e43d16b 1114 "If you want to use it\n");
dabecd7c
MR
1115#endif
1116 } else { // use tcp connection
1117 return_value = add_tcp_cache(cache, tcpport, preference);
1118 }
1119
1120 if (return_value == ERROR) {
1121 vty_out(vty, "Could not create new rpki cache\n");
1122 return CMD_WARNING;
1123 }
1124
1125 return CMD_SUCCESS;
1126}
1127
1128DEFPY (no_rpki_cache,
1129 no_rpki_cache_cmd,
1130 "no rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport> preference (1-255)$preference",
1131 NO_STR
1132 RPKI_OUTPUT_STRING
1133 "Remove a cache server\n"
1134 "IP address of cache server\n Hostname of cache server\n"
1135 "TCP port number\n"
1136 "SSH port number\n"
1137 "Preference of the cache server\n"
1138 "Preference value\n")
1139{
1140 struct cache *cache_p = find_cache(preference);
1141
222487fe 1142 if (!cache_p) {
dabecd7c
MR
1143 vty_out(vty, "Could not find cache %ld\n", preference);
1144 return CMD_WARNING;
1145 }
1146
1147 if (rtr_is_running) {
1148 if (rtr_mgr_remove_group(rtr_config, preference) == RTR_ERROR) {
1149 vty_out(vty, "Could not remove cache %ld", preference);
1150 if (listcount(cache_list) == 1)
1151 vty_out(vty, " because it is the last cache");
1152
1153 vty_out(vty, "\n");
1154 return CMD_WARNING;
1155 }
1156 }
1157
1158 listnode_delete(cache_list, cache_p);
1159 free_cache(cache_p);
1160
1161 return CMD_SUCCESS;
1162}
1163
1164DEFUN (show_rpki_prefix_table,
1165 show_rpki_prefix_table_cmd,
1166 "show rpki prefix-table",
1167 SHOW_STR
1168 RPKI_OUTPUT_STRING
08f9cfb8 1169 "Show validated prefixes which were received from RPKI Cache\n")
dabecd7c
MR
1170{
1171 struct listnode *cache_node;
1172 struct cache *cache;
1173
1174 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
996c9314 1175 vty_out(vty, "host: %s port: %s\n",
dabecd7c
MR
1176 cache->tr_config.tcp_config->host,
1177 cache->tr_config.tcp_config->port);
1178 }
1179 if (is_synchronized())
1180 print_prefix_table(vty);
1181 else
1182 vty_out(vty, "No connection to RPKI cache server.\n");
1183
1184 return CMD_SUCCESS;
1185}
1186
5d799192
MR
1187DEFPY (show_rpki_prefix,
1188 show_rpki_prefix_cmd,
1189 "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)$asn]",
1190 SHOW_STR
1191 RPKI_OUTPUT_STRING
1192 "Lookup IP prefix and optionally ASN in prefix table\n"
1193 "IPv4 prefix\n"
1194 "IPv6 prefix\n"
1195 "AS Number\n")
1196{
1197
1198 if (!is_synchronized()) {
1199 vty_out(vty, "No Conection to RPKI cache server.\n");
1200 return CMD_WARNING;
1201 }
1202
1203 struct lrtr_ip_addr addr;
1204 char addr_str[INET6_ADDRSTRLEN];
1205 size_t addr_len = strchr(prefix_str, '/') - prefix_str;
1206
1207 memset(addr_str, 0, sizeof(addr_str));
1208 memcpy(addr_str, prefix_str, addr_len);
1209
1210 if (lrtr_ip_str_to_addr(addr_str, &addr) != 0) {
1211 vty_out(vty, "Invalid IP prefix\n");
1212 return CMD_WARNING;
1213 }
1214
1215 struct pfx_record *matches = NULL;
1216 unsigned int match_count = 0;
1217 enum pfxv_state result;
1218
1219 if (pfx_table_validate_r(rtr_config->pfx_table, &matches, &match_count,
1220 asn, &addr, prefix->prefixlen, &result)
1221 != PFX_SUCCESS) {
1222 vty_out(vty, "Prefix lookup failed");
1223 return CMD_WARNING;
1224 }
1225
1226 vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
1227 for (size_t i = 0; i < match_count; ++i) {
1228 const struct pfx_record *record = &matches[i];
1229
1230 if (record->max_len >= prefix->prefixlen
1231 && ((asn != 0 && asn == record->asn) || asn == 0)) {
1232 print_record(&matches[i], vty);
1233 }
1234 }
1235
1236 return CMD_SUCCESS;
1237}
1238
dabecd7c
MR
1239DEFUN (show_rpki_cache_server,
1240 show_rpki_cache_server_cmd,
1241 "show rpki cache-server",
1242 SHOW_STR
1243 RPKI_OUTPUT_STRING
08f9cfb8 1244 "SHOW configured cache server\n")
dabecd7c
MR
1245{
1246 struct listnode *cache_node;
1247 struct cache *cache;
1248
1249 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
745ae9c0
MR
1250 if (cache->type == TCP) {
1251 vty_out(vty, "host: %s port: %s\n",
1252 cache->tr_config.tcp_config->host,
1253 cache->tr_config.tcp_config->port);
1254
fef6fafa 1255#if defined(FOUND_SSH)
745ae9c0
MR
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);
fef6fafa 1267#endif
745ae9c0 1268 }
dabecd7c
MR
1269 }
1270
1271 return CMD_SUCCESS;
1272}
1273
1274DEFUN (show_rpki_cache_connection,
1275 show_rpki_cache_connection_cmd,
1276 "show rpki cache-connection",
1277 SHOW_STR
1278 RPKI_OUTPUT_STRING
08f9cfb8 1279 "Show to which RPKI Cache Servers we have a connection\n")
dabecd7c
MR
1280{
1281 if (is_synchronized()) {
1282 struct listnode *cache_node;
1283 struct cache *cache;
1284 struct rtr_mgr_group *group = get_connected_group();
1285
1286 if (!group) {
1287 vty_out(vty, "Cannot find a connected group.\n");
1288 return CMD_SUCCESS;
1289 }
1290 vty_out(vty, "Connected to group %d\n", group->preference);
996c9314 1291 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
dabecd7c
MR
1292 if (cache->preference == group->preference) {
1293 struct tr_tcp_config *tcp_config;
acd4a9f4 1294#if defined(FOUND_SSH)
dabecd7c 1295 struct tr_ssh_config *ssh_config;
acd4a9f4 1296#endif
dabecd7c
MR
1297
1298 switch (cache->type) {
1299 case TCP:
1300 tcp_config =
996c9314 1301 cache->tr_config.tcp_config;
dabecd7c
MR
1302 vty_out(vty,
1303 "rpki tcp cache %s %s pref %hhu\n",
1304 tcp_config->host,
1305 tcp_config->port,
1306 cache->preference);
1307 break;
1308
1309#if defined(FOUND_SSH)
1310 case SSH:
1311 ssh_config =
996c9314 1312 cache->tr_config.ssh_config;
dabecd7c
MR
1313 vty_out(vty,
1314 "rpki ssh cache %s %u pref %hhu\n",
1315 ssh_config->host,
1316 ssh_config->port,
1317 cache->preference);
1318 break;
1319#endif
1320
1321 default:
1322 break;
1323 }
1324 }
1325 }
1326 } else {
1327 vty_out(vty, "No connection to RPKI cache server.\n");
1328 }
1329
1330 return CMD_SUCCESS;
1331}
1332
1333DEFUN_NOSH (rpki_exit,
1334 rpki_exit_cmd,
1335 "exit",
08f9cfb8 1336 "Exit rpki configuration and restart rpki session\n")
dabecd7c 1337{
61a484a9 1338 reset(false);
dabecd7c
MR
1339
1340 vty->node = CONFIG_NODE;
61a484a9 1341 return CMD_SUCCESS;
dabecd7c
MR
1342}
1343
1344DEFUN_NOSH (rpki_quit,
1345 rpki_quit_cmd,
1346 "quit",
08f9cfb8 1347 "Exit rpki configuration mode\n")
dabecd7c
MR
1348{
1349 return rpki_exit(self, vty, argc, argv);
1350}
1351
1352DEFUN_NOSH (rpki_end,
1353 rpki_end_cmd,
1354 "end",
08f9cfb8 1355 "End rpki configuration, restart rpki session and change to enable mode.\n")
dabecd7c
MR
1356{
1357 int ret = reset(false);
1358
f344c66e 1359 vty_config_exit(vty);
dabecd7c
MR
1360 vty->node = ENABLE_NODE;
1361 return ret == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1362}
1363
1364DEFUN (rpki_reset,
1365 rpki_reset_cmd,
1366 "rpki reset",
1367 RPKI_OUTPUT_STRING
1368 "reset rpki\n")
1369{
1370 return reset(true) == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1371}
1372
1373DEFUN (debug_rpki,
1374 debug_rpki_cmd,
1375 "debug rpki",
1376 DEBUG_STR
08f9cfb8 1377 "Enable debugging for rpki\n")
dabecd7c
MR
1378{
1379 rpki_debug = 1;
1380 return CMD_SUCCESS;
1381}
1382
1383DEFUN (no_debug_rpki,
1384 no_debug_rpki_cmd,
1385 "no debug rpki",
1386 NO_STR
1387 DEBUG_STR
08f9cfb8 1388 "Disable debugging for rpki\n")
dabecd7c
MR
1389{
1390 rpki_debug = 0;
1391 return CMD_SUCCESS;
1392}
1393
1394DEFUN (match_rpki,
1395 match_rpki_cmd,
1396 "match rpki <valid|invalid|notfound>",
1397 MATCH_STR
1398 RPKI_OUTPUT_STRING
1399 "Valid prefix\n"
1400 "Invalid prefix\n"
1401 "Prefix not found\n")
1402{
1403 VTY_DECLVAR_CONTEXT(route_map_index, index);
1404 int ret;
1405
e2c8d6ce
NT
1406 ret = route_map_add_match(index, "rpki", argv[2]->arg,
1407 RMAP_EVENT_MATCH_ADDED);
dabecd7c
MR
1408 if (ret) {
1409 switch (ret) {
1410 case RMAP_RULE_MISSING:
1411 vty_out(vty, "%% BGP Can't find rule.\n");
1412 return CMD_WARNING_CONFIG_FAILED;
1413 case RMAP_COMPILE_ERROR:
1414 vty_out(vty, "%% BGP Argument is malformed.\n");
1415 return CMD_WARNING_CONFIG_FAILED;
1416 }
1417 }
1418 return CMD_SUCCESS;
1419}
1420
1421DEFUN (no_match_rpki,
1422 no_match_rpki_cmd,
1423 "no match rpki <valid|invalid|notfound>",
1424 NO_STR
1425 MATCH_STR
1426 RPKI_OUTPUT_STRING
1427 "Valid prefix\n"
1428 "Invalid prefix\n"
1429 "Prefix not found\n")
1430{
1431 VTY_DECLVAR_CONTEXT(route_map_index, index);
1432 int ret;
1433
1434 ret = route_map_delete_match(index, "rpki", argv[3]->arg);
1435 if (ret) {
1436 switch (ret) {
1437 case RMAP_RULE_MISSING:
1438 vty_out(vty, "%% BGP Can't find rule.\n");
1439 break;
1440 case RMAP_COMPILE_ERROR:
1441 vty_out(vty, "%% BGP Argument is malformed.\n");
1442 break;
1443 }
1444 return CMD_WARNING_CONFIG_FAILED;
1445 }
1446
1447 return CMD_SUCCESS;
1448}
1449
1450static void overwrite_exit_commands(void)
1451{
1452 unsigned int i;
1453 vector cmd_vector = rpki_node.cmd_vector;
1454
1455 for (i = 0; i < cmd_vector->active; ++i) {
1456 struct cmd_element *cmd = vector_lookup(cmd_vector, i);
1457
996c9314
LB
1458 if (strcmp(cmd->string, "exit") == 0
1459 || strcmp(cmd->string, "quit") == 0
1460 || strcmp(cmd->string, "end") == 0) {
dabecd7c
MR
1461 uninstall_element(RPKI_NODE, cmd);
1462 }
1463 }
1464
1465 install_element(RPKI_NODE, &rpki_exit_cmd);
1466 install_element(RPKI_NODE, &rpki_quit_cmd);
1467 install_element(RPKI_NODE, &rpki_end_cmd);
1468}
1469
1470static void install_cli_commands(void)
1471{
996c9314 1472 // TODO: make config write work
dabecd7c
MR
1473 install_node(&rpki_node, &config_write);
1474 install_default(RPKI_NODE);
1475 overwrite_exit_commands();
1476 install_element(CONFIG_NODE, &rpki_cmd);
9593708d 1477 install_element(ENABLE_NODE, &rpki_cmd);
dabecd7c
MR
1478
1479 install_element(ENABLE_NODE, &bgp_rpki_start_cmd);
1480 install_element(ENABLE_NODE, &bgp_rpki_stop_cmd);
1481
1482 /* Install rpki reset command */
1483 install_element(RPKI_NODE, &rpki_reset_cmd);
1484
1485 /* Install rpki polling period commands */
1486 install_element(RPKI_NODE, &rpki_polling_period_cmd);
1487 install_element(RPKI_NODE, &no_rpki_polling_period_cmd);
1488
1489 /* Install rpki expire interval commands */
1490 install_element(RPKI_NODE, &rpki_expire_interval_cmd);
1491 install_element(RPKI_NODE, &no_rpki_expire_interval_cmd);
1492
1493 /* Install rpki retry interval commands */
1494 install_element(RPKI_NODE, &rpki_retry_interval_cmd);
1495 install_element(RPKI_NODE, &no_rpki_retry_interval_cmd);
1496
1497 /* Install rpki timeout commands */
1498 install_element(RPKI_NODE, &rpki_timeout_cmd);
1499 install_element(RPKI_NODE, &no_rpki_timeout_cmd);
1500
1501 /* Install rpki synchronisation timeout commands */
1502 install_element(RPKI_NODE, &rpki_synchronisation_timeout_cmd);
1503 install_element(RPKI_NODE, &no_rpki_synchronisation_timeout_cmd);
1504
1505 /* Install rpki cache commands */
1506 install_element(RPKI_NODE, &rpki_cache_cmd);
1507 install_element(RPKI_NODE, &no_rpki_cache_cmd);
1508
1509 /* Install show commands */
9593708d 1510 install_element(VIEW_NODE, &show_rpki_prefix_table_cmd);
1511 install_element(VIEW_NODE, &show_rpki_cache_connection_cmd);
1512 install_element(VIEW_NODE, &show_rpki_cache_server_cmd);
1513 install_element(VIEW_NODE, &show_rpki_prefix_cmd);
dabecd7c
MR
1514
1515 /* Install debug commands */
1516 install_element(CONFIG_NODE, &debug_rpki_cmd);
1517 install_element(ENABLE_NODE, &debug_rpki_cmd);
1518 install_element(CONFIG_NODE, &no_debug_rpki_cmd);
1519 install_element(ENABLE_NODE, &no_debug_rpki_cmd);
1520
1521 /* Install route match */
1522 route_map_install_match(&route_match_rpki_cmd);
1523 install_element(RMAP_NODE, &match_rpki_cmd);
1524 install_element(RMAP_NODE, &no_match_rpki_cmd);
1525}
1526
1527FRR_MODULE_SETUP(.name = "bgpd_rpki", .version = "0.3.6",
1528 .description = "Enable RPKI support for FRR.",
996c9314 1529 .init = bgp_rpki_module_init)