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