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