From: pcarana Date: Thu, 23 Jul 2020 16:46:10 +0000 (-0500) Subject: Move rrdp.* args to http.* configurations X-Git-Tag: v1.4.0~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=85478ff30ebc029abb0ded48de5b557f52a758e0;p=thirdparty%2FFORT-validator.git Move rrdp.* args to http.* configurations +The new arguments are: http.enabled, http.priority, http.retry.count, http.retry.interval. +rrdp.* args still exist. When any of them is set (via conf file or as arg) a warning message is displayed and the value of the argument is set to its corresponding http.* arg. +Move the 'retries logic' to the http requests, since only RRDP flows had it. +At a TAL: when shuffle-uris arg is set, do the shuffle first and then consider the priority set at rsync and http args, so that the priority argument can be honored. --- diff --git a/src/Makefile.am b/src/Makefile.am index b03cb514..ccf10fc8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -47,6 +47,7 @@ fort_SOURCES += config/filename_format.h config/filename_format.c fort_SOURCES += config/log_conf.h config/log_conf.c fort_SOURCES += config/mode.c config/mode.h fort_SOURCES += config/incidences.h config/incidences.c +fort_SOURCES += config/rrdp_conf.h config/rrdp_conf.c fort_SOURCES += config/rsync_strategy.h config/rsync_strategy.c fort_SOURCES += config/str.c config/str.h fort_SOURCES += config/string_array.h config/string_array.c diff --git a/src/config.c b/src/config.c index c8b358e8..2d03935e 100644 --- a/src/config.c +++ b/src/config.c @@ -15,6 +15,7 @@ #include "log.h" #include "config/boolean.h" #include "config/incidences.h" +#include "config/rrdp_conf.h" #include "config/str.h" #include "config/sync_strategy.h" #include "config/uint.h" @@ -118,6 +119,22 @@ struct rpki_config { } rrdp; struct { + /* Enables the protocol */ + bool enabled; + /* + * Priority, whenever there's an option to sync something via + * http or rsync, use this priority. When working with CAs, this + * will override the order set at the CAs in their accessMethod + * extension. + */ + unsigned int priority; + /* Retry conf, utilized on errors */ + struct { + /* Maximum number of retries on error */ + unsigned int count; + /* Interval (in seconds) between each retry */ + unsigned int interval; + } retry; /* User-Agent header set at requests */ char *user_agent; /* Timeout in seconds for the connect phase */ @@ -457,31 +474,31 @@ static const struct option_field options[] = { { .id = 10000, .name = "rrdp.enabled", - .type = >_bool, + .type = >_rrdp_enabled, .offset = offsetof(struct rpki_config, rrdp.enabled), - .doc = "Enables RRDP execution", + .doc = "Enables RRDP execution. Will be deprecated, use 'http.enabled' instead.", }, { .id = 10001, .name = "rrdp.priority", - .type = >_uint32, + .type = >_rrdp_priority, .offset = offsetof(struct rpki_config, rrdp.priority), - .doc = "Priority of execution to fetch repositories files, a higher value means higher priority", + .doc = "Priority of execution to fetch repositories files, a higher value means higher priority. Will be deprecated, use 'http.priority' instead.", .min = 0, .max = 100, }, { .id = 10002, .name = "rrdp.retry.count", - .type = >_uint, + .type = >_rrdp_retry_count, .offset = offsetof(struct rpki_config, rrdp.retry.count), - .doc = "Maximum amount of retries whenever there's an error fetching RRDP files", + .doc = "Maximum amount of retries whenever there's an error fetching RRDP files. Will be deprecated, use 'http.retry.count' instead.", .min = 0, .max = UINT_MAX, }, { .id = 10003, .name = "rrdp.retry.interval", - .type = >_uint, + .type = >_rrdp_retry_interval, .offset = offsetof(struct rpki_config, rrdp.retry.interval), - .doc = "Period (in seconds) to wait between retries after an error ocurred fetching RRDP files", + .doc = "Period (in seconds) to wait between retries after an error ocurred fetching RRDP files. Will be deprecated, use 'http.retry.interval' instead.", .min = 0, .max = UINT_MAX, }, @@ -489,13 +506,47 @@ static const struct option_field options[] = { /* HTTP requests parameters */ { .id = 9000, + .name = "http.enabled", + .type = >_rrdp_enabled, + .offset = offsetof(struct rpki_config, http.enabled), + .doc = "Enables outgoing HTTP requests", + }, + { + .id = 9001, + .name = "http.priority", + .type = >_rrdp_priority, + .offset = offsetof(struct rpki_config, http.priority), + .doc = "Priority of execution to fetch repositories files, a higher value means higher priority", + .min = 0, + .max = 100, + }, + { + .id = 9002, + .name = "http.retry.count", + .type = >_rrdp_retry_count, + .offset = offsetof(struct rpki_config, http.retry.count), + .doc = "Maximum amount of retries whenever there's an error requesting HTTP URIs", + .min = 0, + .max = UINT_MAX, + }, + { + .id = 9003, + .name = "http.retry.interval", + .type = >_rrdp_retry_interval, + .offset = offsetof(struct rpki_config, http.retry.interval), + .doc = "Period (in seconds) to wait between retries after an error ocurred doing HTTP requests", + .min = 0, + .max = UINT_MAX, + }, + { + .id = 9004, .name = "http.user-agent", .type = >_string, .offset = offsetof(struct rpki_config, http.user_agent), .doc = "User-Agent to use at HTTP requests, eg. Fort Validator Local/1.0", }, { - .id = 9001, + .id = 9005, .name = "http.connect-timeout", .type = >_uint, .offset = offsetof(struct rpki_config, http.connect_timeout), @@ -504,7 +555,7 @@ static const struct option_field options[] = { .max = UINT_MAX, }, { - .id = 9002, + .id = 9006, .name = "http.transfer-timeout", .type = >_uint, .offset = offsetof(struct rpki_config, http.transfer_timeout), @@ -513,7 +564,7 @@ static const struct option_field options[] = { .max = UINT_MAX, }, { - .id = 9003, + .id = 9007, .name = "http.idle-timeout", .type = >_uint, .offset = offsetof(struct rpki_config, http.idle_timeout), @@ -522,7 +573,7 @@ static const struct option_field options[] = { .max = UINT_MAX, }, { - .id = 9004, + .id = 9008, .name = "http.ca-path", .type = >_string, .offset = offsetof(struct rpki_config, http.ca_path), @@ -875,11 +926,11 @@ set_default_values(void) if (error) goto revert_recursive_array; - rpki_config.rrdp.enabled = true; - rpki_config.rrdp.priority = 50; - rpki_config.rrdp.retry.count = 2; - rpki_config.rrdp.retry.interval = 5; - + /* By default, has a higher priority than rsync */ + rpki_config.http.enabled = true; + rpki_config.http.priority = 60; + rpki_config.http.retry.count = 2; + rpki_config.http.retry.interval = 5; rpki_config.http.user_agent = strdup(PACKAGE_NAME "/" PACKAGE_VERSION); if (rpki_config.http.user_agent == NULL) { error = pr_enomem(); @@ -890,6 +941,15 @@ set_default_values(void) rpki_config.http.idle_timeout = 15; rpki_config.http.ca_path = NULL; /* Use system default */ + /* + * FIXME (later) Same values as http.*, delete when rrdp.* is fully + * deprecated + */ + rpki_config.rrdp.enabled = rpki_config.http.enabled; + rpki_config.rrdp.priority = rpki_config.http.priority; + rpki_config.rrdp.retry.count = rpki_config.http.retry.count; + rpki_config.rrdp.retry.interval = rpki_config.http.retry.interval; + rpki_config.log.color = false; rpki_config.log.filename_format = FNF_GLOBAL; rpki_config.log.level = LOG_WARNING; @@ -1318,27 +1378,27 @@ config_get_rsync_args(bool is_ta) } bool -config_get_rrdp_enabled(void) +config_get_http_enabled(void) { - return rpki_config.rrdp.enabled; + return rpki_config.http.enabled; } unsigned int -config_get_rrdp_priority(void) +config_get_http_priority(void) { - return rpki_config.rrdp.priority; + return rpki_config.http.priority; } unsigned int -config_get_rrdp_retry_count(void) +config_get_http_retry_count(void) { - return rpki_config.rrdp.retry.count; + return rpki_config.http.retry.count; } unsigned int -config_get_rrdp_retry_interval(void) +config_get_http_retry_interval(void) { - return rpki_config.rrdp.retry.interval; + return rpki_config.http.retry.interval; } char const * @@ -1401,6 +1461,25 @@ config_set_rsync_enabled(bool value) rpki_config.rsync.enabled = value; } +void +config_set_http_enabled(bool value) +{ + rpki_config.http.enabled = value; +} + +void +free_rpki_config(void) +{ + struct option_field const *option; + + FOREACH_OPTION(options, option, 0xFFFF) + if (is_rpki_config_field(option) && option->type->free != NULL) + option->type->free(get_rpki_config_field(option)); +} + +/* + * "To be deprecated" section + */ void config_set_rrdp_enabled(bool value) { @@ -1420,11 +1499,37 @@ config_set_rsync_strategy(enum rsync_strategy value) } void -free_rpki_config(void) +config_set_rrdp_priority(unsigned int value) { - struct option_field const *option; + rpki_config.rrdp.priority = value; +} - FOREACH_OPTION(options, option, 0xFFFF) - if (is_rpki_config_field(option) && option->type->free != NULL) - option->type->free(get_rpki_config_field(option)); +void +config_set_http_priority(unsigned int value) +{ + rpki_config.http.priority = value; +} + +void +config_set_rrdp_retry_count(unsigned int value) +{ + rpki_config.rrdp.retry.count = value; +} + +void +config_set_http_retry_count(unsigned int value) +{ + rpki_config.http.retry.count = value; +} + +void +config_set_rrdp_retry_interval(unsigned int value) +{ + rpki_config.rrdp.retry.interval = value; +} + +void +config_set_http_retry_interval(unsigned int value) +{ + rpki_config.http.retry.interval = value; } diff --git a/src/config.h b/src/config.h index 0e785862..0a8c8d64 100644 --- a/src/config.h +++ b/src/config.h @@ -43,10 +43,10 @@ unsigned int config_get_rsync_retry_count(void); unsigned int config_get_rsync_retry_interval(void); char *config_get_rsync_program(void); struct string_array const *config_get_rsync_args(bool); -bool config_get_rrdp_enabled(void); -unsigned int config_get_rrdp_priority(void); -unsigned int config_get_rrdp_retry_count(void); -unsigned int config_get_rrdp_retry_interval(void); +bool config_get_http_enabled(void); +unsigned int config_get_http_priority(void); +unsigned int config_get_http_retry_count(void); +unsigned int config_get_http_retry_interval(void); char const *config_get_output_roa(void); char const *config_get_output_bgpsec(void); unsigned int config_get_asn1_decode_max_stack(void); @@ -74,12 +74,22 @@ uint32_t config_get_val_log_facility(void); * sync-strategy when set to 'off'. */ void config_set_rsync_enabled(bool); +void config_set_http_enabled(bool); +/* FIXME (later) This will be deprecated */ void config_set_rrdp_enabled(bool); /* FIXME (later) Remove when sync-strategy is fully deprecated */ void config_set_sync_strategy(enum rsync_strategy); void config_set_rsync_strategy(enum rsync_strategy); +/* FIXME (later) Remove once rrdp.* is fully deprecated */ +void config_set_rrdp_priority(unsigned int); +void config_set_http_priority(unsigned int); +void config_set_rrdp_retry_count(unsigned int); +void config_set_http_retry_count(unsigned int); +void config_set_rrdp_retry_interval(unsigned int); +void config_set_http_retry_interval(unsigned int); + /* Needed public by the JSON module */ void *get_rpki_config_field(struct option_field const *); struct option_field const *get_option_metadatas(void); diff --git a/src/config/rrdp_conf.c b/src/config/rrdp_conf.c new file mode 100644 index 00000000..4ec952f2 --- /dev/null +++ b/src/config/rrdp_conf.c @@ -0,0 +1,209 @@ +#include "config/rrdp_conf.h" + +#include +#include +#include +#include "config.h" +#include "log.h" +#include "config/boolean.h" +#include "config/uint.h" +#include "config/uint32.h" + +/* + * Note that this is just a wrapper to set rrdp.* arguments and its equivalent + * http.* args. + * + * FIXME (later) This wrapper will live until all rrdp.* args are fully + * deprecated. + */ + +#define DEREFERENCE_BOOL(void_value) (*((bool *) void_value)) +#define DEREFERENCE_UINT32(void_value) (*((uint32_t *) void_value)) +#define DEREFERENCE_UINT(void_value) (*((unsigned int *) void_value)) + +static int +set_rrdp_enabled(char const *name, bool value) +{ + /* Warn about future deprecation */ + if (strcmp(name, "rrdp.enabled") == 0) + pr_op_warn("'rrdp.enabled' will be deprecated, use 'http.enabled' instead."); + + config_set_rrdp_enabled(value); + config_set_http_enabled(value); + return 0; +} + +static int +set_priority(char const *name, uint32_t value) +{ + /* Warn about future deprecation */ + if (strcmp(name, "rrdp.priority") == 0) + pr_op_warn("'rrdp.priority' will be deprecated, use 'http.priority' instead."); + + config_set_rrdp_priority(value); + config_set_http_priority(value); + return 0; +} + +static int +set_retry_count(char const *name, unsigned int value) +{ + /* Warn about future deprecation */ + if (strcmp(name, "rrdp.retry.count") == 0) + pr_op_warn("'rrdp.retry.count' will be deprecated, use 'http.retry.count' instead."); + + config_set_rrdp_retry_count(value); + config_set_http_retry_count(value); + return 0; +} + +static int +set_retry_interval(char const *name, unsigned int value) +{ + /* Warn about future deprecation */ + if (strcmp(name, "rrdp.retry.interval") == 0) + pr_op_warn("'rrdp.retry.interval' will be deprecated, use 'http.retry.interval' instead."); + + config_set_rrdp_retry_interval(value); + config_set_http_retry_interval(value); + return 0; +} + +int +parse_argv_enabled(struct option_field const *field, char const *str, + void *result) +{ + int error; + + error = parse_argv_bool(field, str, result); + if (error) + return error; + + return set_rrdp_enabled(field->name, DEREFERENCE_BOOL(result)); +} + +int +parse_json_enabled(struct option_field const *opt, struct json_t *json, + void *result) +{ + int error; + + error = parse_json_bool(opt, json, result); + if (error) + return error; + + return set_rrdp_enabled(opt->name, DEREFERENCE_BOOL(result)); +} + +int +parse_argv_priority(struct option_field const *field, char const *str, + void *result) +{ + int error; + + error = parse_argv_uint32(field, str, result); + if (error) + return error; + + return set_priority(field->name, DEREFERENCE_UINT32(result)); +} + +int +parse_json_priority(struct option_field const *opt, json_t *json, void *result) +{ + int error; + + error = parse_json_uint32(opt, json, result); + if (error) + return error; + + return set_priority(opt->name, DEREFERENCE_UINT32(result)); +} + +int +parse_argv_retry_count(struct option_field const *field, char const *str, + void *result) +{ + int error; + + error = parse_argv_uint(field, str, result); + if (error) + return error; + + return set_retry_count(field->name, DEREFERENCE_UINT(result)); +} + +int +parse_json_retry_count(struct option_field const *opt, json_t *json, + void *result) +{ + int error; + + error = parse_json_uint(opt, json, result); + if (error) + return error; + + return set_retry_count(opt->name, DEREFERENCE_UINT(result)); +} + +int +parse_argv_retry_interval(struct option_field const *field, char const *str, + void *result) +{ + int error; + + error = parse_argv_uint(field, str, result); + if (error) + return error; + + return set_retry_interval(field->name, DEREFERENCE_UINT(result)); +} + +int +parse_json_retry_interval(struct option_field const *opt, json_t *json, + void *result) +{ + int error; + + error = parse_json_uint(opt, json, result); + if (error) + return error; + + return set_retry_interval(opt->name, DEREFERENCE_UINT(result)); +} + +const struct global_type gt_rrdp_enabled = { + .has_arg = optional_argument, + .size = sizeof(bool), + .print = print_bool, + .parse.argv = parse_argv_enabled, + .parse.json = parse_json_enabled, + .arg_doc = "true|false", +}; + +const struct global_type gt_rrdp_priority = { + .has_arg = required_argument, + .size = sizeof(uint32_t), + .print = print_uint32, + .parse.argv = parse_argv_priority, + .parse.json = parse_json_priority, + .arg_doc = "<32-bit unsigned integer>", +}; + +const struct global_type gt_rrdp_retry_count = { + .has_arg = required_argument, + .size = sizeof(unsigned int), + .print = print_uint, + .parse.argv = parse_argv_retry_count, + .parse.json = parse_json_retry_count, + .arg_doc = "", +}; + +const struct global_type gt_rrdp_retry_interval = { + .has_arg = required_argument, + .size = sizeof(unsigned int), + .print = print_uint, + .parse.argv = parse_argv_retry_interval, + .parse.json = parse_json_retry_interval, + .arg_doc = "", +}; diff --git a/src/config/rrdp_conf.h b/src/config/rrdp_conf.h new file mode 100644 index 00000000..85112bd3 --- /dev/null +++ b/src/config/rrdp_conf.h @@ -0,0 +1,11 @@ +#ifndef SRC_CONFIG_RRDP_CONF_H_ +#define SRC_CONFIG_RRDP_CONF_H_ + +#include "config/types.h" + +extern const struct global_type gt_rrdp_enabled; +extern const struct global_type gt_rrdp_priority; +extern const struct global_type gt_rrdp_retry_count; +extern const struct global_type gt_rrdp_retry_interval; + +#endif /* SRC_CONFIG_RRDP_CONF_H_ */ diff --git a/src/config/uint.c b/src/config/uint.c index 6888489d..3534109a 100644 --- a/src/config/uint.c +++ b/src/config/uint.c @@ -6,7 +6,7 @@ #include #include "log.h" -static void +void print_uint(struct option_field const *field, void *value) { pr_op_info("%s: %u", field->name, *((unsigned int *) value)); diff --git a/src/config/uint.h b/src/config/uint.h index b7869e54..61c79358 100644 --- a/src/config/uint.h +++ b/src/config/uint.h @@ -5,6 +5,7 @@ extern const struct global_type gt_uint; +void print_uint(struct option_field const *, void *); int parse_argv_uint(struct option_field const *, char const *, void *); int parse_json_uint(struct option_field const *, struct json_t *, void *); diff --git a/src/config/uint32.c b/src/config/uint32.c index 942cfcfe..cbd82592 100644 --- a/src/config/uint32.c +++ b/src/config/uint32.c @@ -7,13 +7,13 @@ #include "log.h" #include "config/uint.h" -static void +void print_uint32(struct option_field const *field, void *value) { pr_op_info("%s: %u", field->name, *((uint32_t *) value)); } -static int +int parse_argv_uint32(struct option_field const *field, char const *str, void *result) { @@ -29,7 +29,7 @@ parse_argv_uint32(struct option_field const *field, char const *str, return 0; } -static int +int parse_json_uint32(struct option_field const *opt, json_t *json, void *result) { unsigned int tmp; diff --git a/src/config/uint32.h b/src/config/uint32.h index 44ae1d77..7878e4a0 100644 --- a/src/config/uint32.h +++ b/src/config/uint32.h @@ -5,4 +5,8 @@ extern const struct global_type gt_uint32; +void print_uint32(struct option_field const *, void *); +int parse_argv_uint32(struct option_field const *, char const *, void *); +int parse_json_uint32(struct option_field const *, json_t *, void *); + #endif /* SRC_CONFIG_UINT32_H_ */ diff --git a/src/config/work_offline.c b/src/config/work_offline.c index 8488e233..6adc161d 100644 --- a/src/config/work_offline.c +++ b/src/config/work_offline.c @@ -19,6 +19,7 @@ parse_argv_offline(struct option_field const *field, char const *str, void *resu config_set_rsync_enabled(!DEREFERENCE(result)); config_set_rrdp_enabled(!DEREFERENCE(result)); + config_set_http_enabled(!DEREFERENCE(result)); return 0; } @@ -35,6 +36,7 @@ parse_json_offline(struct option_field const *opt, struct json_t *json, config_set_rsync_enabled(!DEREFERENCE(result)); config_set_rrdp_enabled(!DEREFERENCE(result)); + config_set_http_enabled(!DEREFERENCE(result)); return 0; } diff --git a/src/http/http.c b/src/http/http.c index d34e17de..99cce080 100644 --- a/src/http/http.c +++ b/src/http/http.c @@ -1,5 +1,6 @@ #include "http.h" +#include #include #include #include "common.h" @@ -168,10 +169,12 @@ __http_download_file(struct rpki_uri *uri, http_write_cb cb, struct http_handler handler; struct stat stat; FILE *out; + unsigned int retries; int error; + retries = 0; *cond_met = 1; - if (config_get_work_offline()) { + if (!config_get_http_enabled()) { *response_code = 0; /* Not 200 code, but also not an error */ return 0; } @@ -184,19 +187,36 @@ __http_download_file(struct rpki_uri *uri, http_write_cb cb, if (error) goto delete_dir; - error = http_easy_init(&handler); - if (error) - goto close_file; - - /* Set "If-Modified-Since" header only if a value is specified */ - if (ims_value > 0) { - curl_easy_setopt(handler.curl, CURLOPT_TIMEVALUE, ims_value); - curl_easy_setopt(handler.curl, CURLOPT_TIMECONDITION, - CURL_TIMECOND_IFMODSINCE); - } + do { + error = http_easy_init(&handler); + if (error) + goto close_file; + + /* Set "If-Modified-Since" header only if a value is specified */ + if (ims_value > 0) { + curl_easy_setopt(handler.curl, CURLOPT_TIMEVALUE, ims_value); + curl_easy_setopt(handler.curl, CURLOPT_TIMECONDITION, + CURL_TIMECOND_IFMODSINCE); + } + error = http_fetch(&handler, uri_get_global(uri), response_code, + cond_met, log_operation, cb, out); + if (error != EREQFAILED) + break; + + if (retries == config_get_http_retry_count()) { + pr_val_warn("Max HTTP retries (%u) reached requesting for '%s', won't retry again.", + retries, uri_get_global(uri)); + break; + } + pr_val_warn("Retrying HTTP request '%s' in %u seconds, %u attempts remaining.", + uri_get_global(uri), + config_get_http_retry_interval(), + config_get_http_retry_count() - retries); + retries++; + http_easy_cleanup(&handler); + sleep(config_get_http_retry_interval()); + } while (true); - error = http_fetch(&handler, uri_get_global(uri), response_code, - cond_met, log_operation, cb, out); http_easy_cleanup(&handler); file_close(out); diff --git a/src/object/certificate.c b/src/object/certificate.c index de0b9d9e..878be517 100644 --- a/src/object/certificate.c +++ b/src/object/certificate.c @@ -2049,7 +2049,7 @@ use_access_method(struct sia_ca_uris *sia_uris, * care of that. */ (*retry_repo_sync) = true; - if (sia_uris->rpkiNotify.uri == NULL || !config_get_rrdp_enabled()) { + if (sia_uris->rpkiNotify.uri == NULL || !config_get_http_enabled()) { error = rsync_cb(sia_uris); goto verify_mft; } @@ -2083,12 +2083,12 @@ use_access_method(struct sia_ca_uris *sia_uris, } /* Use CA's or configured priority? */ - if (config_get_rsync_priority() == config_get_rrdp_priority()) + if (config_get_rsync_priority() == config_get_http_priority()) primary_rrdp = sia_uris->caRepository.position > sia_uris->rpkiNotify.position; else primary_rrdp = config_get_rsync_priority() - < config_get_rrdp_priority(); + < config_get_http_priority(); cb_primary = primary_rrdp ? rrdp_cb : rsync_cb; cb_secondary = primary_rrdp ? rsync_cb : rrdp_cb; diff --git a/src/object/tal.c b/src/object/tal.c index 2c940d68..cdf331b0 100644 --- a/src/object/tal.c +++ b/src/object/tal.c @@ -30,11 +30,14 @@ #include "rrdp/db/db_rrdp.h" #define TAL_FILE_EXTENSION ".tal" +typedef int (*foreach_uri_cb)(struct tal *, struct rpki_uri *, void *); struct uris { struct rpki_uri **array; /* This is an array of rpki URIs. */ unsigned int count; unsigned int size; + unsigned int rsync_count; + unsigned int https_count; }; struct tal { @@ -76,9 +79,11 @@ static int uris_init(struct uris *uris) { uris->count = 0; + uris->rsync_count = 0; + uris->https_count = 0; uris->size = 4; /* Most TALs only define one. */ uris->array = malloc(uris->size * sizeof(struct rpki_uri *)); - return (uris->array != NULL) ? 0 : -ENOMEM; + return (uris->array != NULL) ? 0 : pr_enomem(); } static void @@ -104,6 +109,11 @@ uris_add(struct uris *uris, char *uri) if (error) return error; + if (uri_is_rsync(new)) + uris->rsync_count++; + else + uris->https_count++; + if (uris->count + 1 >= uris->size) { uris->size *= 2; tmp = realloc(uris->array, @@ -409,7 +419,7 @@ foreach_uri(struct tal *tal, foreach_uri_cb cb, void *arg) return 0; } -void +static void tal_shuffle_uris(struct tal *tal) { struct rpki_uri **array = tal->uris.array; @@ -428,6 +438,48 @@ tal_shuffle_uris(struct tal *tal) } } +static int +tal_order_uris(struct tal *tal) +{ + struct rpki_uri **ordered; + struct rpki_uri **tmp; + bool http_first; + unsigned int i; + unsigned int last_rsync; + unsigned int last_https; + + /* First do the shuffle */ + if (config_get_shuffle_tal_uris()) + tal_shuffle_uris(tal); + + if (config_get_rsync_priority() == config_get_http_priority()) + return 0; + + /* Now order according to the priority */ + http_first = (config_get_http_priority() > config_get_rsync_priority()); + + ordered = malloc(tal->uris.size * sizeof(struct rpki_uri *)); + if (ordered == NULL) + return pr_enomem(); + + last_rsync = (http_first ? tal->uris.https_count : 0); + last_https = (http_first ? 0 : tal->uris.rsync_count); + + for (i = 0; i < tal->uris.count; i++) { + if (uri_is_rsync(tal->uris.array[i])) + ordered[last_rsync++] = tal->uris.array[i]; + else + ordered[last_https++] = tal->uris.array[i]; + } + + /* Everything is ok, point to the ordered array */ + tmp = tal->uris.array; + tal->uris.array = ordered; + free(tmp); + + return 0; +} + char const * tal_get_file_name(struct tal *tal) { @@ -514,8 +566,7 @@ handle_tal_uri(struct tal *tal, struct rpki_uri *uri, void *arg) error = download_files(uri, true, false); break; } - /* FIXME (later) Should be 'config_get_http_enabled()' */ - if (config_get_work_offline()) + if (!config_get_http_enabled()) return 0; /* Soft error */ error = handle_https_uri(uri); } while (0); @@ -637,8 +688,10 @@ do_file_validation(void *thread_arg) if (error) goto end; - if (config_get_shuffle_tal_uris()) - tal_shuffle_uris(tal); + error = tal_order_uris(tal); + if (error) + goto destroy_tal; + error = foreach_uri(tal, __handle_tal_uri_sync, thread_arg); if (error > 0) { error = 0; diff --git a/src/object/tal.h b/src/object/tal.h index 62227535..dba2644b 100644 --- a/src/object/tal.h +++ b/src/object/tal.h @@ -12,10 +12,6 @@ struct tal; int tal_load(char const *, struct tal **); void tal_destroy(struct tal *); -typedef int (*foreach_uri_cb)(struct tal *, struct rpki_uri *, void *); -int foreach_uri(struct tal *, foreach_uri_cb, void *); -void tal_shuffle_uris(struct tal *); - char const *tal_get_file_name(struct tal *); void tal_get_spki(struct tal *, unsigned char const **, size_t *); diff --git a/src/rrdp/rrdp_loader.c b/src/rrdp/rrdp_loader.c index 62be80c6..3755051e 100644 --- a/src/rrdp/rrdp_loader.c +++ b/src/rrdp/rrdp_loader.c @@ -115,7 +115,7 @@ rrdp_load(struct rpki_uri *uri) bool log_operation; int error, upd_error; - if (!config_get_rrdp_enabled()) + if (!config_get_http_enabled()) return 0; /* Avoid multiple requests on the same run */ diff --git a/src/rrdp/rrdp_parser.c b/src/rrdp/rrdp_parser.c index 7fecc65b..759ec3ef 100644 --- a/src/rrdp/rrdp_parser.c +++ b/src/rrdp/rrdp_parser.c @@ -112,40 +112,25 @@ write_local(unsigned char *content, size_t size, size_t nmemb, void *arg) static int download_file(struct rpki_uri *uri, long last_update, bool log_operation) { - unsigned int retries; int error; - retries = 0; - do { - if (last_update > 0) - error = http_download_file_with_ims(uri, write_local, - last_update, log_operation); - else - error = http_download_file(uri, write_local, - log_operation); + if (last_update > 0) + error = http_download_file_with_ims(uri, write_local, + last_update, log_operation); + else + error = http_download_file(uri, write_local, + log_operation); - /* Remember: positive values are expected */ - if (error >= 0) - return error; + /* + * Since distinct files can be downloaded (notification, snapshot, + * delta) just return the error and let the caller to add only the + * update notification URI to the request errors DB. + */ + if (error == -EREQFAILED) + return EREQFAILED; - if (retries == config_get_rrdp_retry_count()) { - pr_val_warn("Max RRDP retries (%u) reached fetching '%s', won't retry again.", - retries, uri_get_global(uri)); - /* - * Since distinct files can be downloaded (notification, - * snapshot, delta) just return the error and let the - * caller to add only the update notification URI to - * the request errors DB. - */ - return EREQFAILED; - } - pr_val_warn("Retrying RRDP file download '%s' in %u seconds, %u attempts remaining.", - uri_get_global(uri), - config_get_rrdp_retry_interval(), - config_get_rrdp_retry_count() - retries); - retries++; - sleep(config_get_rrdp_retry_interval()); - } while (true); + /* Remember: positive values are expected */ + return error; } /* Left trim @from, setting the result at @result pointer */ diff --git a/test/impersonator.c b/test/impersonator.c index 94b0a03e..3e82f904 100644 --- a/test/impersonator.c +++ b/test/impersonator.c @@ -10,6 +10,9 @@ static char addr_buffer1[INET6_ADDRSTRLEN]; static char addr_buffer2[INET6_ADDRSTRLEN]; +static unsigned int http_priority = 60; +static unsigned int rsync_priority = 50; + char const * v4addr2str(struct in_addr const *addr) { @@ -85,19 +88,19 @@ config_get_rsync_enabled(void) unsigned int config_get_rsync_priority(void) { - return 50; + return rsync_priority; } bool -config_get_rrdp_enabled(void) +config_get_http_enabled(void) { return false; } unsigned int -config_get_rrdp_priority(void) +config_get_http_priority(void) { - return 50; + return http_priority; } bool @@ -286,3 +289,15 @@ config_get_http_ca_path(void) { return NULL; } + +void +config_set_rsync_priority(unsigned int value) +{ + rsync_priority = value; +} + +void +config_set_http_priority(unsigned int value) +{ + http_priority = value; +} diff --git a/test/tal_test.c b/test/tal_test.c index 797b15f6..ad65c7c0 100644 --- a/test/tal_test.c +++ b/test/tal_test.c @@ -149,16 +149,59 @@ START_TEST(tal_load_normal) } END_TEST +START_TEST(tal_order_http_first) +{ + struct tal *tal; + + ck_assert_int_eq(tal_load("tal/lacnic.tal", &tal), 0); + + config_set_http_priority(60); + config_set_rsync_priority(50); + ck_assert_int_eq(tal_order_uris(tal), 0); + + ck_assert_str_eq(tal->uris.array[0]->global, "https://potato"); + ck_assert_str_eq(tal->uris.array[1]->global, + "rsync://repository.lacnic.net/rpki/lacnic/rta-lacnic-rpki.cer"); + ck_assert_str_eq(tal->uris.array[2]->global, "rsync://potato"); + + tal_destroy(tal); +} +END_TEST + +START_TEST(tal_order_http_last) +{ + struct tal *tal; + + ck_assert_int_eq(tal_load("tal/lacnic.tal", &tal), 0); + + config_set_http_priority(50); + config_set_rsync_priority(60); + ck_assert_int_eq(tal_order_uris(tal), 0); + + ck_assert_str_eq(tal->uris.array[0]->global, + "rsync://repository.lacnic.net/rpki/lacnic/rta-lacnic-rpki.cer"); + ck_assert_str_eq(tal->uris.array[1]->global, "rsync://potato"); + ck_assert_str_eq(tal->uris.array[2]->global, "https://potato"); + + tal_destroy(tal); +} +END_TEST + Suite *tal_load_suite(void) { Suite *suite; - TCase *core; + TCase *core, *order; core = tcase_create("Core"); tcase_add_test(core, tal_load_normal); - suite = suite_create("lfile_read()"); + order = tcase_create("Order"); + tcase_add_test(order, tal_order_http_first); + tcase_add_test(order, tal_order_http_last); + + suite = suite_create("tal_load()"); suite_add_tcase(suite, core); + suite_add_tcase(suite, order); return suite; }