From: pcarana Date: Fri, 17 Jan 2020 23:40:18 +0000 (-0600) Subject: Avoid HTTP requests on previously error'd URIs. X-Git-Tag: v1.2.0~15 X-Git-Url: http://git.ipfire.org/gitweb/gitweb.cgi?a=commitdiff_plain;h=149f1788ccce259fdbe579c02eb3f647ada40a09;p=thirdparty%2FFORT-validator.git Avoid HTTP requests on previously error'd URIs. +Create type to set RRDP URIs request status (error, unvisited, visited). The status is set accordingly to the result of the last request and processing of the RRDP Update Notification URIs; during RRDP loading, the status is validated to either do a request (URIs hasn't been visited) or skip it (was previously visited or had an error). If a request had an error, then continue the access methods flow considering priorities. +Update RET_NOT_FOUND_URI macro, it always returned the same error code. +Remove downloaded files via HTTP (and its local directory structure) whenever there's an error during the download process. --- diff --git a/src/http/http.c b/src/http/http.c index a55faf08..3ae0f89b 100644 --- a/src/http/http.c +++ b/src/http/http.c @@ -146,7 +146,7 @@ __http_download_file(struct rpki_uri *uri, http_write_cb cb, error = file_write(uri_get_local(uri), &out, &stat); if (error) - return ENSURE_NEGATIVE(error); + goto delete_dir; error = http_easy_init(&handler); if (error) @@ -164,10 +164,13 @@ __http_download_file(struct rpki_uri *uri, http_write_cb cb, http_easy_cleanup(&handler); file_close(out); - /* Error 0 it's ok */ - return ENSURE_NEGATIVE(error); + if (error) + goto delete_dir; + + return 0; close_file: file_close(out); +delete_dir: delete_dir_recursive_bottom_up(uri_get_local(uri)); return ENSURE_NEGATIVE(error); } diff --git a/src/object/certificate.c b/src/object/certificate.c index 5def8cab..3b720ec4 100644 --- a/src/object/certificate.c +++ b/src/object/certificate.c @@ -1930,14 +1930,20 @@ use_access_method(struct sia_ca_uris *sia_uris, if (!error) return 0; - if (primary_rrdp) - pr_warn("Couldn't fetch data from RRDP repository '%s', trying to fetch data now from '%s'.", - uri_get_global(sia_uris->rpkiNotify.uri), - uri_get_global(sia_uris->caRepository.uri)); - else + if (primary_rrdp) { + if (error != -EPERM) + pr_warn("Couldn't fetch data from RRDP repository '%s', trying to fetch data now from '%s'.", + uri_get_global(sia_uris->rpkiNotify.uri), + uri_get_global(sia_uris->caRepository.uri)); + else + pr_debug("RRDP repository '%s' download/processing returned error previously, now I will try to fetch data from '%s'.", + uri_get_global(sia_uris->rpkiNotify.uri), + uri_get_global(sia_uris->caRepository.uri)); + } else { pr_warn("Couldn't fetch data from repository '%s', trying to fetch data now from RRDP '%s'.", uri_get_global(sia_uris->caRepository.uri), uri_get_global(sia_uris->rpkiNotify.uri)); + } return cb_secondary(sia_uris); } diff --git a/src/object/tal.c b/src/object/tal.c index 187f154a..d1b908e2 100644 --- a/src/object/tal.c +++ b/src/object/tal.c @@ -510,7 +510,7 @@ handle_tal_uri(struct tal *tal, struct rpki_uri *uri, void *arg) * Set all RRDPs URIs to non-requested, this way we will force the * request on every cycle (to check if there are updates). */ - error = db_rrdp_uris_set_all_nonrequested(); + error = db_rrdp_uris_set_all_unvisited(); if (error) goto end; diff --git a/src/rrdp/db/db_rrdp_uris.c b/src/rrdp/db/db_rrdp_uris.c index e99c6b3b..b00a222a 100644 --- a/src/rrdp/db/db_rrdp_uris.c +++ b/src/rrdp/db/db_rrdp_uris.c @@ -16,7 +16,7 @@ struct uris_table { /* Last local update of the URI (after a successful processing) */ long last_update; /* The URI has been requested (HTTPS) at this cycle? */ - bool requested; + rrdp_req_status_t request_status; /* MFT URIs loaded from the @uri */ struct visited_uris *visited_uris; UT_hash_handle hh; @@ -28,7 +28,8 @@ struct db_rrdp_uri { static int uris_table_create(char const *uri, char const *session_id, - unsigned long serial, struct uris_table **result) + unsigned long serial, rrdp_req_status_t req_status, + struct uris_table **result) { struct uris_table *tmp; int error; @@ -53,7 +54,7 @@ uris_table_create(char const *uri, char const *session_id, tmp->data.serial = serial; tmp->last_update = 0; - tmp->requested = true; + tmp->request_status = req_status; tmp->visited_uris = NULL; *result = tmp; @@ -82,10 +83,10 @@ find_rrdp_uri(struct db_rrdp_uri *uris, const char *search) return found; } -#define RET_NOT_FOUND_URI(uris, search, found, retval) \ +#define RET_NOT_FOUND_URI(uris, search, found) \ found = find_rrdp_uri(uris, search); \ if (found == NULL) \ - return retval; + return -ENOENT; static void add_rrdp_uri(struct db_rrdp_uri *uris, struct uris_table *new_uri) @@ -175,7 +176,8 @@ db_rrdp_uris_cmp(char const *uri, char const *session_id, unsigned long serial, int db_rrdp_uris_update(char const *uri, char const *session_id, - unsigned long serial, struct visited_uris *visited_uris) + unsigned long serial, rrdp_req_status_t req_status, + struct visited_uris *visited_uris) { struct db_rrdp_uri *uris; struct uris_table *db_uri; @@ -186,7 +188,7 @@ db_rrdp_uris_update(char const *uri, char const *session_id, return error; db_uri = NULL; - error = uris_table_create(uri, session_id, serial, &db_uri); + error = uris_table_create(uri, session_id, serial, req_status, &db_uri); if (error) return error; @@ -209,7 +211,7 @@ db_rrdp_uris_get_serial(char const *uri, unsigned long *serial) if (error) return error; - RET_NOT_FOUND_URI(uris, uri, found, -ENOENT) + RET_NOT_FOUND_URI(uris, uri, found) *serial = found->data.serial; return 0; } @@ -225,7 +227,7 @@ db_rrdp_uris_get_last_update(char const *uri, long *date) if (error) return error; - RET_NOT_FOUND_URI(uris, uri, found, -ENOENT) + RET_NOT_FOUND_URI(uris, uri, found) *date = found->last_update; return 0; } @@ -255,12 +257,12 @@ db_rrdp_uris_set_last_update(char const *uri) if (error) return error; - RET_NOT_FOUND_URI(uris, uri, found, -ENOENT) + RET_NOT_FOUND_URI(uris, uri, found) return get_current_time(&found->last_update); } int -db_rrdp_uris_get_requested(char const *uri, bool *result) +db_rrdp_uris_get_request_status(char const *uri, rrdp_req_status_t *result) { struct db_rrdp_uri *uris; struct uris_table *found; @@ -270,13 +272,13 @@ db_rrdp_uris_get_requested(char const *uri, bool *result) if (error) return error; - RET_NOT_FOUND_URI(uris, uri, found, -ENOENT) - *result = found->requested; + RET_NOT_FOUND_URI(uris, uri, found) + *result = found->request_status; return 0; } int -db_rrdp_uris_set_requested(char const *uri, bool value) +db_rrdp_uris_set_request_status(char const *uri, rrdp_req_status_t value) { struct db_rrdp_uri *uris; struct uris_table *found; @@ -286,13 +288,13 @@ db_rrdp_uris_set_requested(char const *uri, bool value) if (error) return error; - RET_NOT_FOUND_URI(uris, uri, found, -ENOENT) - found->requested = value; + RET_NOT_FOUND_URI(uris, uri, found) + found->request_status = value; return 0; } int -db_rrdp_uris_set_all_nonrequested(void) +db_rrdp_uris_set_all_unvisited(void) { struct db_rrdp_uri *uris; struct uris_table *uri_node, *uri_tmp; @@ -303,7 +305,7 @@ db_rrdp_uris_set_all_nonrequested(void) return error; HASH_ITER(hh, uris->table, uri_node, uri_tmp) - uri_node->requested = false; + uri_node->request_status = RRDP_URI_REQ_UNVISITED; return 0; } @@ -323,7 +325,7 @@ db_rrdp_uris_get_visited_uris(char const *uri, struct visited_uris **result) if (error) return error; - RET_NOT_FOUND_URI(uris, uri, found, -ENOENT) + RET_NOT_FOUND_URI(uris, uri, found) *result = found->visited_uris; return 0; } diff --git a/src/rrdp/db/db_rrdp_uris.h b/src/rrdp/db/db_rrdp_uris.h index f221987a..737c38bd 100644 --- a/src/rrdp/db/db_rrdp_uris.h +++ b/src/rrdp/db/db_rrdp_uris.h @@ -5,6 +5,12 @@ #include "rrdp/rrdp_objects.h" #include "visited_uris.h" +typedef enum { + RRDP_URI_REQ_ERROR, + RRDP_URI_REQ_UNVISITED, + RRDP_URI_REQ_VISITED, +} rrdp_req_status_t; + /* * RRDP URI fetched from 'rpkiNotify' OID at a CA certificate, each TAL thread * may have a reference to one of these (it holds information such as update @@ -18,15 +24,15 @@ void db_rrdp_uris_destroy(struct db_rrdp_uri *); int db_rrdp_uris_cmp(char const *, char const *, unsigned long, rrdp_uri_cmp_result_t *); int db_rrdp_uris_update(char const *, char const *session_id, unsigned long, - struct visited_uris *); + rrdp_req_status_t, struct visited_uris *); int db_rrdp_uris_get_serial(char const *, unsigned long *); int db_rrdp_uris_get_last_update(char const *, long *); int db_rrdp_uris_set_last_update(char const *); -int db_rrdp_uris_get_requested(char const *, bool *); -int db_rrdp_uris_set_requested(char const *, bool); -int db_rrdp_uris_set_all_nonrequested(void); +int db_rrdp_uris_get_request_status(char const *, rrdp_req_status_t *); +int db_rrdp_uris_set_request_status(char const *, rrdp_req_status_t); +int db_rrdp_uris_set_all_unvisited(void); int db_rrdp_uris_get_visited_uris(char const *, struct visited_uris **); diff --git a/src/rrdp/rrdp_loader.c b/src/rrdp/rrdp_loader.c index 40913b48..301abf70 100644 --- a/src/rrdp/rrdp_loader.c +++ b/src/rrdp/rrdp_loader.c @@ -65,30 +65,73 @@ remove_rrdp_uri_files(char const *notification_uri) return visited_uris_remove_local(tmp); } +/* Mark the URI as errored with dummy data, so it won't be requested again */ +static int +mark_rrdp_uri_request_err(char const *notification_uri) +{ + struct visited_uris *tmp; + int error; + + pr_debug("RRDP data of '%s' won't be requested again during this cycle due to previous error.", + notification_uri); + + error = visited_uris_create(&tmp); + if (error) + return error; + + error = db_rrdp_uris_update(notification_uri, "", 0, + RRDP_URI_REQ_ERROR, tmp); + if (error) { + visited_uris_refput(tmp); + return error; + } + + return 0; +} + +/* + * Try to get RRDP Update Notification file and process it accordingly. + * + * If there's an error that could lead to an inconsistent local repository + * state, marks the @uri as error'd so that it won't be requested again during + * the same validation cycle. + * + * If there are no errors, updates the local DB and marks the @uri as visited. + * + * If the @uri is being visited again, verify its previous visit state. If there + * were no errors, just return success; otherwise, return error code -EPERM. + */ int rrdp_load(struct rpki_uri *uri) { struct update_notification *upd_notification; struct visited_uris *visited; + rrdp_req_status_t requested; rrdp_uri_cmp_result_t res; - int error; - bool requested; + int error, upd_error; if (!config_get_rrdp_enabled()) return 0; /* Avoid multiple requests on the same run */ - requested = false; - error = db_rrdp_uris_get_requested(uri_get_global(uri), &requested); + requested = RRDP_URI_REQ_UNVISITED; + error = db_rrdp_uris_get_request_status(uri_get_global(uri), &requested); if (error && error != -ENOENT) return error; - if (requested) + switch(requested) { + case RRDP_URI_REQ_VISITED: return 0; + case RRDP_URI_REQ_UNVISITED: + break; + case RRDP_URI_REQ_ERROR: + /* Log has been done before this call */ + return -EPERM; + } error = rrdp_parse_notification(uri, &upd_notification); if (error) - return error; + goto upd_error; /* No updates at the file (yet), didn't pushed to fnstack */ if (upd_notification == NULL) { @@ -101,7 +144,7 @@ rrdp_load(struct rpki_uri *uri) upd_notification->global_data.serial, &res); if (error) - goto end; + goto upd_destroy; switch (res) { case RRDP_URI_EQUAL: @@ -127,7 +170,7 @@ rrdp_load(struct rpki_uri *uri) } if (error) - goto end; + goto upd_destroy; /* Any update, and no error during the process, update db as well */ pr_debug("Updating local RRDP data of '%s' to:", uri_get_global(uri)); @@ -136,20 +179,27 @@ rrdp_load(struct rpki_uri *uri) error = db_rrdp_uris_update(uri_get_global(uri), upd_notification->global_data.session_id, upd_notification->global_data.serial, + RRDP_URI_REQ_VISITED, visited); if (error) - goto end; + goto upd_destroy; set_update: /* Set the last update to now */ pr_debug("Set last update of RRDP data of '%s' to now.", uri_get_global(uri)); - error = db_rrdp_uris_set_last_update(uri_get_global(uri)); -end: + db_rrdp_uris_set_last_update(uri_get_global(uri)); +upd_destroy: if (upd_notification != NULL) { update_notification_destroy(upd_notification); fnstack_pop(); /* Pop from rrdp_parse_notification */ } - +upd_error: + /* Don't fall here on success */ + if (error) { + upd_error = mark_rrdp_uri_request_err(uri_get_global(uri)); + if (upd_error) + return upd_error; + } return error; } diff --git a/src/rrdp/rrdp_parser.c b/src/rrdp/rrdp_parser.c index 9780b0af..55bad006 100644 --- a/src/rrdp/rrdp_parser.c +++ b/src/rrdp/rrdp_parser.c @@ -1120,9 +1120,10 @@ rrdp_parse_notification(struct rpki_uri *uri, * this is probably the first time is visited (first run), so it will * be marked as visited when the URI is stored at DB. */ - vis_err = db_rrdp_uris_set_requested(uri_get_global(uri), true); + vis_err = db_rrdp_uris_set_request_status(uri_get_global(uri), + RRDP_URI_REQ_VISITED); if (vis_err && vis_err != -ENOENT) - return pr_err("Coudln't mark '%s' as visited", + return pr_err("Couldn't mark '%s' as visited", uri_get_global(uri)); /* No updates yet */