Now to perform a standalone validation, the server must be disabled (server.enabled = false).
The ROAs in CSV format can be: printed to console (output.roa = '-'), printed to a file (output.roa = '<file>'), not printed (output.roa isn't configured).
'server.address' docs specify the scenario when no value is set to that argument.
4. [`root-except-ta`](#root-except-ta)
7. [`--shuffle-uris`](#--shuffle-uris)
8. [`--maximum-certificate-depth`](#--maximum-certificate-depth)
- 9. [`--server.address`](#--serveraddress)
- 10. [`--server.port`](#--serverport)
- 11. [`--server.backlog`](#--serverbacklog)
- 12. [`--server.validation-interval`](#--servervalidation-interval)
- 13. [`--slurm`](#--slurm)
- 14. [`--log.color-output`](#--logcolor-output)
- 15. [`--log.file-name-format`](#--logfile-name-format)
- 16. [`--configuration-file`](#--configuration-file)
- 17. [`rsync.program`](#rsyncprogram)
- 18. [`rsync.arguments-recursive`](#rsyncarguments-recursive)
- 19. [`rsync.arguments-flat`](#rsyncarguments-flat)
- 20. [`incidences`](#incidences)
+ 9. [`--server.enabled`](#--serverenabled)
+ 10. [`--server.address`](#--serveraddress)
+ 11. [`--server.port`](#--serverport)
+ 12. [`--server.backlog`](#--serverbacklog)
+ 13. [`--server.validation-interval`](#--servervalidation-interval)
+ 14. [`--slurm`](#--slurm)
+ 15. [`--log.color-output`](#--logcolor-output)
+ 16. [`--log.file-name-format`](#--logfile-name-format)
+ 17. [`--output.roa`](#--outputroa)
+ 18. [`--configuration-file`](#--configuration-file)
+ 19. [`rsync.program`](#rsyncprogram)
+ 20. [`rsync.arguments-recursive`](#rsyncarguments-recursive)
+ 21. [`rsync.arguments-flat`](#rsyncarguments-flat)
+ 22. [`incidences`](#incidences)
## Syntax
[--sync-strategy=off|strict|root|root-except-ta]
[--shuffle-uris]
[--maximum-certificate-depth=<unsigned integer>]
+ [--server.enabled=true|false]
[--server.address=<string>]
[--server.port=<string>]
[--server.backlog=<unsigned integer>]
[--slurm=<string>]
[--log.color-output]
[--log.file-name-format=global-url|local-path|file-name]
+ [--output.roa=<file>]
```
If an argument is declared more than once, the last one takes precedence:
Fort's tree traversal is actually iterative (not recursive), so there should be no risk of stack overflow, regardless of this value.
+### `--server.enabled`
+
+- **Type:** Boolean
+- **Availability:** `argv` and JSON
+- **Default:** true
+
+Enable or disable the RTR server.
+
+If set to `false`: the server is disabled, the rest of the `server.*` arguments are discarded, and Fort performs an in-place standalone RPKI validation.
+
### `--server.address`
- **Type:** String
Hostname or numeric host address the RTR server will be bound to. Must resolve to (or be) a bindable IP address. IPv4 and IPv6 are supported.
-If this field is omitted, Fort falls back to perform an in-place standalone RPKI validation. Presently, this is only intended for debugging.
+If this field is omitted, Fort will attempt to bind the server using the IP address `INADDR_ANY` (for an IPv4 address) or `IN6ADDR_ANY_INIT` (for an IPv6 address); see '`$ man getaddrinfo`'.
### `--server.port`
ERR: baz.cer: Certificate validation failed: certificate has expired
{% endhighlight %}
+### `--output.roa`
+
+- **Type:** String (Path to file)
+- **Availability:** `argv` and JSON
+
+File where the ROAs will be stored in CSV format.
+
+When the file is specified, its content will be removed to store the ROAs; if the file doesn't exists, it will be created. To print at console, use a hyphen `"-"`. If RTR server is enabled, then the ROAs will be printed every [`--server.validation-interval`](#--servervalidation-interval) secs.
+
+If a value isn't specified, then the ROAs aren't printed.
+
### `--configuration-file`
- **Type:** String (Path to file)
fort_SOURCES += cert_stack.h cert_stack.c
fort_SOURCES += clients.c clients.h
fort_SOURCES += common.c common.h
-fort_SOURCES += console_handler.h console_handler.c
fort_SOURCES += config.h config.c
fort_SOURCES += debug.h debug.c
fort_SOURCES += extension.h extension.c
fort_SOURCES += log.h log.c
fort_SOURCES += nid.h nid.c
fort_SOURCES += notify.c notify.h
+fort_SOURCES += output_printer.h output_printer.c
fort_SOURCES += random.h random.c
fort_SOURCES += resource.h resource.c
fort_SOURCES += rpp.h rpp.c
char *slurm;
struct {
+ /** Enable/disable the RTR server. */
+ bool enabled;
/** The bound listening address of the RTR server. */
char *address;
/** The bound listening port of the RTR server. */
/** Format in which file names will be printed. */
enum filename_format filename_format;
} log;
+
+ struct {
+ /** File where the validated ROAs will be stored */
+ char *roa;
+ /** TODO (next iteration) Add BGPsec output */
+ } output;
};
static void print_usage(FILE *, bool);
.type = >_string,
.offset = offsetof(struct rpki_config, tal),
.doc = "Path to the TAL file or TALs directory",
- .arg_doc = "<file>",
+ .arg_doc = "<file or directory>",
}, {
.id = 'r',
.name = "local-repository",
/* Server fields */
{
.id = 5000,
+ .name = "server.enabled",
+ .type = >_bool,
+ .offset = offsetof(struct rpki_config, server.enabled),
+ .doc = "Enable or disable the RTR server.",
+ }, {
+ .id = 5001,
.name = "server.address",
.type = >_string,
.offset = offsetof(struct rpki_config, server.address),
- .doc = "Address the RTR server will bind itself to. Can be a name, in which case an address will be resolved.",
+ .doc = "Address to which RTR server will bind itself to. Can be a name, in which case an address will be resolved.",
}, {
- .id = 5001,
+ .id = 5002,
.name = "server.port",
.type = >_string,
.offset = offsetof(struct rpki_config, server.port),
- .doc = "Port the RTR server will bind itself to. Can be a string, in which case a number will be resolved.",
+ .doc = "Port to which RTR server will bind itself to. Can be a string, in which case a number will be resolved.",
}, {
.id = 5003,
.name = "server.backlog",
.availability = AVAILABILITY_JSON,
},
+ /* Output files */
+ {
+ .id = 6000,
+ .name = "output.roa",
+ .type = >_string,
+ .offset = offsetof(struct rpki_config, output.roa),
+ .doc = "File where ROAs will be stored in CSV format, use '-' to print at console",
+ .arg_doc = "<file>",
+ },
+
{ 0 },
};
* duplicates.
*/
+ rpki_config.server.enabled = true;
rpki_config.server.address = NULL;
rpki_config.server.port = strdup("323");
if (rpki_config.server.port == NULL)
rpki_config.log.color = false;
rpki_config.log.filename_format = FNF_GLOBAL;
+ rpki_config.output.roa = NULL;
+
return 0;
revert_recursive_array:
return options;
}
+bool
+config_get_server_enabled(void)
+{
+ return rpki_config.server.enabled;
+}
+
char const *
config_get_server_address(void)
{
pr_crit("Invalid sync strategy: '%u'", rpki_config.sync_strategy);
}
+char const *
+config_get_output_roa(void)
+{
+ return rpki_config.output.roa;
+}
+
void
free_rpki_config(void)
{
void free_rpki_config(void);
/* Getters */
+bool config_get_server_enabled(void);
char const *config_get_server_address(void);
char const *config_get_server_port(void);
int config_get_server_queue(void);
enum filename_format config_get_filename_format(void);
char *config_get_rsync_program(void);
struct string_array const *config_get_rsync_args(bool);
+char const *config_get_output_roa(void);
/* Needed public by the JSON module */
void *get_rpki_config_field(struct option_field const *);
+++ /dev/null
-#include "console_handler.h"
-
-#include "thread_var.h"
-#include "validation_handler.h"
-#include "object/tal.h"
-
-static int
-print_v4_roa(uint32_t as, struct ipv4_prefix const *prefix, uint8_t max_length,
- void *arg)
-{
- printf("AS%u,%s/%u,%u\n", as, v4addr2str(&prefix->addr), prefix->len,
- max_length);
- return 0;
-}
-
-static int
-print_v6_roa(uint32_t as, struct ipv6_prefix const *prefix, uint8_t max_length,
- void *arg)
-{
- printf("AS%u,%s/%u,%u\n", as, v6addr2str(&prefix->addr), prefix->len,
- max_length);
- return 0;
-}
-
-int
-validate_into_console(void)
-{
- struct validation_handler handler;
-
- handler.handle_roa_v4 = print_v4_roa;
- handler.handle_roa_v6 = print_v6_roa;
- handler.arg = NULL;
-
- return perform_standalone_validation(&handler);
-}
+++ /dev/null
-#ifndef SRC_CONSOLE_HANDLER_H_
-#define SRC_CONSOLE_HANDLER_H_
-
-int validate_into_console(void);
-
-#endif /* SRC_CONSOLE_HANDLER_H_ */
#include <stdlib.h>
#include "log.h"
-int
-file_open(char const *file_name, FILE **result, struct stat *stat)
+static int
+file_get(char const *file_name, FILE **result, struct stat *stat,
+ char const *mode)
{
FILE *file;
int error;
- file = fopen(file_name, "rb");
+ file = fopen(file_name, mode);
if (file == NULL)
return pr_errno(errno, "Could not open file '%s'", file_name);
return error;
}
+int
+file_open(char const *file_name, FILE **result, struct stat *stat)
+{
+ return file_get(file_name, result, stat, "rb");
+}
+
+int
+file_write(char const *file_name, FILE **result, struct stat *stat)
+{
+ return file_get(file_name, result, stat, "wb");
+}
+
void
file_close(FILE *file)
{
};
int file_open(char const *, FILE **, struct stat *);
+int file_write(char const *, FILE **, struct stat *);
void file_close(FILE *);
int file_load(char const *, struct file_contents *);
#include "clients.h"
#include "config.h"
-#include "console_handler.h"
#include "debug.h"
#include "extension.h"
#include "nid.h"
if (error)
goto revert_nid;
- error = (config_get_server_address() != NULL)
- ? start_rtr_server()
- : validate_into_console();
+ error = start_rtr_server();
revert_nid:
nid_destroy();
--- /dev/null
+#include "output_printer.h"
+
+#include "config.h"
+#include "file.h"
+#include "log.h"
+#include "rtr/db/vrp.h"
+#include <arpa/inet.h>
+
+char addr_buf[INET6_ADDRSTRLEN];
+
+static char const *
+strv4addr(struct in_addr const *addr)
+{
+ return inet_ntop(AF_INET, addr, addr_buf, INET6_ADDRSTRLEN);
+}
+
+static char const *
+strv6addr(struct in6_addr const *addr)
+{
+ return inet_ntop(AF_INET6, addr, addr_buf, INET6_ADDRSTRLEN);
+}
+
+static int
+load_output_file(FILE **result, bool *fopen)
+{
+ FILE *tmp;
+ struct stat stat;
+ char const *output = config_get_output_roa();
+ int error;
+
+ if (output == NULL) {
+ *result = NULL;
+ return 0;
+ }
+
+ *fopen = false;
+ if (strcmp(output, "-") == 0) {
+ *result = stdout;
+ return 0;
+ }
+
+ error = file_write(output, &tmp, &stat);
+ if (error)
+ return error;
+
+ *fopen = true;
+ *result = tmp;
+ return 0;
+}
+
+static int
+print_roa(struct vrp const *vrp, void *arg)
+{
+ FILE *out = arg;
+
+ switch(vrp->addr_fam) {
+ case AF_INET:
+ fprintf(out, "AS%u,%s/%u,%u\n", vrp->asn,
+ strv4addr(&vrp->prefix.v4), vrp->prefix_length,
+ vrp->max_prefix_length);
+ break;
+ case AF_INET6:
+ fprintf(out, "AS%u,%s/%u,%u\n", vrp->asn,
+ strv6addr(&vrp->prefix.v6), vrp->prefix_length,
+ vrp->max_prefix_length);
+ break;
+ default:
+ pr_crit("Unknown family type");
+ }
+
+ return 0;
+}
+
+void
+output_print_roas(struct roa_table *roas)
+{
+ FILE *out;
+ bool fopen;
+ int error;
+
+ error = load_output_file(&out, &fopen);
+ if (error) {
+ pr_err("Error getting file '%s'", config_get_output_roa());
+ return;
+ }
+
+ /* No output configured */
+ if (out == NULL)
+ return;
+
+ fprintf(out, "ASN,Prefix,Max prefix length\n");
+ error = roa_table_foreach_roa(roas, print_roa, out);
+ if (fopen)
+ file_close(out);
+ if (error) {
+ pr_err("Error printing ROAs");
+ return;
+ }
+}
--- /dev/null
+#ifndef SRC_OUTPUT_PRINTER_H_
+#define SRC_OUTPUT_PRINTER_H_
+
+#include "rtr/db/roa_table.h"
+
+void output_print_roas(struct roa_table *);
+
+#endif /* SRC_OUTPUT_PRINTER_H_ */
#include <sys/queue.h>
#include "clients.h"
#include "common.h"
+#include "output_printer.h"
#include "validation_handler.h"
#include "data_structure/array_list.h"
#include "object/tal.h"
validation_handler.arg = roas;
error = perform_standalone_validation(&validation_handler);
+ /* Print after validation to avoid duplicated info */
+ output_print_roas(roas);
if (error) {
roa_table_destroy(roas);
return error;
#include "updates_daemon.h"
#include "rtr/err_pdu.h"
#include "rtr/pdu.h"
+#include "rtr/db/vrps.h"
struct sigaction act;
/*
* Starts the server, using the current thread to listen for RTR client
- * requests.
+ * requests. If configuration parameter 'server.enabled' is false, then the
+ * server runs "one time" (a.k.a. run the validation just once), it doesn't
+ * waits for clients requests.
*
- * This function blocks.
+ * When listening for client requests, this function blocks.
*/
int
rtr_listen(void)
{
+ bool changed;
int server_fd; /* "file descriptor" */
int error;
- error = create_server_socket(&server_fd);
+ error = init_signal_handler();
if (error)
return error;
- /* Server ready, start everything else */
error = clients_db_init();
if (error)
- goto revert_server_socket;
+ return error;
- error = updates_daemon_start();
+ if (!config_get_server_enabled()) {
+ error = vrps_update(&changed);
+ if (error)
+ pr_err("Error %d while trying to update the ROA database.",
+ error);
+ goto revert_clients_db; /* Error 0 it's ok */
+ }
+
+ error = create_server_socket(&server_fd);
if (error)
goto revert_clients_db;
- error = init_signal_handler();
+ error = updates_daemon_start();
if (error)
- goto revert_updates_daemon;
+ goto revert_server_socket;
error = handle_client_connections(server_fd);
end_clients();
-revert_updates_daemon:
updates_daemon_destroy();
-revert_clients_db:
- clients_db_destroy(join_thread, NULL);
revert_server_socket:
close(server_fd);
+revert_clients_db:
+ clients_db_destroy(join_thread, NULL);
return error;
}
pdu_handler_test_SOURCES = ${BASIC_MODULES}
pdu_handler_test_SOURCES += ${SLURM_SOURCES}
pdu_handler_test_SOURCES += ../src/common.c
+pdu_handler_test_SOURCES += ../src/file.c
+pdu_handler_test_SOURCES += ../src/output_printer.c
pdu_handler_test_SOURCES += ../src/rtr/pdu_handler.c
pdu_handler_test_SOURCES += ../src/rtr/err_pdu.c
pdu_handler_test_SOURCES += ../src/rtr/db/delta.c
vrps_test_SOURCES = ${BASIC_MODULES}
vrps_test_SOURCES += ${SLURM_SOURCES}
vrps_test_SOURCES += ../src/common.c
+vrps_test_SOURCES += ../src/file.c
+vrps_test_SOURCES += ../src/output_printer.c
vrps_test_SOURCES += ../src/rtr/db/delta.c
vrps_test_SOURCES += ../src/rtr/db/roa_table.c
vrps_test_SOURCES += ../src/rtr/db/vrps.c
return NULL;
}
+bool
+config_get_server_enabled(void)
+{
+ return false;
+}
+
+char const *
+config_get_output_roa(void)
+{
+ return "-";
+}
+
enum incidence_action
incidence_get_action(enum incidence_id id)
{