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