]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_rpki.c
bgpd: Validate large-community-list against UINT_MAX
[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. "
0e43d16b 1115 "If you want to use it\n");
dabecd7c
MR
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
fef6fafa 1256#if defined(FOUND_SSH)
745ae9c0
MR
1257 } else if (cache->type == SSH) {
1258 vty_out(vty,
1259 "host: %s port: %d username: %s "
1260 "server_hostkey_path: %s client_privkey_path: %s\n",
1261 cache->tr_config.ssh_config->host,
1262 cache->tr_config.ssh_config->port,
1263 cache->tr_config.ssh_config->username,
1264 cache->tr_config.ssh_config
1265 ->server_hostkey_path,
1266 cache->tr_config.ssh_config
1267 ->client_privkey_path);
fef6fafa 1268#endif
745ae9c0 1269 }
dabecd7c
MR
1270 }
1271
1272 return CMD_SUCCESS;
1273}
1274
1275DEFUN (show_rpki_cache_connection,
1276 show_rpki_cache_connection_cmd,
1277 "show rpki cache-connection",
1278 SHOW_STR
1279 RPKI_OUTPUT_STRING
08f9cfb8 1280 "Show to which RPKI Cache Servers we have a connection\n")
dabecd7c
MR
1281{
1282 if (is_synchronized()) {
1283 struct listnode *cache_node;
1284 struct cache *cache;
1285 struct rtr_mgr_group *group = get_connected_group();
1286
1287 if (!group) {
1288 vty_out(vty, "Cannot find a connected group.\n");
1289 return CMD_SUCCESS;
1290 }
1291 vty_out(vty, "Connected to group %d\n", group->preference);
996c9314 1292 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
dabecd7c
MR
1293 if (cache->preference == group->preference) {
1294 struct tr_tcp_config *tcp_config;
acd4a9f4 1295#if defined(FOUND_SSH)
dabecd7c 1296 struct tr_ssh_config *ssh_config;
acd4a9f4 1297#endif
dabecd7c
MR
1298
1299 switch (cache->type) {
1300 case TCP:
1301 tcp_config =
996c9314 1302 cache->tr_config.tcp_config;
dabecd7c
MR
1303 vty_out(vty,
1304 "rpki tcp cache %s %s pref %hhu\n",
1305 tcp_config->host,
1306 tcp_config->port,
1307 cache->preference);
1308 break;
1309
1310#if defined(FOUND_SSH)
1311 case SSH:
1312 ssh_config =
996c9314 1313 cache->tr_config.ssh_config;
dabecd7c
MR
1314 vty_out(vty,
1315 "rpki ssh cache %s %u pref %hhu\n",
1316 ssh_config->host,
1317 ssh_config->port,
1318 cache->preference);
1319 break;
1320#endif
1321
1322 default:
1323 break;
1324 }
1325 }
1326 }
1327 } else {
1328 vty_out(vty, "No connection to RPKI cache server.\n");
1329 }
1330
1331 return CMD_SUCCESS;
1332}
1333
1334DEFUN_NOSH (rpki_exit,
1335 rpki_exit_cmd,
1336 "exit",
08f9cfb8 1337 "Exit rpki configuration and restart rpki session\n")
dabecd7c 1338{
61a484a9 1339 reset(false);
dabecd7c
MR
1340
1341 vty->node = CONFIG_NODE;
61a484a9 1342 return CMD_SUCCESS;
dabecd7c
MR
1343}
1344
1345DEFUN_NOSH (rpki_quit,
1346 rpki_quit_cmd,
1347 "quit",
08f9cfb8 1348 "Exit rpki configuration mode\n")
dabecd7c
MR
1349{
1350 return rpki_exit(self, vty, argc, argv);
1351}
1352
1353DEFUN_NOSH (rpki_end,
1354 rpki_end_cmd,
1355 "end",
08f9cfb8 1356 "End rpki configuration, restart rpki session and change to enable mode.\n")
dabecd7c
MR
1357{
1358 int ret = reset(false);
1359
f344c66e 1360 vty_config_exit(vty);
dabecd7c
MR
1361 vty->node = ENABLE_NODE;
1362 return ret == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1363}
1364
1365DEFUN (rpki_reset,
1366 rpki_reset_cmd,
1367 "rpki reset",
1368 RPKI_OUTPUT_STRING
1369 "reset rpki\n")
1370{
1371 return reset(true) == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1372}
1373
1374DEFUN (debug_rpki,
1375 debug_rpki_cmd,
1376 "debug rpki",
1377 DEBUG_STR
08f9cfb8 1378 "Enable debugging for rpki\n")
dabecd7c
MR
1379{
1380 rpki_debug = 1;
1381 return CMD_SUCCESS;
1382}
1383
1384DEFUN (no_debug_rpki,
1385 no_debug_rpki_cmd,
1386 "no debug rpki",
1387 NO_STR
1388 DEBUG_STR
08f9cfb8 1389 "Disable debugging for rpki\n")
dabecd7c
MR
1390{
1391 rpki_debug = 0;
1392 return CMD_SUCCESS;
1393}
1394
1395DEFUN (match_rpki,
1396 match_rpki_cmd,
1397 "match rpki <valid|invalid|notfound>",
1398 MATCH_STR
1399 RPKI_OUTPUT_STRING
1400 "Valid prefix\n"
1401 "Invalid prefix\n"
1402 "Prefix not found\n")
1403{
1404 VTY_DECLVAR_CONTEXT(route_map_index, index);
1405 int ret;
1406
1407 ret = route_map_add_match(index, "rpki", argv[2]->arg);
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)