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