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