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