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