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