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