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