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