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