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