]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_rpki.c
Merge pull request #2624 from donaldsharp/PIM_ZOMILY_ZOM
[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{
867 int return_value = SUCCESS;
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
MR
875#else
876 vty_out(vty,
877 "ssh sockets are not supported. "
878 "Please recompile rtrlib and frr with ssh support. "
879 "If you want to use it");
880#endif
881 } else { // use tcp connection
882 return_value = add_tcp_cache(cache, tcpport, preference);
883 }
884
885 if (return_value == ERROR) {
886 vty_out(vty, "Could not create new rpki cache\n");
887 return CMD_WARNING;
888 }
889
890 return CMD_SUCCESS;
891}
892
893DEFPY (no_rpki_cache,
894 no_rpki_cache_cmd,
895 "no rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport> preference (1-255)$preference",
896 NO_STR
897 RPKI_OUTPUT_STRING
898 "Remove a cache server\n"
899 "IP address of cache server\n Hostname of cache server\n"
900 "TCP port number\n"
901 "SSH port number\n"
902 "Preference of the cache server\n"
903 "Preference value\n")
904{
905 struct cache *cache_p = find_cache(preference);
906
907 if (!cache) {
908 vty_out(vty, "Could not find cache %ld\n", preference);
909 return CMD_WARNING;
910 }
911
912 if (rtr_is_running) {
913 if (rtr_mgr_remove_group(rtr_config, preference) == RTR_ERROR) {
914 vty_out(vty, "Could not remove cache %ld", preference);
915 if (listcount(cache_list) == 1)
916 vty_out(vty, " because it is the last cache");
917
918 vty_out(vty, "\n");
919 return CMD_WARNING;
920 }
921 }
922
923 listnode_delete(cache_list, cache_p);
924 free_cache(cache_p);
925
926 return CMD_SUCCESS;
927}
928
929DEFUN (show_rpki_prefix_table,
930 show_rpki_prefix_table_cmd,
931 "show rpki prefix-table",
932 SHOW_STR
933 RPKI_OUTPUT_STRING
08f9cfb8 934 "Show validated prefixes which were received from RPKI Cache\n")
dabecd7c
MR
935{
936 struct listnode *cache_node;
937 struct cache *cache;
938
939 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
996c9314 940 vty_out(vty, "host: %s port: %s\n",
dabecd7c
MR
941 cache->tr_config.tcp_config->host,
942 cache->tr_config.tcp_config->port);
943 }
944 if (is_synchronized())
945 print_prefix_table(vty);
946 else
947 vty_out(vty, "No connection to RPKI cache server.\n");
948
949 return CMD_SUCCESS;
950}
951
952DEFUN (show_rpki_cache_server,
953 show_rpki_cache_server_cmd,
954 "show rpki cache-server",
955 SHOW_STR
956 RPKI_OUTPUT_STRING
08f9cfb8 957 "SHOW configured cache server\n")
dabecd7c
MR
958{
959 struct listnode *cache_node;
960 struct cache *cache;
961
962 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
996c9314 963 vty_out(vty, "host: %s port: %s\n",
dabecd7c
MR
964 cache->tr_config.tcp_config->host,
965 cache->tr_config.tcp_config->port);
966 }
967
968 return CMD_SUCCESS;
969}
970
971DEFUN (show_rpki_cache_connection,
972 show_rpki_cache_connection_cmd,
973 "show rpki cache-connection",
974 SHOW_STR
975 RPKI_OUTPUT_STRING
08f9cfb8 976 "Show to which RPKI Cache Servers we have a connection\n")
dabecd7c
MR
977{
978 if (is_synchronized()) {
979 struct listnode *cache_node;
980 struct cache *cache;
981 struct rtr_mgr_group *group = get_connected_group();
982
983 if (!group) {
984 vty_out(vty, "Cannot find a connected group.\n");
985 return CMD_SUCCESS;
986 }
987 vty_out(vty, "Connected to group %d\n", group->preference);
996c9314 988 for (ALL_LIST_ELEMENTS_RO(cache_list, cache_node, cache)) {
dabecd7c
MR
989 if (cache->preference == group->preference) {
990 struct tr_tcp_config *tcp_config;
acd4a9f4 991#if defined(FOUND_SSH)
dabecd7c 992 struct tr_ssh_config *ssh_config;
acd4a9f4 993#endif
dabecd7c
MR
994
995 switch (cache->type) {
996 case TCP:
997 tcp_config =
996c9314 998 cache->tr_config.tcp_config;
dabecd7c
MR
999 vty_out(vty,
1000 "rpki tcp cache %s %s pref %hhu\n",
1001 tcp_config->host,
1002 tcp_config->port,
1003 cache->preference);
1004 break;
1005
1006#if defined(FOUND_SSH)
1007 case SSH:
1008 ssh_config =
996c9314 1009 cache->tr_config.ssh_config;
dabecd7c
MR
1010 vty_out(vty,
1011 "rpki ssh cache %s %u pref %hhu\n",
1012 ssh_config->host,
1013 ssh_config->port,
1014 cache->preference);
1015 break;
1016#endif
1017
1018 default:
1019 break;
1020 }
1021 }
1022 }
1023 } else {
1024 vty_out(vty, "No connection to RPKI cache server.\n");
1025 }
1026
1027 return CMD_SUCCESS;
1028}
1029
1030DEFUN_NOSH (rpki_exit,
1031 rpki_exit_cmd,
1032 "exit",
08f9cfb8 1033 "Exit rpki configuration and restart rpki session\n")
dabecd7c
MR
1034{
1035 int ret = reset(false);
1036
1037 vty->node = CONFIG_NODE;
1038 return ret == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1039}
1040
1041DEFUN_NOSH (rpki_quit,
1042 rpki_quit_cmd,
1043 "quit",
08f9cfb8 1044 "Exit rpki configuration mode\n")
dabecd7c
MR
1045{
1046 return rpki_exit(self, vty, argc, argv);
1047}
1048
1049DEFUN_NOSH (rpki_end,
1050 rpki_end_cmd,
1051 "end",
08f9cfb8 1052 "End rpki configuration, restart rpki session and change to enable mode.\n")
dabecd7c
MR
1053{
1054 int ret = reset(false);
1055
1056 vty_config_unlock(vty);
1057 vty->node = ENABLE_NODE;
1058 return ret == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1059}
1060
1061DEFUN (rpki_reset,
1062 rpki_reset_cmd,
1063 "rpki reset",
1064 RPKI_OUTPUT_STRING
1065 "reset rpki\n")
1066{
1067 return reset(true) == SUCCESS ? CMD_SUCCESS : CMD_WARNING;
1068}
1069
1070DEFUN (debug_rpki,
1071 debug_rpki_cmd,
1072 "debug rpki",
1073 DEBUG_STR
08f9cfb8 1074 "Enable debugging for rpki\n")
dabecd7c
MR
1075{
1076 rpki_debug = 1;
1077 return CMD_SUCCESS;
1078}
1079
1080DEFUN (no_debug_rpki,
1081 no_debug_rpki_cmd,
1082 "no debug rpki",
1083 NO_STR
1084 DEBUG_STR
08f9cfb8 1085 "Disable debugging for rpki\n")
dabecd7c
MR
1086{
1087 rpki_debug = 0;
1088 return CMD_SUCCESS;
1089}
1090
1091DEFUN (match_rpki,
1092 match_rpki_cmd,
1093 "match rpki <valid|invalid|notfound>",
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_add_match(index, "rpki", argv[2]->arg);
1104 if (ret) {
1105 switch (ret) {
1106 case RMAP_RULE_MISSING:
1107 vty_out(vty, "%% BGP Can't find rule.\n");
1108 return CMD_WARNING_CONFIG_FAILED;
1109 case RMAP_COMPILE_ERROR:
1110 vty_out(vty, "%% BGP Argument is malformed.\n");
1111 return CMD_WARNING_CONFIG_FAILED;
1112 }
1113 }
1114 return CMD_SUCCESS;
1115}
1116
1117DEFUN (no_match_rpki,
1118 no_match_rpki_cmd,
1119 "no match rpki <valid|invalid|notfound>",
1120 NO_STR
1121 MATCH_STR
1122 RPKI_OUTPUT_STRING
1123 "Valid prefix\n"
1124 "Invalid prefix\n"
1125 "Prefix not found\n")
1126{
1127 VTY_DECLVAR_CONTEXT(route_map_index, index);
1128 int ret;
1129
1130 ret = route_map_delete_match(index, "rpki", argv[3]->arg);
1131 if (ret) {
1132 switch (ret) {
1133 case RMAP_RULE_MISSING:
1134 vty_out(vty, "%% BGP Can't find rule.\n");
1135 break;
1136 case RMAP_COMPILE_ERROR:
1137 vty_out(vty, "%% BGP Argument is malformed.\n");
1138 break;
1139 }
1140 return CMD_WARNING_CONFIG_FAILED;
1141 }
1142
1143 return CMD_SUCCESS;
1144}
1145
1146static void overwrite_exit_commands(void)
1147{
1148 unsigned int i;
1149 vector cmd_vector = rpki_node.cmd_vector;
1150
1151 for (i = 0; i < cmd_vector->active; ++i) {
1152 struct cmd_element *cmd = vector_lookup(cmd_vector, i);
1153
996c9314
LB
1154 if (strcmp(cmd->string, "exit") == 0
1155 || strcmp(cmd->string, "quit") == 0
1156 || strcmp(cmd->string, "end") == 0) {
dabecd7c
MR
1157 uninstall_element(RPKI_NODE, cmd);
1158 }
1159 }
1160
1161 install_element(RPKI_NODE, &rpki_exit_cmd);
1162 install_element(RPKI_NODE, &rpki_quit_cmd);
1163 install_element(RPKI_NODE, &rpki_end_cmd);
1164}
1165
1166static void install_cli_commands(void)
1167{
996c9314 1168 // TODO: make config write work
dabecd7c
MR
1169 install_node(&rpki_node, &config_write);
1170 install_default(RPKI_NODE);
1171 overwrite_exit_commands();
1172 install_element(CONFIG_NODE, &rpki_cmd);
1173 install_element(VIEW_NODE, &rpki_cmd);
1174
1175 install_element(ENABLE_NODE, &bgp_rpki_start_cmd);
1176 install_element(ENABLE_NODE, &bgp_rpki_stop_cmd);
1177
1178 /* Install rpki reset command */
1179 install_element(RPKI_NODE, &rpki_reset_cmd);
1180
1181 /* Install rpki polling period commands */
1182 install_element(RPKI_NODE, &rpki_polling_period_cmd);
1183 install_element(RPKI_NODE, &no_rpki_polling_period_cmd);
1184
1185 /* Install rpki expire interval commands */
1186 install_element(RPKI_NODE, &rpki_expire_interval_cmd);
1187 install_element(RPKI_NODE, &no_rpki_expire_interval_cmd);
1188
1189 /* Install rpki retry interval commands */
1190 install_element(RPKI_NODE, &rpki_retry_interval_cmd);
1191 install_element(RPKI_NODE, &no_rpki_retry_interval_cmd);
1192
1193 /* Install rpki timeout commands */
1194 install_element(RPKI_NODE, &rpki_timeout_cmd);
1195 install_element(RPKI_NODE, &no_rpki_timeout_cmd);
1196
1197 /* Install rpki synchronisation timeout commands */
1198 install_element(RPKI_NODE, &rpki_synchronisation_timeout_cmd);
1199 install_element(RPKI_NODE, &no_rpki_synchronisation_timeout_cmd);
1200
1201 /* Install rpki cache commands */
1202 install_element(RPKI_NODE, &rpki_cache_cmd);
1203 install_element(RPKI_NODE, &no_rpki_cache_cmd);
1204
1205 /* Install show commands */
1206 install_element(ENABLE_NODE, &show_rpki_prefix_table_cmd);
1207 install_element(ENABLE_NODE, &show_rpki_cache_connection_cmd);
1208 install_element(ENABLE_NODE, &show_rpki_cache_server_cmd);
1209
1210 /* Install debug commands */
1211 install_element(CONFIG_NODE, &debug_rpki_cmd);
1212 install_element(ENABLE_NODE, &debug_rpki_cmd);
1213 install_element(CONFIG_NODE, &no_debug_rpki_cmd);
1214 install_element(ENABLE_NODE, &no_debug_rpki_cmd);
1215
1216 /* Install route match */
1217 route_map_install_match(&route_match_rpki_cmd);
1218 install_element(RMAP_NODE, &match_rpki_cmd);
1219 install_element(RMAP_NODE, &no_match_rpki_cmd);
1220}
1221
1222FRR_MODULE_SETUP(.name = "bgpd_rpki", .version = "0.3.6",
1223 .description = "Enable RPKI support for FRR.",
996c9314 1224 .init = bgp_rpki_module_init)