# FORT Validator
-An RPKI Validator and RTR Server, part of the [FORT project](https://www.fortproject.net).
+An RPKI Relying Party and RTR Server.
## Documentation
-FORT Validator's documentation (installation, usage, etc.) can be found at [https://nicmx.github.io/FORT-validator/](https://nicmx.github.io/FORT-validator/).
-
-If you wish to generate the docs by yourself, visit the [docs directory](docs/).
+- [Home](https://nicmx.github.io/FORT-validator/index.html)
+- [Installation](https://nicmx.github.io/FORT-validator/installation.html)
+- [Usage](https://nicmx.github.io/FORT-validator/run.html)
+- [Arguments](https://nicmx.github.io/FORT-validator/usage.html)
## Docker image
-A Dockerfile to build the image is located at the [docker directory](docker/).
-
-## Quick start
-
-TL;DR all the docs, probably you just want to read:
-- How to install? Visit [Compilation and Installation](https://nicmx.github.io/FORT-validator/installation.html).
-- How to execute? Visit [Basic Usage](https://nicmx.github.io/FORT-validator/run.html) and [Program Arguments](https://nicmx.github.io/FORT-validator/usage.html).
-- How to configure the router(s)? Visit [Routers](https://nicmx.github.io/FORT-validator/routers.html).
+See the [docker/ directory](docker/).
[--configuration-file=<file>]
[--tal=<file>|<directory>]
[--local-repository=<directory>]
- [--sync-strategy=off|root|root-except-ta]
- [--shuffle-uris=true|false]
[--maximum-certificate-depth=<unsigned integer>]
[--slurm=<file>|<directory>]
[--mode=server|standalone]
[--server.interval.expire=<unsigned integer>]
[--server.deltas.lifetime=<unsigned integer>]
[--rsync.enabled=true|false]
- [--rsync.priority=<32-bit unsigned integer>]
- [--rsync.strategy=root|root-except-ta]
+ [--rsync.priority=<unsigned integer>]
[--rsync.retry.count=<unsigned integer>]
[--rsync.retry.interval=<unsigned integer>]
- [--rrdp.enabled=true|false]
- [--rrdp.priority=<32-bit unsigned integer>]
- [--rrdp.retry.count=<unsigned integer>]
- [--rrdp.retry.interval=<unsigned integer>]
[--http.enabled=true|false]
- [--http.priority=<32-bit unsigned integer>]
+ [--http.priority=<unsigned integer>]
[--http.retry.count=<unsigned integer>]
[--http.retry.interval=<unsigned integer>]
[--http.user-agent=<string>]
+ [--http.max-redirs=<unsigned integer>]
[--http.connect-timeout=<unsigned integer>]
[--http.transfer-timeout=<unsigned integer>]
[--http.low-speed-limit=<unsigned integer>]
[--output.bgpsec=<file>]
[--output.format=csv|json]
[--asn1-decode-max-stack=<unsigned integer>]
- [--stale-repository-period=<unsigned integer>]
[--init-tals=true|false]
[--init-as0-tals=true|false]
[--thread-pool.server.max=<unsigned integer>]
- [--thread-pool.validation.max=<unsigned integer>]
```
If an argument is specified more than once, the last one takes precedence:
<pre><code>{
"<a href="#--tal">tal</a>": "/tmp/fort/tal/",
- "<a href="#--local-repository">local-repository</a>": "/tmp/fort/repository/",
+ "<a href="#--local-repository">local-repository</a>": "/tmp/fort/repository",
"<a href="#--work-offline">work-offline</a>": false,
- "<a href="#--shuffle-uris">shuffle-uris</a>": true,
"<a href="#--maximum-certificate-depth">maximum-certificate-depth</a>": 32,
"<a href="#--mode">mode</a>": "server",
"<a href="#--daemon">daemon</a>": false,
"<a href="#--slurm">slurm</a>": "/tmp/fort/test.slurm",
+ "<a href="#--asn1-decode-max-stack">asn1-decode-max-stack</a>": 4096,
"server": {
"<a href="#--serveraddress">address</a>": [
"2001:db8::1"
],
"<a href="#--serverport">port</a>": "8323",
- "<a href="#--serverbacklog">backlog</a>": 16,
+ "<a href="#--serverbacklog">backlog</a>": 4096,
"interval": {
"<a href="#--serverintervalvalidation">validation</a>": 3600,
"<a href="#--serverintervalrefresh">refresh</a>": 3600,
"<a href="#--serverintervalexpire">expire</a>": 7200
},
"deltas": {
- "<a href="#--serverdeltaslifetime">lifetime</a>": 4
+ "<a href="#--serverdeltaslifetime">lifetime</a>": 2
}
},
"log": {
"<a href="#--logenabled">enabled</a>": true,
- "<a href="#--loglevel">level</a>": "warning",
"<a href="#--logoutput">output</a>": "console",
- "<a href="#--logcolor-output">color-output</a>": true,
- "<a href="#--logfile-name-format">file-name-format</a>": "file-name",
+ "<a href="#--loglevel">level</a>": "info",
+ "<a href="#--logtag">tag</a>": "Operation",
"<a href="#--logfacility">facility</a>": "daemon",
- "<a href="#--logtag">tag</a>": "Operation"
+ "<a href="#--logfile-name-format">file-name-format</a>": "global-url",
+ "<a href="#--logcolor-output">color-output</a>": false
},
"validation-log": {
"<a href="#--validation-logenabled">enabled</a>": false,
- "<a href="#--validation-loglevel">level</a>": "warning",
"<a href="#--validation-logoutput">output</a>": "console",
- "<a href="#--validation-logcolor-output">color-output</a>": true,
- "<a href="#--validation-logfile-name-format">file-name-format</a>": "global-url",
+ "<a href="#--validation-loglevel">level</a>": "warning",
+ "<a href="#--validation-logtag">tag</a>": "Validation",
"<a href="#--validation-logfacility">facility</a>": "daemon",
- "<a href="#--validation-logtag">tag</a>": "Validation"
+ "<a href="#--validation-logfile-name-format">file-name-format</a>": "global-url",
+ "<a href="#--validation-logcolor-output">color-output</a>": false
},
"http": {
"<a href="#--httpenabled">enabled</a>": true,
"<a href="#--httppriority">priority</a>": 60,
"retry": {
- "<a href="#--httpretrycount">count</a>": 2,
- "<a href="#--httpretryinterval">interval</a>": 5
+ "<a href="#--httpretrycount">count</a>": 1,
+ "<a href="#--httpretryinterval">interval</a>": 4
},
"<a href="#--httpuser-agent">user-agent</a>": "{{ page.command }}/{{ site.fort-latest-version }}",
+ "<a href="#--httpconnect-timeout">max-redirs</a>": 10,
"<a href="#--httpconnect-timeout">connect-timeout</a>": 30,
"<a href="#--httptransfer-timeout">transfer-timeout</a>": 0,
- "<a href="#--httplow-speed-limit">low-speed-limit</a>": 30,
+ "<a href="#--httplow-speed-limit">low-speed-limit</a>": 100000,
"<a href="#--httplow-speed-time">low-speed-time</a>": 10,
- "<a href="#--httpmax-file-size">max-file-size</a>": 10000000,
+ "<a href="#--httpmax-file-size">max-file-size</a>": 1000000000,
"<a href="#--httpca-path">ca-path</a>": "/usr/local/ssl/certs"
},
"rsync": {
"<a href="#--rsyncenabled">enabled</a>": true,
"<a href="#--rsyncpriority">priority</a>": 50,
- "<a href="#--rsyncstrategy">strategy</a>": "root-except-ta",
"retry": {
- "<a href="#--rsyncretrycount">count</a>": 2,
- "<a href="#--rsyncretryinterval">interval</a>": 5
+ "<a href="#--rsyncretrycount">count</a>": 1,
+ "<a href="#--rsyncretryinterval">interval</a>": 4
},
"<a href="#rsyncprogram">program</a>": "rsync",
"<a href="#rsyncarguments-recursive">arguments-recursive</a>": [
- "--recursive",
+ "-rtz",
"--delete",
- "--times",
+ "--omit-dir-times",
"--contimeout=20",
+ "--max-size=20MB",
"--timeout=15",
- "$REMOTE",
- "$LOCAL"
- ],
- "<a href="#rsyncarguments-flat">arguments-flat</a>": [
- "--times",
- "--contimeout=20",
- "--timeout=15",
- "--dirs",
+ "--include=*/",
+ "--include=*.cer",
+ "--include=*.crl",
+ "--include=*.gbr",
+ "--include=*.mft",
+ "--include=*.roa",
+ "--exclude=*",
"$REMOTE",
"$LOCAL"
]
"thread-pool": {
"server": {
"<a href="#--thread-poolservermax">max</a>": 20
- },
- "validation": {
- "<a href="#--thread-poolvalidationmax">max</a>": 5
}
- },
-
- "<a href="#--asn1-decode-max-stack">asn1-decode-max-stack</a>": 4096,
- "<a href="#--stale-repository-period">stale-repository-period</a>": 43200
+ }
}
</code></pre>
-.TH fort 8 "2023-11-16" "v1.6.0" "FORT validator"
+.TH fort 8 "2023-11-30" "v1.6.0" "FORT validator"
.SH NAME
fort \- RPKI validator and RTR server
This is an example of a valid JSON configuration file with all its members set
to a specific value:
.nf
-
{
"tal": "/tmp/fort/tal/",
- "local-repository": "/tmp/fort/repository/",
+ "local-repository": "/tmp/fort/repository",
"work-offline": false,
- "shuffle-uris": true,
"maximum-certificate-depth": 32,
"mode": "server",
"daemon": false,
"slurm": "/tmp/fort/test.slurm",
+ "asn1-decode-max-stack": 4096,
+
"server": {
"address": [
"192.0.2.1",
"2001:db8::1"
],
"port": "8323",
- "backlog": 64,
+ "backlog": 4096,
"interval": {
"validation": 3600,
"refresh": 3600,
"expire": 7200
},
"deltas": {
- "lifetime": 4
+ "lifetime": 2
}
},
+
"log": {
"enabled": true,
- "level": "warning",
"output": "console",
- "color-output": true,
- "file-name-format": "local-path",
+ "level": "info",
+ "tag": "Operation",
"facility": "daemon",
- "tag": "Operation"
+ "file-name-format": "global-url",
+ "color-output": false
},
+
"validation-log": {
"enabled": false,
- "level": "warning",
"output": "console",
- "color-output": true,
- "file-name-format": "local-path",
+ "level": "warning",
+ "tag": "Validation",
"facility": "daemon",
- "tag": "Validation"
+ "file-name-format": "global-url",
+ "color-output": false
},
+
"http": {
"enabled": true,
"priority": 60,
"retry": {
- "count": 2,
- "interval": 5
+ "count": 1,
+ "interval": 4
},
- "user-agent": "fort/1.5.1",
+ "user-agent": "fort/1.6.0",
+ "max-redirs": 10,
"connect-timeout": 30,
"transfer-timeout": 0,
- "idle-timeout": 15,
+ "low-speed-limit": 100000,
+ "low-speed-time": 10,
+ "max-file-size": 1000000000,
"ca-path": "/usr/local/ssl/certs"
},
+
"rsync": {
"enabled": true,
"priority": 50,
- "strategy": "root-except-ta",
"retry": {
- "count": 2,
- "interval": 5
+ "count": 1,
+ "interval": 4
},
"program": "rsync",
"arguments-recursive": [
- "--recursive",
+ "-rtz",
"--delete",
- "--times",
- "--contimeout=20",
- "--timeout=15",
- "$REMOTE",
- "$LOCAL"
- ],
- "arguments-flat": [
- "--times",
+ "--omit-dir-times",
"--contimeout=20",
+ "--max-size=20MB",
"--timeout=15",
- "--dirs",
+ "--include=*/",
+ "--include=*.cer",
+ "--include=*.crl",
+ "--include=*.gbr",
+ "--include=*.mft",
+ "--include=*.roa",
+ "--exclude=*",
"$REMOTE",
"$LOCAL"
]
},
+
"incidences": [
{
"name": "incid-hashalg-has-params",
"action": "error"
}
],
+
"output": {
"roa": "/tmp/fort/roas.csv",
"bgpsec": "/tmp/fort/bgpsec.csv",
"format": "csv"
},
+
"thread-pool": {
"server": {
"max": 20
- },
- "validation": {
- "max": 5
}
- },
- "asn1-decode-max-stack": 4096
+ }
}
.fi
.RE
xml_test_SOURCES = xml_test.c
xml_test_LDADD = ${MY_LDADD} ${XML2_LIBS}
-EXTRA_DIST = mock.c
+EXTRA_DIST = mock.c mock.h
EXTRA_DIST += line_file/core.txt
EXTRA_DIST += line_file/empty.txt
EXTRA_DIST += line_file/error.txt
#define TAL_FILE "test.tal"
-struct rpki_cache *cache;
+static struct rpki_cache *cache;
static bool dl_error; /* Download should return error? */
/* Paths downloaded during the test */
static SLIST_HEAD(downloaded_paths, downloaded_path) downloaded;
-unsigned int rsync_counter; /* Times the rsync function was called */
-unsigned int https_counter; /* Times the https function was called */
+static unsigned int rsync_counter; /* Times the rsync function was called */
+static unsigned int https_counter; /* Times the https function was called */
int
file_exists(char const *file)
node->attempt.ts = epoch;
}
-void
+static void
cache_reset(struct rpki_cache *cache)
{
struct cache_node *node, *tmp;
/* Boilerplate */
-Suite *thread_pool_suite(void)
+static Suite *thread_pool_suite(void)
{
Suite *suite;
TCase *rsync , *https, *dot, *meta, *recover;
}
END_TEST
-Suite *
+static Suite *
pdu_suite(void)
{
Suite *suite;
}
END_TEST
-Suite *pdu_suite(void)
+static Suite *pdu_suite(void)
{
Suite *suite;
TCase *core, *uri;
}
END_TEST
-Suite *ghostbusters_suite(void)
+static Suite *ghostbusters_suite(void)
{
Suite *suite;
TCase *core, *limits, *errors;
#include <errno.h>
#include <arpa/inet.h>
+#include "config.h"
#include "state.h"
+#include "thread_var.h"
#include "config/filename_format.h"
#include "config/mode.h"
#include "incidence/incidence.h"
MOCK_UINT(config_get_http_priority, 60, void)
MOCK_NULL(config_get_output_roa, char const *, void)
MOCK_NULL(config_get_output_bgpsec, char const *, void)
-MOCK_UINT(config_get_thread_pool_validation_max, 10, void)
MOCK(config_get_op_log_filename_format, enum filename_format, FNF_NAME, void)
MOCK(config_get_val_log_filename_format, enum filename_format, FNF_NAME, void)
}
END_TEST
-Suite *xml_load_suite(void)
+static Suite *xml_load_suite(void)
{
Suite *suite;
TCase *validate;
}
END_TEST
-Suite *pdu_suite(void)
+static Suite *pdu_suite(void)
{
Suite *suite;
TCase *core;
#include "rtr/db/deltas_array.c"
#define TOTAL_CREATED 15
-struct deltas *created[TOTAL_CREATED];
+static struct deltas *created[TOTAL_CREATED];
unsigned int
config_get_deltas_lifetime(void)
}
END_TEST
-Suite *address_load_suite(void)
+static Suite *address_load_suite(void)
{
Suite *suite;
TCase *core;
db_imp_spk, handler->arg));
}
-int
+static int
__handle_roa_v4(uint32_t as, struct ipv4_prefix const *prefix,
uint8_t max_length, void *arg)
{
return rtrhandler_handle_roa_v4(arg, as, prefix, max_length);
}
-int
+static int
__handle_roa_v6(uint32_t as, struct ipv6_prefix const *prefix,
uint8_t max_length, void *arg)
{
return rtrhandler_handle_roa_v6(arg, as, prefix, max_length);
}
-int
+static int
__handle_router_key(unsigned char const *ski, struct asn_range const *range,
unsigned char const *spk, void *arg)
{
/* Mocks */
-unsigned int deltas_lifetime = 5;
+static unsigned int deltas_lifetime = 5;
MOCK_UINT(config_get_deltas_lifetime, deltas_lifetime, void)
MOCK_ABORT_ENUM(config_get_output_format, output_format, void)
}
END_TEST
-Suite *pdu_suite(void)
+static Suite *pdu_suite(void)
{
Suite *suite;
TCase *core;
/* Mocks */
-struct rtr_buffer const *
-pdustream_last_pdu_raw(struct pdu_stream *s)
-{
- static unsigned char bytes[] = {
- /* header */
- 1, 1, 7, 8, 0, 0, 0, 12,
- /* serial number */
- 14, 15, 16, 17,
- };
- static struct rtr_buffer buf = {
- .bytes = bytes,
- .bytes_len = sizeof(bytes),
- };
-
- return &buf;
-}
-
MOCK_INT(slurm_apply, 0, struct db_table *base, struct db_slurm **slurm)
MOCK_ABORT_VOID(db_slurm_destroy, struct db_slurm *db)
MOCK_UINT(config_get_deltas_lifetime, 5, void)
-int
-clients_get_rtr_version_set(int fd, bool *is_set, uint8_t *rtr_version)
-{
- (*is_set) = true;
- (*rtr_version) = RTR_V1;
- return 0;
-}
-
int
send_cache_reset_pdu(int fd, uint8_t version)
{
}
END_TEST
-Suite *pdu_suite(void)
+static Suite *pdu_suite(void)
{
Suite *suite;
TCase *core, *error;
}
END_TEST
-Suite *pdu_suite(void)
+static Suite *pdu_suite(void)
{
Suite *suite;
TCase *core, *errors, *string;
MOCK(state_retrieve, struct validation *, NULL, void)
MOCK_ABORT_PTR(validation_certstack, cert_stack, struct validation *state)
MOCK_ABORT_VOID(validation_destroy, struct validation *state)
-MOCK_ABORT_PTR(validation_get_notification_uri, rpki_uri,
- struct validation *state)
MOCK_ABORT_INT(validation_prepare, struct validation **out, struct tal *tal,
struct validation_handler *validation_handler)
MOCK_ABORT_ENUM(validation_pubkey_state, pubkey_state, struct validation *state)
}
END_TEST
-Suite *tal_load_suite(void)
+static Suite *tal_load_suite(void)
{
Suite *suite;
TCase *core;
}
END_TEST
-Suite *thread_pool_suite(void)
+static Suite *thread_pool_suite(void)
{
Suite *suite;
TCase *single, *multiple;
}
END_TEST
-Suite *address_load_suite(void)
+static Suite *address_load_suite(void)
{
Suite *suite;
TCase *core;
}
END_TEST
-Suite *serial_suite(void)
+static Suite *serial_suite(void)
{
Suite *suite;
TCase *core;
/* Mocks */
-struct rpki_uri *notif;
+static struct rpki_uri *notif;
MOCK(state_retrieve, struct validation *, NULL, void)
MOCK(validation_tal, struct tal *, NULL, struct validation *state)
MOCK(tal_get_file_name, char const *, "test.tal", struct tal *tal)
-MOCK(validation_get_notification_uri, struct rpki_uri *, notif,
- struct validation *state)
-MOCK_ABORT_INT(cache_download, struct rpki_uri *uri, bool *changed)
MOCK_ABORT_INT(rrdp_update, struct rpki_uri *uri)
-MOCK_ABORT_PTR(cache_recover, rpki_uri, struct uri_list *uris,
- bool use_rrdp)
/* Tests */
}
END_TEST
-Suite *address_load_suite(void)
+static Suite *address_load_suite(void)
{
Suite *suite;
TCase *core;
}
END_TEST
-Suite *ghostbusters_suite(void)
+static Suite *ghostbusters_suite(void)
{
Suite *suite;
TCase *hgv;
}
END_TEST
-Suite *xml_load_suite(void)
+static Suite *xml_load_suite(void)
{
Suite *suite;
TCase *validate;