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