]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_rpki.c
*: Fixup to use proper list_cmp functions
[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
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;
9b6d8fcf 220 struct bgp_path_info *path;
dabecd7c
MR
221
222 if (type == RMAP_BGP) {
9b6d8fcf 223 path = object;
dabecd7c 224
9b6d8fcf 225 if (rpki_validate_prefix(path->peer, path->attr, prefix)
dabecd7c
MR
226 == *rpki_status) {
227 return RMAP_MATCH;
228 }
229 }
230 return RMAP_NOMATCH;
231}
232
233static void *route_match_compile(const char *arg)
234{
235 int *rpki_status;
236
0b2c4b35 237 rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
dabecd7c
MR
238
239 if (strcmp(arg, "valid") == 0)
240 *rpki_status = RPKI_VALID;
241 else if (strcmp(arg, "invalid") == 0)
242 *rpki_status = RPKI_INVALID;
243 else
244 *rpki_status = RPKI_NOTFOUND;
245
246 return rpki_status;
247}
248
249static void route_match_free(void *rule)
250{
251 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
252}
253
254static struct rtr_socket *create_rtr_socket(struct tr_socket *tr_socket)
255{
256 struct rtr_socket *rtr_socket =
257 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct rtr_socket));
258 rtr_socket->tr_socket = tr_socket;
259 return rtr_socket;
260}
261
262static struct cache *find_cache(const uint8_t preference)
263{
264 struct listnode *cache_node;
265 struct cache *cache;
266
267 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
268 if (cache->preference == preference)
269 return cache;
270 }
271 return NULL;
272}
273
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
6a154c88 405 list_delete(&matches);
31a2af32 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;
9b6d8fcf 421 struct bgp_path_info *path = bgp_node->info;
1dacdd8b
MR
422 mpls_label_t *label = NULL;
423 uint32_t num_labels = 0;
424
9b6d8fcf
DS
425 if (path && path->extra) {
426 label = path->extra->label;
427 num_labels = path->extra->num_labels;
1dacdd8b 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();
6a154c88 542 list_delete(&cache_list);
dabecd7c 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
1136 if (!cache) {
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)) {
996c9314 1192 vty_out(vty, "host: %s port: %s\n",
dabecd7c
MR
1193 cache->tr_config.tcp_config->host,
1194 cache->tr_config.tcp_config->port);
1195 }
1196
1197 return CMD_SUCCESS;
1198}
1199
1200DEFUN (show_rpki_cache_connection,
1201 show_rpki_cache_connection_cmd,
1202 "show rpki cache-connection",
1203 SHOW_STR
1204 RPKI_OUTPUT_STRING
08f9cfb8 1205 "Show to which RPKI Cache Servers we have a connection\n")
dabecd7c
MR
1206{
1207 if (is_synchronized()) {
1208 struct listnode *cache_node;
1209 struct cache *cache;
1210 struct rtr_mgr_group *group = get_connected_group();
1211
1212 if (!group) {
1213 vty_out(vty, "Cannot find a connected group.\n");
1214 return CMD_SUCCESS;
1215 }
1216 vty_out(vty, "Connected to group %d\n", group->preference);
996c9314 1217 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
dabecd7c
MR
1218 if (cache->preference == group->preference) {
1219 struct tr_tcp_config *tcp_config;
acd4a9f4 1220#if defined(FOUND_SSH)
dabecd7c 1221 struct tr_ssh_config *ssh_config;
acd4a9f4 1222#endif
dabecd7c
MR
1223
1224 switch (cache->type) {
1225 case TCP:
1226 tcp_config =
996c9314 1227 cache->tr_config.tcp_config;
dabecd7c
MR
1228 vty_out(vty,
1229 "rpki tcp cache %s %s pref %hhu\n",
1230 tcp_config->host,
1231 tcp_config->port,
1232 cache->preference);
1233 break;
1234
1235#if defined(FOUND_SSH)
1236 case SSH:
1237 ssh_config =
996c9314 1238 cache->tr_config.ssh_config;
dabecd7c
MR
1239 vty_out(vty,
1240 "rpki ssh cache %s %u pref %hhu\n",
1241 ssh_config->host,
1242 ssh_config->port,
1243 cache->preference);
1244 break;
1245#endif
1246
1247 default:
1248 break;
1249 }
1250 }
1251 }
1252 } else {
1253 vty_out(vty, "No connection to RPKI cache server.\n");
1254 }
1255
1256 return CMD_SUCCESS;
1257}
1258
1259DEFUN_NOSH (rpki_exit,
1260 rpki_exit_cmd,
1261 "exit",
08f9cfb8 1262 "Exit rpki configuration and restart rpki session\n")
dabecd7c 1263{
61a484a9 1264 reset(false);
dabecd7c
MR
1265
1266 vty->node = CONFIG_NODE;
61a484a9 1267 return CMD_SUCCESS;
dabecd7c
MR
1268}
1269
1270DEFUN_NOSH (rpki_quit,
1271 rpki_quit_cmd,
1272 "quit",
08f9cfb8 1273 "Exit rpki configuration mode\n")
dabecd7c
MR
1274{
1275 return rpki_exit(self, vty, argc, argv);
1276}
1277
1278DEFUN_NOSH (rpki_end,
1279 rpki_end_cmd,
1280 "end",
08f9cfb8 1281 "End rpki configuration, restart rpki session and change to enable mode.\n")
dabecd7c
MR
1282{
1283 int ret = reset(false);
1284
1285 vty_config_unlock(vty);
1286 vty->node = ENABLE_NODE;
1287 return ret == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1288}
1289
1290DEFUN (rpki_reset,
1291 rpki_reset_cmd,
1292 "rpki reset",
1293 RPKI_OUTPUT_STRING
1294 "reset rpki\n")
1295{
1296 return reset(true) == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1297}
1298
1299DEFUN (debug_rpki,
1300 debug_rpki_cmd,
1301 "debug rpki",
1302 DEBUG_STR
08f9cfb8 1303 "Enable debugging for rpki\n")
dabecd7c
MR
1304{
1305 rpki_debug = 1;
1306 return CMD_SUCCESS;
1307}
1308
1309DEFUN (no_debug_rpki,
1310 no_debug_rpki_cmd,
1311 "no debug rpki",
1312 NO_STR
1313 DEBUG_STR
08f9cfb8 1314 "Disable debugging for rpki\n")
dabecd7c
MR
1315{
1316 rpki_debug = 0;
1317 return CMD_SUCCESS;
1318}
1319
1320DEFUN (match_rpki,
1321 match_rpki_cmd,
1322 "match rpki <valid|invalid|notfound>",
1323 MATCH_STR
1324 RPKI_OUTPUT_STRING
1325 "Valid prefix\n"
1326 "Invalid prefix\n"
1327 "Prefix not found\n")
1328{
1329 VTY_DECLVAR_CONTEXT(route_map_index, index);
1330 int ret;
1331
1332 ret = route_map_add_match(index, "rpki", argv[2]->arg);
1333 if (ret) {
1334 switch (ret) {
1335 case RMAP_RULE_MISSING:
1336 vty_out(vty, "%% BGP Can't find rule.\n");
1337 return CMD_WARNING_CONFIG_FAILED;
1338 case RMAP_COMPILE_ERROR:
1339 vty_out(vty, "%% BGP Argument is malformed.\n");
1340 return CMD_WARNING_CONFIG_FAILED;
1341 }
1342 }
1343 return CMD_SUCCESS;
1344}
1345
1346DEFUN (no_match_rpki,
1347 no_match_rpki_cmd,
1348 "no match rpki <valid|invalid|notfound>",
1349 NO_STR
1350 MATCH_STR
1351 RPKI_OUTPUT_STRING
1352 "Valid prefix\n"
1353 "Invalid prefix\n"
1354 "Prefix not found\n")
1355{
1356 VTY_DECLVAR_CONTEXT(route_map_index, index);
1357 int ret;
1358
1359 ret = route_map_delete_match(index, "rpki", argv[3]->arg);
1360 if (ret) {
1361 switch (ret) {
1362 case RMAP_RULE_MISSING:
1363 vty_out(vty, "%% BGP Can't find rule.\n");
1364 break;
1365 case RMAP_COMPILE_ERROR:
1366 vty_out(vty, "%% BGP Argument is malformed.\n");
1367 break;
1368 }
1369 return CMD_WARNING_CONFIG_FAILED;
1370 }
1371
1372 return CMD_SUCCESS;
1373}
1374
1375static void overwrite_exit_commands(void)
1376{
1377 unsigned int i;
1378 vector cmd_vector = rpki_node.cmd_vector;
1379
1380 for (i = 0; i < cmd_vector->active; ++i) {
1381 struct cmd_element *cmd = vector_lookup(cmd_vector, i);
1382
996c9314
LB
1383 if (strcmp(cmd->string, "exit") == 0
1384 || strcmp(cmd->string, "quit") == 0
1385 || strcmp(cmd->string, "end") == 0) {
dabecd7c
MR
1386 uninstall_element(RPKI_NODE, cmd);
1387 }
1388 }
1389
1390 install_element(RPKI_NODE, &rpki_exit_cmd);
1391 install_element(RPKI_NODE, &rpki_quit_cmd);
1392 install_element(RPKI_NODE, &rpki_end_cmd);
1393}
1394
1395static void install_cli_commands(void)
1396{
996c9314 1397 // TODO: make config write work
dabecd7c
MR
1398 install_node(&rpki_node, &config_write);
1399 install_default(RPKI_NODE);
1400 overwrite_exit_commands();
1401 install_element(CONFIG_NODE, &rpki_cmd);
1402 install_element(VIEW_NODE, &rpki_cmd);
1403
1404 install_element(ENABLE_NODE, &bgp_rpki_start_cmd);
1405 install_element(ENABLE_NODE, &bgp_rpki_stop_cmd);
1406
1407 /* Install rpki reset command */
1408 install_element(RPKI_NODE, &rpki_reset_cmd);
1409
1410 /* Install rpki polling period commands */
1411 install_element(RPKI_NODE, &rpki_polling_period_cmd);
1412 install_element(RPKI_NODE, &no_rpki_polling_period_cmd);
1413
1414 /* Install rpki expire interval commands */
1415 install_element(RPKI_NODE, &rpki_expire_interval_cmd);
1416 install_element(RPKI_NODE, &no_rpki_expire_interval_cmd);
1417
1418 /* Install rpki retry interval commands */
1419 install_element(RPKI_NODE, &rpki_retry_interval_cmd);
1420 install_element(RPKI_NODE, &no_rpki_retry_interval_cmd);
1421
1422 /* Install rpki timeout commands */
1423 install_element(RPKI_NODE, &rpki_timeout_cmd);
1424 install_element(RPKI_NODE, &no_rpki_timeout_cmd);
1425
1426 /* Install rpki synchronisation timeout commands */
1427 install_element(RPKI_NODE, &rpki_synchronisation_timeout_cmd);
1428 install_element(RPKI_NODE, &no_rpki_synchronisation_timeout_cmd);
1429
1430 /* Install rpki cache commands */
1431 install_element(RPKI_NODE, &rpki_cache_cmd);
1432 install_element(RPKI_NODE, &no_rpki_cache_cmd);
1433
1434 /* Install show commands */
1435 install_element(ENABLE_NODE, &show_rpki_prefix_table_cmd);
1436 install_element(ENABLE_NODE, &show_rpki_cache_connection_cmd);
1437 install_element(ENABLE_NODE, &show_rpki_cache_server_cmd);
1438
1439 /* Install debug commands */
1440 install_element(CONFIG_NODE, &debug_rpki_cmd);
1441 install_element(ENABLE_NODE, &debug_rpki_cmd);
1442 install_element(CONFIG_NODE, &no_debug_rpki_cmd);
1443 install_element(ENABLE_NODE, &no_debug_rpki_cmd);
1444
1445 /* Install route match */
1446 route_map_install_match(&route_match_rpki_cmd);
1447 install_element(RMAP_NODE, &match_rpki_cmd);
1448 install_element(RMAP_NODE, &no_match_rpki_cmd);
1449}
1450
1451FRR_MODULE_SETUP(.name = "bgpd_rpki", .version = "0.3.6",
1452 .description = "Enable RPKI support for FRR.",
996c9314 1453 .init = bgp_rpki_module_init)