]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_rpki.c
*: conform with COMMUNITY.md formatting rules, via 'make indent'
[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
8 * Copyright (C) 2017 Marcel Röthke (marcel.roethke@haw-hamburg.de), for HAW
9 * 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
28#include <zebra.h>
29#include <pthread.h>
30#include <time.h>
31#include <stdbool.h>
32#include <stdlib.h>
33#include "prefix.h"
34#include "log.h"
35#include "command.h"
36#include "linklist.h"
37#include "memory.h"
38#include "thread.h"
39#include "filter.h"
40#include "bgpd/bgpd.h"
41#include "bgpd/bgp_table.h"
42#include "bgp_advertise.h"
43#include "bgpd/bgp_debug.h"
44#include "bgpd/bgp_attr.h"
45#include "bgpd/bgp_aspath.h"
46#include "bgpd/bgp_route.h"
47#include "rtrlib/rtrlib.h"
48#include "rtrlib/rtr_mgr.h"
49#include "rtrlib/lib/ip.h"
50#include "rtrlib/transport/tcp/tcp_transport.h"
51#if defined(FOUND_SSH)
52#include "rtrlib/transport/ssh/ssh_transport.h"
53#endif
54#include "hook.h"
55#include "libfrr.h"
56#include "version.h"
57
2e4c2296
RW
58#ifndef VTYSH_EXTRACT_PL
59#include "bgpd/bgp_rpki_clippy.c"
60#endif
dabecd7c
MR
61
62DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_CACHE, "BGP RPKI Cache server")
63DEFINE_MTYPE_STATIC(BGPD, BGP_RPKI_CACHE_GROUP, "BGP RPKI Cache server group")
64
65#define RPKI_VALID 1
66#define RPKI_NOTFOUND 2
67#define RPKI_INVALID 3
68
69#define POLLING_PERIOD_DEFAULT 3600
70#define EXPIRE_INTERVAL_DEFAULT 7200
71#define RETRY_INTERVAL_DEFAULT 600
72#define TIMEOUT_DEFAULT 600
73#define INITIAL_SYNCHRONISATION_TIMEOUT_DEFAULT 30
74
75#define RPKI_DEBUG(...) \
76 if (rpki_debug) { \
77 zlog_debug("RPKI: " __VA_ARGS__); \
78 }
79
80#define RPKI_OUTPUT_STRING "Control rpki specific settings\n"
81
82struct cache {
996c9314
LB
83 enum { TCP, SSH } type;
84 struct tr_socket *tr_socket;
85 union {
dabecd7c
MR
86 struct tr_tcp_config *tcp_config;
87 struct tr_ssh_config *ssh_config;
996c9314
LB
88 } tr_config;
89 struct rtr_socket *rtr_socket;
90 uint8_t preference;
dabecd7c
MR
91};
92
93enum return_values { SUCCESS = 0, ERROR = -1 };
94
95struct rpki_for_each_record_arg {
96 struct vty *vty;
97 unsigned int *prefix_amount;
98};
99
100static int start(void);
101static void stop(void);
102static int reset(bool force);
103static struct rtr_mgr_group *get_connected_group(void);
104static void print_prefix_table(struct vty *vty);
105static void install_cli_commands(void);
106static int config_write(struct vty *vty);
107static void overwrite_exit_commands(void);
108static void free_cache(struct cache *cache);
109static struct rtr_mgr_group *get_groups(void);
110#if defined(FOUND_SSH)
996c9314
LB
111static int add_ssh_cache(const char *host, const unsigned int port,
112 const char *username, const char *client_privkey_path,
dabecd7c
MR
113 const char *client_pubkey_path,
114 const char *server_pubkey_path,
115 const uint8_t preference);
116#endif
117static struct rtr_socket *create_rtr_socket(struct tr_socket *tr_socket);
118static struct cache *find_cache(const uint8_t preference);
996c9314 119static int add_tcp_cache(const char *host, const char *port,
dabecd7c
MR
120 const uint8_t preference);
121static void print_record(const struct pfx_record *record, void *data);
122static int is_synchronized(void);
123static int is_running(void);
124static void route_match_free(void *rule);
996c9314
LB
125static route_map_result_t route_match(void *rule, struct prefix *prefix,
126 route_map_object_t type, void *object);
dabecd7c
MR
127static void *route_match_compile(const char *arg);
128
129static struct rtr_mgr_config *rtr_config;
130static struct list *cache_list;
131static int rtr_is_running;
132static int rpki_debug;
133static unsigned int polling_period;
134static unsigned int expire_interval;
135static unsigned int retry_interval;
136static unsigned int timeout;
137static unsigned int initial_synchronisation_timeout;
138
139static struct cmd_node rpki_node = {RPKI_NODE, "%s(config-rpki)# ", 1};
996c9314
LB
140static struct route_map_rule_cmd route_match_rpki_cmd = {
141 "rpki", route_match, route_match_compile, route_match_free};
dabecd7c
MR
142
143static void *malloc_wrapper(size_t size)
144{
145 return XMALLOC(MTYPE_BGP_RPKI_CACHE, size);
146}
147
148static void *realloc_wrapper(void *ptr, size_t size)
149{
150 return XREALLOC(MTYPE_BGP_RPKI_CACHE, ptr, size);
151}
152
153static void free_wrapper(void *ptr)
154{
155 XFREE(MTYPE_BGP_RPKI_CACHE, ptr);
156}
157
158static int rpki_validate_prefix(struct peer *peer, struct attr *attr,
159 struct prefix *prefix);
160
161static route_map_result_t route_match(void *rule, struct prefix *prefix,
996c9314 162 route_map_object_t type, void *object)
dabecd7c
MR
163{
164 int *rpki_status = rule;
165 struct bgp_info *bgp_info;
166
167 if (type == RMAP_BGP) {
168 bgp_info = object;
169
170 if (rpki_validate_prefix(bgp_info->peer, bgp_info->attr, prefix)
171 == *rpki_status) {
172 return RMAP_MATCH;
173 }
174 }
175 return RMAP_NOMATCH;
176}
177
178static void *route_match_compile(const char *arg)
179{
180 int *rpki_status;
181
182 rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(u_char));
183
184 if (strcmp(arg, "valid") == 0)
185 *rpki_status = RPKI_VALID;
186 else if (strcmp(arg, "invalid") == 0)
187 *rpki_status = RPKI_INVALID;
188 else
189 *rpki_status = RPKI_NOTFOUND;
190
191 return rpki_status;
192}
193
194static void route_match_free(void *rule)
195{
196 XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
197}
198
199static struct rtr_socket *create_rtr_socket(struct tr_socket *tr_socket)
200{
201 struct rtr_socket *rtr_socket =
202 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct rtr_socket));
203 rtr_socket->tr_socket = tr_socket;
204 return rtr_socket;
205}
206
207static struct cache *find_cache(const uint8_t preference)
208{
209 struct listnode *cache_node;
210 struct cache *cache;
211
212 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
213 if (cache->preference == preference)
214 return cache;
215 }
216 return NULL;
217}
218
219static void print_record(const struct pfx_record *record, void *data)
220{
221 char ip[INET6_ADDRSTRLEN];
222 struct rpki_for_each_record_arg *arg = data;
223 struct vty *vty = arg->vty;
224
a220aec6 225 (*arg->prefix_amount)++;
dabecd7c
MR
226
227 lrtr_ip_addr_to_str(&record->prefix, ip, sizeof(ip));
228 vty_out(vty, "%-40s %3u - %3u %10u\n", ip, record->min_len,
229 record->max_len, record->asn);
230}
231
232static struct rtr_mgr_group *get_groups(void)
233{
234 struct listnode *cache_node;
235 struct rtr_mgr_group *rtr_mgr_groups;
236 struct cache *cache;
237
238 int group_count = listcount(cache_list);
239
240 if (group_count == 0)
241 return NULL;
242
243 rtr_mgr_groups = XMALLOC(MTYPE_BGP_RPKI_CACHE_GROUP,
244 group_count * sizeof(struct rtr_mgr_group));
245
246 size_t i = 0;
247
248 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
249 rtr_mgr_groups[i].sockets = &cache->rtr_socket;
250 rtr_mgr_groups[i].sockets_len = 1;
251 rtr_mgr_groups[i].preference = cache->preference;
252
253 if (cache->type == TCP)
254 tr_tcp_init(cache->tr_config.tcp_config,
255 cache->tr_socket);
acd4a9f4 256#if defined(FOUND_SSH)
dabecd7c
MR
257 else
258 tr_ssh_init(cache->tr_config.ssh_config,
259 cache->tr_socket);
acd4a9f4 260#endif
dabecd7c
MR
261
262 i++;
263 }
264
265 return rtr_mgr_groups;
266}
267
268inline int is_synchronized(void)
269{
270 return rtr_is_running && rtr_mgr_conf_in_sync(rtr_config);
271}
272
273inline int is_running(void)
274{
275 return rtr_is_running;
276}
277
278static int bgp_rpki_init(struct thread_master *master)
279{
280 rpki_debug = 0;
281 rtr_is_running = 0;
282
283 cache_list = list_new();
996c9314 284 cache_list->del = (void (*)(void *)) & free_cache;
dabecd7c
MR
285
286 polling_period = POLLING_PERIOD_DEFAULT;
287 expire_interval = EXPIRE_INTERVAL_DEFAULT;
288 retry_interval = RETRY_INTERVAL_DEFAULT;
289 timeout = TIMEOUT_DEFAULT;
290 initial_synchronisation_timeout =
291 INITIAL_SYNCHRONISATION_TIMEOUT_DEFAULT;
292 install_cli_commands();
293 return 0;
294}
295
296static int bgp_rpki_fini(void)
297{
298 stop();
299 list_delete_and_null(&cache_list);
300
301 return 0;
302}
303
304static int bgp_rpki_module_init(void)
305{
996c9314 306 lrtr_set_alloc_functions(malloc_wrapper, realloc_wrapper, free_wrapper);
dabecd7c
MR
307
308 hook_register(frr_late_init, bgp_rpki_init);
309 hook_register(frr_early_fini, &bgp_rpki_fini);
310
311 return 0;
312}
313
314static int start(void)
315{
316 unsigned int waiting_time = 0;
317 int ret;
318
319 if (list_isempty(cache_list)) {
320 RPKI_DEBUG(
321 "No caches were found in config. Prefix validation is off.");
322 return ERROR;
323 }
324 RPKI_DEBUG("Init rtr_mgr.");
325 int groups_len = listcount(cache_list);
326 struct rtr_mgr_group *groups = get_groups();
327
328 ret = rtr_mgr_init(&rtr_config, groups, groups_len, polling_period,
996c9314
LB
329 expire_interval, retry_interval, NULL, NULL, NULL,
330 NULL);
dabecd7c
MR
331 if (ret == RTR_ERROR) {
332 RPKI_DEBUG("Init rtr_mgr failed.");
333 return ERROR;
334 }
335
336 RPKI_DEBUG("Starting rtr_mgr.");
337 ret = rtr_mgr_start(rtr_config);
338 if (ret == RTR_ERROR) {
339 RPKI_DEBUG("Starting rtr_mgr failed.");
340 rtr_mgr_free(rtr_config);
341 return ERROR;
342 }
343 rtr_is_running = 1;
344 RPKI_DEBUG("Waiting for rtr connection to synchronize.");
345 while (waiting_time++ <= initial_synchronisation_timeout) {
346 if (rtr_mgr_conf_in_sync(rtr_config))
347 break;
348
349 sleep(1);
350 }
351 if (rtr_mgr_conf_in_sync(rtr_config)) {
352 RPKI_DEBUG("Got synchronisation with at least one RPKI cache!");
353 } else {
354 RPKI_DEBUG(
355 "Timeout expired! Proceeding without RPKI validation data.");
356 }
357
358 XFREE(MTYPE_BGP_RPKI_CACHE_GROUP, groups);
359
360 return SUCCESS;
361}
362
363static void stop(void)
364{
365 if (rtr_is_running) {
366 rtr_mgr_stop(rtr_config);
367 rtr_mgr_free(rtr_config);
368 rtr_is_running = 0;
369 }
370}
371
372static int reset(bool force)
373{
374 if (rtr_is_running && !force)
375 return SUCCESS;
376
377 RPKI_DEBUG("Resetting RPKI Session");
378 stop();
379 return start();
380}
381
382static struct rtr_mgr_group *get_connected_group(void)
383{
384 if (list_isempty(cache_list))
385 return NULL;
386
387 return rtr_mgr_get_first_group(rtr_config);
388}
389
390static void print_prefix_table(struct vty *vty)
391{
392 struct rpki_for_each_record_arg arg;
393
394 unsigned int number_of_ipv4_prefixes = 0;
395 unsigned int number_of_ipv6_prefixes = 0;
396 struct rtr_mgr_group *group = get_connected_group();
397
398 arg.vty = vty;
399
400 if (!group)
401 return;
402
403 struct pfx_table *pfx_table = group->sockets[0]->pfx_table;
404
405 vty_out(vty, "RPKI/RTR prefix table\n");
406 vty_out(vty, "%-40s %s %s\n", "Prefix", "Prefix Length", "Origin-AS");
407
408 arg.prefix_amount = &number_of_ipv4_prefixes;
409 pfx_table_for_each_ipv4_record(pfx_table, print_record, &arg);
410
411 arg.prefix_amount = &number_of_ipv6_prefixes;
412 pfx_table_for_each_ipv6_record(pfx_table, print_record, &arg);
413
414 vty_out(vty, "Number of IPv4 Prefixes: %u\n", number_of_ipv4_prefixes);
415 vty_out(vty, "Number of IPv6 Prefixes: %u\n", number_of_ipv6_prefixes);
416}
417
418static int rpki_validate_prefix(struct peer *peer, struct attr *attr,
419 struct prefix *prefix)
420{
421 struct assegment *as_segment;
422 as_t as_number = 0;
423 struct lrtr_ip_addr ip_addr_prefix;
424 enum pfxv_state result;
425 char buf[BUFSIZ];
426 const char *prefix_string;
427
428 if (!is_synchronized())
429 return 0;
430
431 // No aspath means route comes from iBGP
432 if (!attr->aspath || !attr->aspath->segments) {
433 // Set own as number
434 as_number = peer->bgp->as;
435 } else {
436 as_segment = attr->aspath->segments;
437 // Find last AsSegment
438 while (as_segment->next)
439 as_segment = as_segment->next;
440
441 if (as_segment->type == AS_SEQUENCE) {
442 // Get rightmost asn
443 as_number = as_segment->as[as_segment->length - 1];
996c9314
LB
444 } else if (as_segment->type == AS_CONFED_SEQUENCE
445 || as_segment->type == AS_CONFED_SET) {
dabecd7c
MR
446 // Set own as number
447 as_number = peer->bgp->as;
448 } else {
449 // RFC says: "Take distinguished value NONE as asn"
450 // which means state is unknown
451 return RPKI_NOTFOUND;
452 }
453 }
454
455 // Get the prefix in requested format
456 switch (prefix->family) {
457 case AF_INET:
458 ip_addr_prefix.ver = LRTR_IPV4;
459 ip_addr_prefix.u.addr4.addr = ntohl(prefix->u.prefix4.s_addr);
460 break;
461
462#ifdef HAVE_IPV6
463 case AF_INET6:
464 ip_addr_prefix.ver = LRTR_IPV6;
465 ipv6_addr_to_host_byte_order(prefix->u.prefix6.s6_addr32,
466 ip_addr_prefix.u.addr6.addr);
467 break;
468#endif /* HAVE_IPV6 */
469
470 default:
471 return 0;
472 }
473
474 // Do the actual validation
475 rtr_mgr_validate(rtr_config, as_number, &ip_addr_prefix,
476 prefix->prefixlen, &result);
477
478 // Print Debug output
479 prefix_string =
480 inet_ntop(prefix->family, &prefix->u.prefix, buf, BUFSIZ);
481 switch (result) {
482 case BGP_PFXV_STATE_VALID:
483 RPKI_DEBUG(
484 "Validating Prefix %s/%hhu from asn %u Result: VALID",
485 prefix_string, prefix->prefixlen, as_number);
486 return RPKI_VALID;
487 case BGP_PFXV_STATE_NOT_FOUND:
488 RPKI_DEBUG(
489 "Validating Prefix %s/%hhu from asn %u Result: NOT FOUND",
490 prefix_string, prefix->prefixlen, as_number);
491 return RPKI_NOTFOUND;
492 case BGP_PFXV_STATE_INVALID:
493 RPKI_DEBUG(
494 "Validating Prefix %s/%hhu from asn %u Result: INVALID",
495 prefix_string, prefix->prefixlen, as_number);
496 return RPKI_INVALID;
497 default:
498 RPKI_DEBUG(
499 "Validating Prefix %s/%hhu from asn %u Result: CANNOT VALIDATE",
500 prefix_string, prefix->prefixlen, as_number);
501 break;
502 }
503 return 0;
504}
505
506static int add_cache(struct cache *cache)
507{
508 uint8_t preference = cache->preference;
509 struct rtr_mgr_group group;
510
511 group.preference = preference;
512 group.sockets_len = 1;
513 group.sockets = &cache->rtr_socket;
514
515 listnode_add(cache_list, cache);
516
996c9314
LB
517 if (rtr_is_running
518 && rtr_mgr_add_group(rtr_config, &group) != RTR_SUCCESS) {
dabecd7c
MR
519 return ERROR;
520 }
521
522 return SUCCESS;
523}
524
996c9314 525static int add_tcp_cache(const char *host, const char *port,
dabecd7c
MR
526 const uint8_t preference)
527{
528 struct rtr_socket *rtr_socket;
529 struct tr_tcp_config *tcp_config =
530 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_tcp_config));
531 struct tr_socket *tr_socket =
532 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
533 struct cache *cache =
534 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
535
536 tcp_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
537 tcp_config->port = XSTRDUP(MTYPE_BGP_RPKI_CACHE, port);
538 tcp_config->bindaddr = NULL;
539
540 rtr_socket = create_rtr_socket(tr_socket);
541
542 cache->type = TCP;
543 cache->tr_socket = tr_socket;
544 cache->tr_config.tcp_config = tcp_config;
545 cache->rtr_socket = rtr_socket;
546 cache->preference = preference;
547
548 return add_cache(cache);
549}
550
551#if defined(FOUND_SSH)
996c9314
LB
552static int add_ssh_cache(const char *host, const unsigned int port,
553 const char *username, const char *client_privkey_path,
dabecd7c
MR
554 const char *client_pubkey_path,
555 const char *server_pubkey_path,
556 const uint8_t preference)
557{
558 struct tr_ssh_config *ssh_config =
559 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_ssh_config));
560 struct cache *cache =
561 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct cache));
562 struct tr_socket *tr_socket =
563 XMALLOC(MTYPE_BGP_RPKI_CACHE, sizeof(struct tr_socket));
564 struct rtr_socket *rtr_socket;
565
566 ssh_config->port = port;
567 ssh_config->host = XSTRDUP(MTYPE_BGP_RPKI_CACHE, host);
568 ssh_config->bindaddr = NULL;
569
570 ssh_config->username = XSTRDUP(MTYPE_BGP_RPKI_CACHE, username);
996c9314
LB
571 ssh_config->client_privkey_path =
572 XSTRDUP(MTYPE_BGP_RPKI_CACHE, client_privkey_path);
dabecd7c
MR
573 ssh_config->server_hostkey_path =
574 XSTRDUP(MTYPE_BGP_RPKI_CACHE, server_pubkey_path);
575
576 rtr_socket = create_rtr_socket(tr_socket);
577
578 cache->type = SSH;
579 cache->tr_socket = tr_socket;
580 cache->tr_config.ssh_config = ssh_config;
581 cache->rtr_socket = rtr_socket;
582 cache->preference = preference;
583
584 return add_cache(cache);
585}
586#endif
587
588static void free_cache(struct cache *cache)
589{
590 if (cache->type == TCP) {
996c9314
LB
591 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->host);
592 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config->port);
dabecd7c
MR
593 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.tcp_config);
594 }
595#if defined(FOUND_SSH)
596 else {
996c9314 597 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config->host);
dabecd7c
MR
598 XFREE(MTYPE_BGP_RPKI_CACHE,
599 cache->tr_config.ssh_config->username);
600 XFREE(MTYPE_BGP_RPKI_CACHE,
601 cache->tr_config.ssh_config->client_privkey_path);
602 XFREE(MTYPE_BGP_RPKI_CACHE,
603 cache->tr_config.ssh_config->server_hostkey_path);
604 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_config.ssh_config);
605 }
606#endif
607 XFREE(MTYPE_BGP_RPKI_CACHE, cache->tr_socket);
608 XFREE(MTYPE_BGP_RPKI_CACHE, cache->rtr_socket);
609 XFREE(MTYPE_BGP_RPKI_CACHE, cache);
610}
611
612static int config_write(struct vty *vty)
613{
614 struct listnode *cache_node;
615 struct cache *cache;
616
617 if (listcount(cache_list)) {
618 if (rpki_debug)
619 vty_out(vty, "debug rpki\n");
620
621 vty_out(vty, "!\n");
622 vty_out(vty, "rpki\n");
623 vty_out(vty, " rpki polling_period %d\n", polling_period);
624 vty_out(vty, " rpki timeout %d\n", timeout);
625 vty_out(vty, " rpki initial-synchronisation-timeout %d\n",
626 initial_synchronisation_timeout);
627 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
628 switch (cache->type) {
629 struct tr_tcp_config *tcp_config;
acd4a9f4 630#if defined(FOUND_SSH)
dabecd7c 631 struct tr_ssh_config *ssh_config;
acd4a9f4 632#endif
dabecd7c
MR
633 case TCP:
634 tcp_config = cache->tr_config.tcp_config;
996c9314
LB
635 vty_out(vty, " rpki cache %s %s ",
636 tcp_config->host, tcp_config->port);
dabecd7c
MR
637 break;
638#if defined(FOUND_SSH)
639 case SSH:
640 ssh_config = cache->tr_config.ssh_config;
996c9314
LB
641 vty_out(vty, " rpki cache %s %u %s %s %s ",
642 ssh_config->host, ssh_config->port,
dabecd7c
MR
643 ssh_config->username,
644 ssh_config->client_privkey_path,
996c9314 645 ssh_config->server_hostkey_path != NULL
dabecd7c
MR
646 ? ssh_config
647 ->server_hostkey_path
648 : " ");
649 break;
650#endif
651 default:
652 break;
653 }
654
655 vty_out(vty, "preference %hhu\n", cache->preference);
656 }
657 vty_out(vty, " exit\n");
658 return 1;
659 } else {
660 return 0;
661 }
662}
663
664DEFUN_NOSH (rpki,
665 rpki_cmd,
666 "rpki",
667 "Enable rpki and enter rpki configuration mode\n")
668{
669 vty->node = RPKI_NODE;
670 return CMD_SUCCESS;
671}
672
673DEFUN (bgp_rpki_start,
674 bgp_rpki_start_cmd,
675 "rpki start",
676 RPKI_OUTPUT_STRING
677 "start rpki support\n")
678{
679 if (listcount(cache_list) == 0)
996c9314
LB
680 vty_out(vty,
681 "Could not start rpki because no caches are configured\n");
dabecd7c
MR
682
683 if (!is_running()) {
684 if (start() == ERROR) {
685 RPKI_DEBUG("RPKI failed to start");
686 return CMD_WARNING;
687 }
688 }
689 return CMD_SUCCESS;
690}
691
692DEFUN (bgp_rpki_stop,
693 bgp_rpki_stop_cmd,
694 "rpki stop",
695 RPKI_OUTPUT_STRING
696 "start rpki support\n")
697{
698 if (is_running())
699 stop();
700
701 return CMD_SUCCESS;
702}
703
704DEFPY (rpki_polling_period,
705 rpki_polling_period_cmd,
706 "rpki polling_period (1-86400)$pp",
707 RPKI_OUTPUT_STRING
708 "Set polling period\n"
709 "Polling period value\n")
710{
711 polling_period = pp;
712 return CMD_SUCCESS;
713}
714
715DEFUN (no_rpki_polling_period,
716 no_rpki_polling_period_cmd,
717 "no rpki polling_period",
718 NO_STR
719 RPKI_OUTPUT_STRING
720 "Set polling period back to default\n")
721{
722 polling_period = POLLING_PERIOD_DEFAULT;
723 return CMD_SUCCESS;
724}
725
726DEFPY (rpki_expire_interval,
727 rpki_expire_interval_cmd,
728 "rpki expire_interval (600-172800)$tmp",
729 RPKI_OUTPUT_STRING
730 "Set expire interval\n"
731 "Expire interval value\n")
732{
733 if (tmp >= polling_period) {
734 expire_interval = tmp;
735 return CMD_SUCCESS;
736 }
737
738 vty_out(vty, "%% Expiry interval must be polling period or larger\n");
739 return CMD_WARNING_CONFIG_FAILED;
740}
741
742DEFUN (no_rpki_expire_interval,
743 no_rpki_expire_interval_cmd,
744 "no rpki expire_interval",
745 NO_STR
746 RPKI_OUTPUT_STRING
747 "Set expire interval back to default\n")
748{
749 expire_interval = polling_period * 2;
750 return CMD_SUCCESS;
751}
752
753DEFPY (rpki_retry_interval,
754 rpki_retry_interval_cmd,
755 "rpki retry_interval (1-7200)$tmp",
756 RPKI_OUTPUT_STRING
757 "Set retry interval\n"
758 "retry interval value\n")
759{
760 retry_interval = tmp;
761 return CMD_SUCCESS;
762}
763
764DEFUN (no_rpki_retry_interval,
765 no_rpki_retry_interval_cmd,
766 "no rpki retry_interval",
767 NO_STR
768 RPKI_OUTPUT_STRING
769 "Set retry interval back to default\n")
770{
771 retry_interval = RETRY_INTERVAL_DEFAULT;
772 return CMD_SUCCESS;
773}
774
775DEFPY (rpki_timeout,
776 rpki_timeout_cmd,
777 "rpki timeout (1-4294967295)$to_arg",
778 RPKI_OUTPUT_STRING
779 "Set timeout\n"
780 "Timeout value\n")
781{
782 timeout = to_arg;
783 return CMD_SUCCESS;
784}
785
786DEFUN (no_rpki_timeout,
787 no_rpki_timeout_cmd,
788 "no rpki timeout",
789 NO_STR
790 RPKI_OUTPUT_STRING
791 "Set timeout back to default\n")
792{
793 timeout = TIMEOUT_DEFAULT;
794 return CMD_SUCCESS;
795}
796
797DEFPY (rpki_synchronisation_timeout,
798 rpki_synchronisation_timeout_cmd,
799 "rpki initial-synchronisation-timeout (1-4294967295)$ito_arg",
800 RPKI_OUTPUT_STRING
801 "Set a timeout for the initial synchronisation of prefix validation data\n"
802 "Timeout value\n")
803{
804 initial_synchronisation_timeout = ito_arg;
805 return CMD_SUCCESS;
806}
807
808DEFUN (no_rpki_synchronisation_timeout,
809 no_rpki_synchronisation_timeout_cmd,
810 "no rpki initial-synchronisation-timeout",
811 NO_STR
812 RPKI_OUTPUT_STRING
813 "Set the initial synchronisation timeout back to default (30 sec.)\n")
814{
815 initial_synchronisation_timeout =
816 INITIAL_SYNCHRONISATION_TIMEOUT_DEFAULT;
817 return CMD_SUCCESS;
818}
819
820DEFPY (rpki_cache,
821 rpki_cache_cmd,
822 "rpki cache <A.B.C.D|WORD>"
823 "<TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY SSH_PUBKEY [SERVER_PUBKEY]> "
824 "preference (1-255)",
825 RPKI_OUTPUT_STRING
826 "Install a cache server to current group\n"
827 "IP address of cache server\n Hostname of cache server\n"
828 "TCP port number\n"
829 "SSH port number\n"
830 "SSH user name\n"
831 "Path to own SSH private key\n"
832 "Path to own SSH public key\n"
833 "Path to Public key of cache server\n"
834 "Preference of the cache server\n"
835 "Preference value\n")
836{
837 int return_value = SUCCESS;
838
839 // use ssh connection
840 if (ssh_uname) {
841#if defined(FOUND_SSH)
996c9314
LB
842 return_value =
843 add_ssh_cache(cache, sshport, ssh_uname, ssh_privkey,
844 ssh_pubkey, server_pubkey, preference);
dabecd7c
MR
845#else
846 vty_out(vty,
847 "ssh sockets are not supported. "
848 "Please recompile rtrlib and frr with ssh support. "
849 "If you want to use it");
850#endif
851 } else { // use tcp connection
852 return_value = add_tcp_cache(cache, tcpport, preference);
853 }
854
855 if (return_value == ERROR) {
856 vty_out(vty, "Could not create new rpki cache\n");
857 return CMD_WARNING;
858 }
859
860 return CMD_SUCCESS;
861}
862
863DEFPY (no_rpki_cache,
864 no_rpki_cache_cmd,
865 "no rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport> preference (1-255)$preference",
866 NO_STR
867 RPKI_OUTPUT_STRING
868 "Remove a cache server\n"
869 "IP address of cache server\n Hostname of cache server\n"
870 "TCP port number\n"
871 "SSH port number\n"
872 "Preference of the cache server\n"
873 "Preference value\n")
874{
875 struct cache *cache_p = find_cache(preference);
876
877 if (!cache) {
878 vty_out(vty, "Could not find cache %ld\n", preference);
879 return CMD_WARNING;
880 }
881
882 if (rtr_is_running) {
883 if (rtr_mgr_remove_group(rtr_config, preference) == RTR_ERROR) {
884 vty_out(vty, "Could not remove cache %ld", preference);
885 if (listcount(cache_list) == 1)
886 vty_out(vty, " because it is the last cache");
887
888 vty_out(vty, "\n");
889 return CMD_WARNING;
890 }
891 }
892
893 listnode_delete(cache_list, cache_p);
894 free_cache(cache_p);
895
896 return CMD_SUCCESS;
897}
898
899DEFUN (show_rpki_prefix_table,
900 show_rpki_prefix_table_cmd,
901 "show rpki prefix-table",
902 SHOW_STR
903 RPKI_OUTPUT_STRING
08f9cfb8 904 "Show validated prefixes which were received from RPKI Cache\n")
dabecd7c
MR
905{
906 struct listnode *cache_node;
907 struct cache *cache;
908
909 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
996c9314 910 vty_out(vty, "host: %s port: %s\n",
dabecd7c
MR
911 cache->tr_config.tcp_config->host,
912 cache->tr_config.tcp_config->port);
913 }
914 if (is_synchronized())
915 print_prefix_table(vty);
916 else
917 vty_out(vty, "No connection to RPKI cache server.\n");
918
919 return CMD_SUCCESS;
920}
921
922DEFUN (show_rpki_cache_server,
923 show_rpki_cache_server_cmd,
924 "show rpki cache-server",
925 SHOW_STR
926 RPKI_OUTPUT_STRING
08f9cfb8 927 "SHOW configured cache server\n")
dabecd7c
MR
928{
929 struct listnode *cache_node;
930 struct cache *cache;
931
932 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
996c9314 933 vty_out(vty, "host: %s port: %s\n",
dabecd7c
MR
934 cache->tr_config.tcp_config->host,
935 cache->tr_config.tcp_config->port);
936 }
937
938 return CMD_SUCCESS;
939}
940
941DEFUN (show_rpki_cache_connection,
942 show_rpki_cache_connection_cmd,
943 "show rpki cache-connection",
944 SHOW_STR
945 RPKI_OUTPUT_STRING
08f9cfb8 946 "Show to which RPKI Cache Servers we have a connection\n")
dabecd7c
MR
947{
948 if (is_synchronized()) {
949 struct listnode *cache_node;
950 struct cache *cache;
951 struct rtr_mgr_group *group = get_connected_group();
952
953 if (!group) {
954 vty_out(vty, "Cannot find a connected group.\n");
955 return CMD_SUCCESS;
956 }
957 vty_out(vty, "Connected to group %d\n", group->preference);
996c9314 958 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
dabecd7c
MR
959 if (cache->preference == group->preference) {
960 struct tr_tcp_config *tcp_config;
acd4a9f4 961#if defined(FOUND_SSH)
dabecd7c 962 struct tr_ssh_config *ssh_config;
acd4a9f4 963#endif
dabecd7c
MR
964
965 switch (cache->type) {
966 case TCP:
967 tcp_config =
996c9314 968 cache->tr_config.tcp_config;
dabecd7c
MR
969 vty_out(vty,
970 "rpki tcp cache %s %s pref %hhu\n",
971 tcp_config->host,
972 tcp_config->port,
973 cache->preference);
974 break;
975
976#if defined(FOUND_SSH)
977 case SSH:
978 ssh_config =
996c9314 979 cache->tr_config.ssh_config;
dabecd7c
MR
980 vty_out(vty,
981 "rpki ssh cache %s %u pref %hhu\n",
982 ssh_config->host,
983 ssh_config->port,
984 cache->preference);
985 break;
986#endif
987
988 default:
989 break;
990 }
991 }
992 }
993 } else {
994 vty_out(vty, "No connection to RPKI cache server.\n");
995 }
996
997 return CMD_SUCCESS;
998}
999
1000DEFUN_NOSH (rpki_exit,
1001 rpki_exit_cmd,
1002 "exit",
08f9cfb8 1003 "Exit rpki configuration and restart rpki session\n")
dabecd7c
MR
1004{
1005 int ret = reset(false);
1006
1007 vty->node = CONFIG_NODE;
1008 return ret == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1009}
1010
1011DEFUN_NOSH (rpki_quit,
1012 rpki_quit_cmd,
1013 "quit",
08f9cfb8 1014 "Exit rpki configuration mode\n")
dabecd7c
MR
1015{
1016 return rpki_exit(self, vty, argc, argv);
1017}
1018
1019DEFUN_NOSH (rpki_end,
1020 rpki_end_cmd,
1021 "end",
08f9cfb8 1022 "End rpki configuration, restart rpki session and change to enable mode.\n")
dabecd7c
MR
1023{
1024 int ret = reset(false);
1025
1026 vty_config_unlock(vty);
1027 vty->node = ENABLE_NODE;
1028 return ret == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1029}
1030
1031DEFUN (rpki_reset,
1032 rpki_reset_cmd,
1033 "rpki reset",
1034 RPKI_OUTPUT_STRING
1035 "reset rpki\n")
1036{
1037 return reset(true) == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1038}
1039
1040DEFUN (debug_rpki,
1041 debug_rpki_cmd,
1042 "debug rpki",
1043 DEBUG_STR
08f9cfb8 1044 "Enable debugging for rpki\n")
dabecd7c
MR
1045{
1046 rpki_debug = 1;
1047 return CMD_SUCCESS;
1048}
1049
1050DEFUN (no_debug_rpki,
1051 no_debug_rpki_cmd,
1052 "no debug rpki",
1053 NO_STR
1054 DEBUG_STR
08f9cfb8 1055 "Disable debugging for rpki\n")
dabecd7c
MR
1056{
1057 rpki_debug = 0;
1058 return CMD_SUCCESS;
1059}
1060
1061DEFUN (match_rpki,
1062 match_rpki_cmd,
1063 "match rpki <valid|invalid|notfound>",
1064 MATCH_STR
1065 RPKI_OUTPUT_STRING
1066 "Valid prefix\n"
1067 "Invalid prefix\n"
1068 "Prefix not found\n")
1069{
1070 VTY_DECLVAR_CONTEXT(route_map_index, index);
1071 int ret;
1072
1073 ret = route_map_add_match(index, "rpki", argv[2]->arg);
1074 if (ret) {
1075 switch (ret) {
1076 case RMAP_RULE_MISSING:
1077 vty_out(vty, "%% BGP Can't find rule.\n");
1078 return CMD_WARNING_CONFIG_FAILED;
1079 case RMAP_COMPILE_ERROR:
1080 vty_out(vty, "%% BGP Argument is malformed.\n");
1081 return CMD_WARNING_CONFIG_FAILED;
1082 }
1083 }
1084 return CMD_SUCCESS;
1085}
1086
1087DEFUN (no_match_rpki,
1088 no_match_rpki_cmd,
1089 "no match rpki <valid|invalid|notfound>",
1090 NO_STR
1091 MATCH_STR
1092 RPKI_OUTPUT_STRING
1093 "Valid prefix\n"
1094 "Invalid prefix\n"
1095 "Prefix not found\n")
1096{
1097 VTY_DECLVAR_CONTEXT(route_map_index, index);
1098 int ret;
1099
1100 ret = route_map_delete_match(index, "rpki", argv[3]->arg);
1101 if (ret) {
1102 switch (ret) {
1103 case RMAP_RULE_MISSING:
1104 vty_out(vty, "%% BGP Can't find rule.\n");
1105 break;
1106 case RMAP_COMPILE_ERROR:
1107 vty_out(vty, "%% BGP Argument is malformed.\n");
1108 break;
1109 }
1110 return CMD_WARNING_CONFIG_FAILED;
1111 }
1112
1113 return CMD_SUCCESS;
1114}
1115
1116static void overwrite_exit_commands(void)
1117{
1118 unsigned int i;
1119 vector cmd_vector = rpki_node.cmd_vector;
1120
1121 for (i = 0; i < cmd_vector->active; ++i) {
1122 struct cmd_element *cmd = vector_lookup(cmd_vector, i);
1123
996c9314
LB
1124 if (strcmp(cmd->string, "exit") == 0
1125 || strcmp(cmd->string, "quit") == 0
1126 || strcmp(cmd->string, "end") == 0) {
dabecd7c
MR
1127 uninstall_element(RPKI_NODE, cmd);
1128 }
1129 }
1130
1131 install_element(RPKI_NODE, &rpki_exit_cmd);
1132 install_element(RPKI_NODE, &rpki_quit_cmd);
1133 install_element(RPKI_NODE, &rpki_end_cmd);
1134}
1135
1136static void install_cli_commands(void)
1137{
996c9314 1138 // TODO: make config write work
dabecd7c
MR
1139 install_node(&rpki_node, &config_write);
1140 install_default(RPKI_NODE);
1141 overwrite_exit_commands();
1142 install_element(CONFIG_NODE, &rpki_cmd);
1143 install_element(VIEW_NODE, &rpki_cmd);
1144
1145 install_element(ENABLE_NODE, &bgp_rpki_start_cmd);
1146 install_element(ENABLE_NODE, &bgp_rpki_stop_cmd);
1147
1148 /* Install rpki reset command */
1149 install_element(RPKI_NODE, &rpki_reset_cmd);
1150
1151 /* Install rpki polling period commands */
1152 install_element(RPKI_NODE, &rpki_polling_period_cmd);
1153 install_element(RPKI_NODE, &no_rpki_polling_period_cmd);
1154
1155 /* Install rpki expire interval commands */
1156 install_element(RPKI_NODE, &rpki_expire_interval_cmd);
1157 install_element(RPKI_NODE, &no_rpki_expire_interval_cmd);
1158
1159 /* Install rpki retry interval commands */
1160 install_element(RPKI_NODE, &rpki_retry_interval_cmd);
1161 install_element(RPKI_NODE, &no_rpki_retry_interval_cmd);
1162
1163 /* Install rpki timeout commands */
1164 install_element(RPKI_NODE, &rpki_timeout_cmd);
1165 install_element(RPKI_NODE, &no_rpki_timeout_cmd);
1166
1167 /* Install rpki synchronisation timeout commands */
1168 install_element(RPKI_NODE, &rpki_synchronisation_timeout_cmd);
1169 install_element(RPKI_NODE, &no_rpki_synchronisation_timeout_cmd);
1170
1171 /* Install rpki cache commands */
1172 install_element(RPKI_NODE, &rpki_cache_cmd);
1173 install_element(RPKI_NODE, &no_rpki_cache_cmd);
1174
1175 /* Install show commands */
1176 install_element(ENABLE_NODE, &show_rpki_prefix_table_cmd);
1177 install_element(ENABLE_NODE, &show_rpki_cache_connection_cmd);
1178 install_element(ENABLE_NODE, &show_rpki_cache_server_cmd);
1179
1180 /* Install debug commands */
1181 install_element(CONFIG_NODE, &debug_rpki_cmd);
1182 install_element(ENABLE_NODE, &debug_rpki_cmd);
1183 install_element(CONFIG_NODE, &no_debug_rpki_cmd);
1184 install_element(ENABLE_NODE, &no_debug_rpki_cmd);
1185
1186 /* Install route match */
1187 route_map_install_match(&route_match_rpki_cmd);
1188 install_element(RMAP_NODE, &match_rpki_cmd);
1189 install_element(RMAP_NODE, &no_match_rpki_cmd);
1190}
1191
1192FRR_MODULE_SETUP(.name = "bgpd_rpki", .version = "0.3.6",
1193 .description = "Enable RPKI support for FRR.",
996c9314 1194 .init = bgp_rpki_module_init)