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