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