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