From 2d542a31aa8ab42443fc44c57759127c9a8fc06e Mon Sep 17 00:00:00 2001 From: pcarana Date: Tue, 10 Dec 2019 18:30:53 -0600 Subject: [PATCH] Remember which manifests where fetched using RRDP, remove rrdp_handler. +Remember all manifests URIs that were processed from a snapshot or delta file, this will aid to avoid unnecessary rsync's on child CAs. +Create 'visited_uris' struct and methods to remember URIs from RRDP snapshot/delta file(s). This should be updated to use another struct more efficient than an SLIST. +Remove 'rrdp_handler' and do its calls directly where needed. +Add warning message whenever an access method fails and the secondary access method is utilized. +Assure that RRDP Update Notification URIs are visited only once per validation run. +In case there's a manifest error, don't retry the repository download if the accessMethod to get the manifest was RRDP. --- src/Makefile.am | 2 +- src/http/http.c | 2 +- src/main.c | 7 +++ src/object/certificate.c | 50 +++++++++++---- src/object/tal.c | 10 +-- src/rrdp/db_rrdp.c | 39 ++++++++++++ src/rrdp/db_rrdp.h | 4 ++ src/rrdp/rrdp_handler.c | 64 ------------------- src/rrdp/rrdp_handler.h | 47 -------------- src/rrdp/rrdp_loader.c | 28 ++++----- src/rrdp/rrdp_parser.c | 54 ++++++++++++++-- src/rrdp/rrdp_parser.h | 3 +- src/rtr/db/vrps.c | 37 +++++++++++ src/rtr/db/vrps.h | 2 + src/state.c | 16 +---- src/state.h | 6 +- src/visited_uris.c | 132 +++++++++++++++++++++++++++++++++++++++ src/visited_uris.h | 13 ++++ test/tal_test.c | 3 +- 19 files changed, 343 insertions(+), 176 deletions(-) delete mode 100644 src/rrdp/rrdp_handler.c delete mode 100644 src/rrdp/rrdp_handler.h create mode 100644 src/visited_uris.c create mode 100644 src/visited_uris.h diff --git a/src/Makefile.am b/src/Makefile.am index d78bf133..1debbcf4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -34,6 +34,7 @@ fort_SOURCES += updates_daemon.c updates_daemon.h fort_SOURCES += uri.h uri.c fort_SOURCES += json_handler.h json_handler.c fort_SOURCES += validation_handler.h validation_handler.c +fort_SOURCES += visited_uris.h visited_uris.c fort_SOURCES += asn1/content_info.h asn1/content_info.c fort_SOURCES += asn1/decode.h asn1/decode.c @@ -81,7 +82,6 @@ fort_SOURCES += resource/ip6.h resource/ip6.c fort_SOURCES += resource/asn.h resource/asn.c fort_SOURCES += rrdp/db_rrdp.h rrdp/db_rrdp.c -fort_SOURCES += rrdp/rrdp_handler.h rrdp/rrdp_handler.c fort_SOURCES += rrdp/rrdp_loader.h rrdp/rrdp_loader.c fort_SOURCES += rrdp/rrdp_objects.h rrdp/rrdp_objects.c fort_SOURCES += rrdp/rrdp_parser.h rrdp/rrdp_parser.c diff --git a/src/http/http.c b/src/http/http.c index 3d848025..cd10ce1a 100644 --- a/src/http/http.c +++ b/src/http/http.c @@ -184,7 +184,7 @@ http_download_file(struct rpki_uri *uri, http_write_cb cb) * Fetch the file from @uri, write it using the @cb. * * The HTTP request is made using the header 'If-Modified-Since' with a value - * of @value. + * of @value (if @value is 0, the header isn't set). * * Returns: * > 0 file was requested but wasn't downloaded since the server didn't sent diff --git a/src/main.c b/src/main.c index cac02d9f..722f753b 100644 --- a/src/main.c +++ b/src/main.c @@ -4,6 +4,7 @@ #include "extension.h" #include "nid.h" #include "thread_var.h" +#include "visited_uris.h" #include "http/http.h" #include "rtr/rtr.h" #include "rtr/db/vrps.h" @@ -18,8 +19,14 @@ start_rtr_server(void) if (error) goto just_quit; + error = visited_uris_init(); + if (error) + goto vrps_cleanup; + error = rtr_listen(); + visited_uris_destroy(); +vrps_cleanup: vrps_destroy(); just_quit: return error; diff --git a/src/object/certificate.c b/src/object/certificate.c index 3b3cfdf3..de8dcf3f 100644 --- a/src/object/certificate.c +++ b/src/object/certificate.c @@ -11,6 +11,7 @@ #include "nid.h" #include "str.h" #include "thread_var.h" +#include "visited_uris.h" #include "asn1/decode.h" #include "asn1/oid.h" #include "asn1/asn1c/IPAddrBlocks.h" @@ -1899,6 +1900,7 @@ use_access_method(struct sia_ca_uris *sia_uris, { access_method_exec *cb_primary; access_method_exec *cb_secondary; + bool primary_rrdp; int error; /* @@ -1912,9 +1914,11 @@ use_access_method(struct sia_ca_uris *sia_uris, if (sia_uris->caRepository.position > sia_uris->rpkiNotify.position) { cb_primary = rrdp_cb; cb_secondary = rsync_cb; + primary_rrdp = true; } else { cb_primary = rsync_cb; cb_secondary = rrdp_cb; + primary_rrdp = false; } /* Try with the preferred; in case of error, try with the next one */ @@ -1922,6 +1926,15 @@ 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 + 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); } @@ -1942,7 +1955,7 @@ certificate_traverse(struct rpp *rpp_parent, struct rpki_uri *cert_uri) enum rpki_policy policy; enum cert_type type; struct rpp *pp; - bool mft_retry; + bool mft_retry, mft_exists; int error; state = state_retrieve(); @@ -2036,8 +2049,6 @@ certificate_traverse(struct rpp *rpp_parent, struct rpki_uri *cert_uri) } /* - * FIXME (now) Beware: what if RRDP is already being utilized? - * * There isn't any restriction about the preferred access method of * children CAs being the same as the parent CA. * @@ -2050,18 +2061,33 @@ certificate_traverse(struct rpp *rpp_parent, struct rpki_uri *cert_uri) * Step (2) must do something different. * - The manifest should exist at the snapshot file (aka, directory * structure), so it should be processed from there on. - * - Verify that the manifest file exists locally (must be the same - * session_id and serial, load those at start, the serial can - * be written to a local file, the session_id can be loaded from the - * directory structure /rrdp/).: + * - Verify that the manifest file exists locally: * + Exists: Read and process normally (no need to do rsync) * + Doesn't exists: check for preferred access method, keep the flow * from there on. */ - error = use_access_method(&sia_uris, exec_rsync_method, - exec_rrdp_method); - if (error) - return error; + + /* Avoid to re-download the repo if the mft was fetched with RRDP */ + mft_exists = false; + switch (type) { + case TA: + error = use_access_method(&sia_uris, exec_rsync_method, + exec_rrdp_method); + if (error) + return error; + break; + case CA: + if (!visited_uris_exists(uri_get_global(sia_uris.mft.uri))) { + mft_exists = true; + error = use_access_method(&sia_uris, exec_rsync_method, + exec_rrdp_method); + if (error) + return error; + } + break; + default: + break; + } /* * RFC 6481 section 5: "when the repository publication point contents @@ -2087,7 +2113,7 @@ certificate_traverse(struct rpp *rpp_parent, struct rpki_uri *cert_uri) error = handle_manifest(sia_uris.mft.uri, &pp); if (!mft_retry) uri_refput(sia_uris.mft.uri); - if (!error || !mft_retry) + if (!error || !mft_retry || mft_exists) break; pr_info("Retrying repository download to discard 'transient inconsistency' manifest issue (see RFC 6481 section 5) '%s'", diff --git a/src/object/tal.c b/src/object/tal.c index 9674c40f..f81f9b4b 100644 --- a/src/object/tal.c +++ b/src/object/tal.c @@ -469,7 +469,6 @@ handle_tal_uri(struct tal *tal, struct rpki_uri *uri, void *arg) */ struct validation_handler validation_handler; - struct rrdp_handler rrdp_handler; struct validation *state; struct cert_stack *certstack; struct deferred_cert deferred; @@ -480,14 +479,7 @@ handle_tal_uri(struct tal *tal, struct rpki_uri *uri, void *arg) validation_handler.handle_router_key = handle_router_key; validation_handler.arg = arg; - rrdp_handler.uri_cmp = rrdp_uri_cmp; - rrdp_handler.uri_update = rrdp_uri_update; - rrdp_handler.uri_get_serial = rrdp_uri_get_serial; - rrdp_handler.uri_get_last_update = rrdp_uri_get_last_update; - rrdp_handler.uri_set_last_update = rrdp_uri_set_last_update; - - error = validation_prepare(&state, tal, &validation_handler, - &rrdp_handler); + error = validation_prepare(&state, tal, &validation_handler); if (error) return ENSURE_NEGATIVE(error); diff --git a/src/rrdp/db_rrdp.c b/src/rrdp/db_rrdp.c index 86e36b3e..82053576 100644 --- a/src/rrdp/db_rrdp.c +++ b/src/rrdp/db_rrdp.c @@ -1,6 +1,7 @@ #include "db_rrdp.h" #include +#include #include #include #include "data_structure/uthash_nonfatal.h" @@ -12,6 +13,7 @@ struct db_rrdp_uri { char *uri; struct global_data data; long last_update; + bool visited; UT_hash_handle hh; }; @@ -59,6 +61,7 @@ db_rrdp_uri_create(char const *uri, char const *session_id, tmp->data.serial = serial; tmp->last_update = 0; + tmp->visited = true; *result = tmp; return 0; @@ -179,6 +182,42 @@ db_rrdp_set_last_update(struct db_rrdp *db, char const *uri) return get_current_time(&found->last_update); } +bool +db_rrdp_get_visited(struct db_rrdp *db, char const *uri) +{ + struct db_rrdp_uri *found; + + HASH_FIND_STR(db->uris, uri, found); + if (found == NULL) + return false; + + return found->visited; +} + +int +db_rrdp_set_visited(struct db_rrdp *db, char const *uri, bool value) +{ + struct db_rrdp_uri *found; + + HASH_FIND_STR(db->uris, uri, found); + if (found == NULL) + return -ENOENT; + + found->visited = value; + return 0; +} + +int +db_rrdp_set_all_nonvisited(struct db_rrdp *db) +{ + struct db_rrdp_uri *uri_node, *uri_tmp; + + HASH_ITER(hh, db->uris, uri_node, uri_tmp) + uri_node->visited = false; + + return 0; +} + int db_rrdp_create(struct db_rrdp **result) { diff --git a/src/rrdp/db_rrdp.h b/src/rrdp/db_rrdp.h index 9aca0769..0339bf8a 100644 --- a/src/rrdp/db_rrdp.h +++ b/src/rrdp/db_rrdp.h @@ -21,4 +21,8 @@ int db_rrdp_get_last_update(struct db_rrdp *, char const *, long *); int db_rrdp_set_last_update(struct db_rrdp *, char const *); +bool db_rrdp_get_visited(struct db_rrdp *, char const *); +int db_rrdp_set_visited(struct db_rrdp *, char const *, bool); +int db_rrdp_set_all_nonvisited(struct db_rrdp *); + #endif /* SRC_RRDP_DB_RRDP_H_ */ diff --git a/src/rrdp/rrdp_handler.c b/src/rrdp/rrdp_handler.c deleted file mode 100644 index 94a9eb05..00000000 --- a/src/rrdp/rrdp_handler.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "rrdp_handler.h" - -#include "thread_var.h" - -#define CALL_HANDLER_FUNC(func_name, func_call) \ - struct rrdp_handler const *handler; \ - int error; \ - \ - error = get_current_threads_handler(&handler); \ - if (error) \ - return error; \ - \ - return (handler->func_name != NULL) \ - ? handler->func_call \ - : 0; - -static int -get_current_threads_handler(struct rrdp_handler const **result) -{ - struct validation *state; - struct rrdp_handler const *handler; - - state = state_retrieve(); - if (state == NULL) - return -EINVAL; - - handler = validation_get_rrdp_handler(state); - if (handler == NULL) - pr_crit("This thread lacks an RRDP handler."); - - *result = handler; - return 0; -} - -rrdp_uri_cmp_result_t -rhandler_uri_cmp(char const *uri, char const *session_id, unsigned long serial) -{ - CALL_HANDLER_FUNC(uri_cmp, uri_cmp(uri, session_id, serial)) -} - -int -rhandler_uri_update(char const *uri, char const *session_id, - unsigned long serial) -{ - CALL_HANDLER_FUNC(uri_update, uri_update(uri, session_id, serial)) -} - -int -rhandler_uri_get_serial(char const *uri, unsigned long *serial) -{ - CALL_HANDLER_FUNC(uri_get_serial, uri_get_serial(uri, serial)) -} - -int -rhandler_uri_get_last_update(char const *uri, long *serial) -{ - CALL_HANDLER_FUNC(uri_get_last_update, uri_get_last_update(uri, serial)) -} - -int -rhandler_uri_set_last_update(char const *uri) -{ - CALL_HANDLER_FUNC(uri_set_last_update, uri_set_last_update(uri)) -} diff --git a/src/rrdp/rrdp_handler.h b/src/rrdp/rrdp_handler.h deleted file mode 100644 index db6f7327..00000000 --- a/src/rrdp/rrdp_handler.h +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef SRC_RRDP_RRDP_HANDLER_H_ -#define SRC_RRDP_RRDP_HANDLER_H_ - -#include "rrdp/rrdp_objects.h" - -/* - * Almost the same idea as 'validation_handler.h', only that the main focus is - * a multithreaded environment. - * - * The RRDP URIs are expected to live at the main thread, the other threads can - * access such URIs. The handler must assure that the data is safe - * (handle r/w locks), that's the reason why there isn't any reference to a - * 'db_rrdp' struct. - */ - -struct rrdp_handler { - /* - * Search the RRDP URI, returns the corresponding enum to indicate - * the comparison result. - */ - rrdp_uri_cmp_result_t (*uri_cmp)(char const *, char const *, - unsigned long); - /* Add or update an RRDP URI */ - int (*uri_update)(char const *, char const *, unsigned long); - /* - * Get the serial related to an URI, returns -ENOENT if the URI doesn't - * exists, any other error means that something went wrong. - */ - int (*uri_get_serial)(char const *, unsigned long *); - /* - * Get the last update that an URI was requested, returns -ENOENT if - * the URI doesn't exists, any other error means that something went - * wrong. - */ - int (*uri_get_last_update)(char const *, long *); - /* Set the last update to now */ - int (*uri_set_last_update)(char const *); -}; - -rrdp_uri_cmp_result_t rhandler_uri_cmp(char const *, char const *, - unsigned long); -int rhandler_uri_update(char const *, char const *, unsigned long); -int rhandler_uri_get_serial(char const *, unsigned long *); -int rhandler_uri_get_last_update(char const *, long *); -int rhandler_uri_set_last_update(char const *); - -#endif /* SRC_RRDP_RRDP_HANDLER_H_ */ diff --git a/src/rrdp/rrdp_loader.c b/src/rrdp/rrdp_loader.c index 1ff706bc..ce7523ce 100644 --- a/src/rrdp/rrdp_loader.c +++ b/src/rrdp/rrdp_loader.c @@ -1,8 +1,8 @@ #include "rrdp_loader.h" -#include "rrdp/rrdp_handler.h" #include "rrdp/rrdp_objects.h" #include "rrdp/rrdp_parser.h" +#include "rtr/db/vrps.h" #include "log.h" #include "thread_var.h" @@ -13,7 +13,7 @@ process_diff_serial(struct update_notification *notification, char const *uri) unsigned long serial; int error; - error = rhandler_uri_get_serial(uri, &serial); + error = rrdp_uri_get_serial(uri, &serial); if (error) return error; @@ -32,23 +32,21 @@ rrdp_load(struct rpki_uri *uri) { struct update_notification *upd_notification; rrdp_uri_cmp_result_t res; - long last_update; int error; - last_update = 0; - error = rhandler_uri_get_last_update(uri_get_global(uri), &last_update); - if (error && error != -ENOENT) - return error; + /* Avoid multiple requests on the same run */ + if (rrdp_uri_visited(uri_get_global(uri))) + return 0; - error = rrdp_parse_notification(uri, last_update, &upd_notification); + error = rrdp_parse_notification(uri, &upd_notification); if (error) return error; - /* No updates at the file (yet) */ + /* No updates at the file (yet), didn't pushed to fnstack */ if (upd_notification == NULL) return 0; - res = rhandler_uri_cmp(uri_get_global(uri), + res = rrdp_uri_cmp(uri_get_global(uri), upd_notification->global_data.session_id, upd_notification->global_data.serial); switch (res) { @@ -74,7 +72,7 @@ rrdp_load(struct rpki_uri *uri) /* Any change, and no error during the process, update db */ if (!error) { - error = rhandler_uri_update(uri_get_global(uri), + error = rrdp_uri_update(uri_get_global(uri), upd_notification->global_data.session_id, upd_notification->global_data.serial); if (error) @@ -83,10 +81,12 @@ rrdp_load(struct rpki_uri *uri) set_update: /* Set the last update to now */ - error = rhandler_uri_set_last_update(uri_get_global(uri)); + error = rrdp_uri_set_last_update(uri_get_global(uri)); end: - update_notification_destroy(upd_notification); - fnstack_pop(); /* Pop from rrdp_parse_notification */ + if (upd_notification != NULL) { + update_notification_destroy(upd_notification); + fnstack_pop(); /* Pop from rrdp_parse_notification */ + } return error; } diff --git a/src/rrdp/rrdp_parser.c b/src/rrdp/rrdp_parser.c index 43fca005..f8839769 100644 --- a/src/rrdp/rrdp_parser.c +++ b/src/rrdp/rrdp_parser.c @@ -13,12 +13,13 @@ #include "crypto/base64.h" #include "crypto/hash.h" #include "http/http.h" -#include "rrdp/rrdp_handler.h" +#include "rtr/db/vrps.h" #include "xml/relax_ng.h" #include "common.h" #include "file.h" #include "log.h" #include "thread_var.h" +#include "visited_uris.h" /* XML Common Namespace of files */ #define RRDP_NAMESPACE "http://www.ripe.net/rpki/rrdp" @@ -71,6 +72,24 @@ struct rdr_delta_ctx { unsigned long expected_serial; }; +static int +add_mft_to_list(char const *uri) +{ + if (strcmp(".mft", strrchr(uri, '.')) != 0) + return 0; + + return visited_uris_add(uri); +} + +static int +rem_mft_from_list(char const *uri) +{ + if (strcmp(".mft", strrchr(uri, '.')) != 0) + return 0; + + return visited_uris_remove(uri); +} + static size_t write_local(unsigned char *content, size_t size, size_t nmemb, void *arg) { @@ -574,6 +593,13 @@ write_from_uri(char const *location, unsigned char *content, size_t content_len) uri_get_local(uri)); } + error = add_mft_to_list(uri_get_global(uri)); + if (error) { + uri_refput(uri); + file_close(out); + return error; + } + uri_refput(uri); file_close(out); return 0; @@ -632,6 +658,10 @@ delete_from_uri(char const *location) goto release_str; } while (true); + error = rem_mft_from_list(uri_get_global(uri)); + if (error) + goto release_str; + uri_refput(uri); free(local_uri); return 0; @@ -695,7 +725,7 @@ rdr_notification_ctx_init(struct rdr_notification_ctx *ctx) ctx->create_snapshot = false; - res = rhandler_uri_cmp(ctx->uri, + res = rrdp_uri_cmp(ctx->uri, ctx->notification->global_data.session_id, ctx->notification->global_data.serial); switch (res) { @@ -1045,18 +1075,34 @@ release_uri: * 'If-Modified-Since' header, return 0 and set @result to NULL. */ int -rrdp_parse_notification(struct rpki_uri *uri, long last_update, +rrdp_parse_notification(struct rpki_uri *uri, struct update_notification **result) { - int error; + long last_update; + int error, vis_err; if (uri == NULL || uri_is_rsync(uri)) pr_crit("Wrong call, trying to parse a non HTTPS URI"); + last_update = 0; + error = rrdp_uri_get_last_update(uri_get_global(uri), &last_update); + if (error && error != -ENOENT) + return error; + error = http_download_file_with_ims(uri, write_local, last_update); if (error < 0) return error; + /* + * Mark as visited, if it doesn't exists yet, there's no problem since + * 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 = rrdp_uri_mark_visited(uri_get_global(uri)); + if (vis_err && vis_err !=-ENOENT) + return pr_err("Coudln't mark '%s' as visited", + uri_get_global(uri)); + /* No updates yet */ if (error > 0) { *result = NULL; diff --git a/src/rrdp/rrdp_parser.h b/src/rrdp/rrdp_parser.h index 21d23404..e4c26735 100644 --- a/src/rrdp/rrdp_parser.h +++ b/src/rrdp/rrdp_parser.h @@ -4,8 +4,7 @@ #include "rrdp/rrdp_objects.h" #include "uri.h" -int rrdp_parse_notification(struct rpki_uri *, long, - struct update_notification **); +int rrdp_parse_notification(struct rpki_uri *, struct update_notification **); int rrdp_parse_snapshot(struct update_notification *); int rrdp_process_deltas(struct update_notification *, unsigned long serial); diff --git a/src/rtr/db/vrps.c b/src/rtr/db/vrps.c index f39b8819..386ae8da 100644 --- a/src/rtr/db/vrps.c +++ b/src/rtr/db/vrps.c @@ -216,6 +216,32 @@ rrdp_uri_set_last_update(char const *uri) db_rrdp_set_last_update(state.rrdp_uris, uri)) } +bool +rrdp_uri_visited(char const *uri) +{ + bool result; + + rwlock_read_lock(&state_lock); + result = db_rrdp_get_visited(state.rrdp_uris, uri); + rwlock_unlock(&state_lock); + + return result; +} + +int +rrdp_uri_mark_visited(char const *uri) +{ + WLOCK_HANDLER(&state_lock, + db_rrdp_set_visited(state.rrdp_uris, uri, true)) +} + +static int +rrdp_uri_reset_visited(void) +{ + WLOCK_HANDLER(&state_lock, + db_rrdp_set_all_nonvisited(state.rrdp_uris)) +} + static int __perform_standalone_validation(struct db_table **result) { @@ -226,6 +252,17 @@ __perform_standalone_validation(struct db_table **result) if (db == NULL) return pr_enomem(); + /* + * Reset all RDDP URIs to 'non visited' every cycle, this way we can + * assure that the update notification file will be requested when + * needed and one time per cycle. + */ + error = rrdp_uri_reset_visited(); + if (error) { + db_table_destroy(db); + return error; + } + error = perform_standalone_validation(db); if (error) { terminate_standalone_validation(); diff --git a/src/rtr/db/vrps.h b/src/rtr/db/vrps.h index a303f428..2c44b0e9 100644 --- a/src/rtr/db/vrps.h +++ b/src/rtr/db/vrps.h @@ -48,6 +48,8 @@ int rrdp_uri_update(char const *, char const *, unsigned long); int rrdp_uri_get_serial(char const *, unsigned long *); int rrdp_uri_get_last_update(char const *, long *); int rrdp_uri_set_last_update(char const *); +bool rrdp_uri_visited(char const *); +int rrdp_uri_mark_visited(char const *); uint16_t get_current_session_id(uint8_t); diff --git a/src/state.c b/src/state.c index 40ee2d62..343f8a24 100644 --- a/src/state.c +++ b/src/state.c @@ -38,12 +38,6 @@ struct validation { char addr_buffer2[INET6_ADDRSTRLEN]; struct validation_handler validation_handler; - - /* - * Handler of RRDP functions, this handler can access data from the - * main thread, so that multiple threads can use it. - */ - struct rrdp_handler rrdp_handler; }; /* @@ -87,8 +81,7 @@ cb(int ok, X509_STORE_CTX *ctx) */ int validation_prepare(struct validation **out, struct tal *tal, - struct validation_handler *validation_handler, - struct rrdp_handler *rrdp_handler) + struct validation_handler *validation_handler) { struct validation *result; X509_VERIFY_PARAM *params; @@ -130,7 +123,6 @@ validation_prepare(struct validation **out, struct tal *tal, result->pubkey_state = PKS_UNTESTED; result->validation_handler = *validation_handler; - result->rrdp_handler = *rrdp_handler; result->x509_data.params = params; /* Ownership transfered */ *out = result; @@ -215,9 +207,3 @@ validation_get_validation_handler(struct validation *state) { return &state->validation_handler; } - -struct rrdp_handler const * -validation_get_rrdp_handler(struct validation *state) -{ - return &state->rrdp_handler; -} diff --git a/src/state.h b/src/state.h index 8c21a0f0..495ae873 100644 --- a/src/state.h +++ b/src/state.h @@ -5,13 +5,12 @@ #include "cert_stack.h" #include "validation_handler.h" #include "object/tal.h" -#include "rrdp/rrdp_handler.h" #include "rsync/rsync.h" struct validation; int validation_prepare(struct validation **, struct tal *, - struct validation_handler *, struct rrdp_handler *); + struct validation_handler *); void validation_destroy(struct validation *); struct tal *validation_tal(struct validation *); @@ -35,7 +34,4 @@ char *validation_get_ip_buffer2(struct validation *); struct validation_handler const * validation_get_validation_handler(struct validation *); -struct rrdp_handler const * -validation_get_rrdp_handler(struct validation *); - #endif /* SRC_STATE_H_ */ diff --git a/src/visited_uris.c b/src/visited_uris.c new file mode 100644 index 00000000..51e0cc3f --- /dev/null +++ b/src/visited_uris.c @@ -0,0 +1,132 @@ +#include "visited_uris.h" + +#include +#include +#include +#include +#include "common.h" +#include "log.h" + +/* + * FIXME (now) This should be replaced with something better (rtrie?) + */ +struct visited_elem { + char *uri; + SLIST_ENTRY(visited_elem) next; +}; + +SLIST_HEAD(visited_uris, visited_elem) uris_db; + +/** Read/write lock, which protects @uris_db. */ +static pthread_rwlock_t lock; + +static int +visited_elem_create(struct visited_elem **elem, char const *uri) +{ + struct visited_elem *tmp; + + tmp = malloc(sizeof(struct visited_elem)); + if (tmp == NULL) + return pr_enomem(); + + tmp->uri = strdup(uri); + if (tmp->uri == NULL) { + free(tmp); + return pr_enomem(); + } + + *elem = tmp; + return 0; +} + +static void +visited_elem_destroy(struct visited_elem *elem) +{ + free(elem->uri); + free(elem); +} + +int +visited_uris_init(void) +{ + int error; + + error = pthread_rwlock_init(&lock, NULL); + if (error) + return pr_errno(error, "Visited uris pthread_rwlock_init() errored"); + + SLIST_INIT(&uris_db); + return 0; +} + +void +visited_uris_destroy(void) +{ + struct visited_elem *elem; + + while (!SLIST_EMPTY(&uris_db)) { + elem = uris_db.slh_first; + SLIST_REMOVE_HEAD(&uris_db, next); + visited_elem_destroy(elem); + } + pthread_rwlock_destroy(&lock); +} + +static struct visited_elem * +elem_find(struct visited_uris *list, char const *uri) +{ + struct visited_elem *found; + + rwlock_read_lock(&lock); + SLIST_FOREACH(found, list, next) { + if (strcmp(uri, found->uri) == 0) { + rwlock_unlock(&lock); + return found; + } + } + rwlock_unlock(&lock); + return NULL; +} + +int +visited_uris_add(char const *uri) +{ + struct visited_elem *elem; + int error; + + if (elem_find(&uris_db, uri) != NULL) + return 0; /* Exists, don't add again */ + + error = visited_elem_create(&elem, uri); + if (error) + return error; + + rwlock_write_lock(&lock); + SLIST_INSERT_HEAD(&uris_db, elem, next); + rwlock_unlock(&lock); + + return 0; +} + +int +visited_uris_remove(char const *uri) +{ + struct visited_elem *elem; + + elem = elem_find(&uris_db, uri); + if (elem == NULL) + return pr_err("Trying to remove a nonexistent URI '%s'", uri); + + rwlock_write_lock(&lock); + SLIST_REMOVE(&uris_db, elem, visited_elem, next); + visited_elem_destroy(elem); + rwlock_unlock(&lock); + + return 0; +} + +bool +visited_uris_exists(char const *uri) +{ + return elem_find(&uris_db, uri) != NULL; +} diff --git a/src/visited_uris.h b/src/visited_uris.h new file mode 100644 index 00000000..1bf77950 --- /dev/null +++ b/src/visited_uris.h @@ -0,0 +1,13 @@ +#ifndef SRC_VISITED_URIS_H_ +#define SRC_VISITED_URIS_H_ + +#include + +int visited_uris_init(void); +void visited_uris_destroy(void); + +int visited_uris_add(char const *); +int visited_uris_remove(char const *); +bool visited_uris_exists(char const *); + +#endif /* SRC_VISITED_URIS_H_ */ diff --git a/test/tal_test.c b/test/tal_test.c index ee762f25..aedfabc6 100644 --- a/test/tal_test.c +++ b/test/tal_test.c @@ -20,8 +20,7 @@ int validation_prepare(struct validation **out, struct tal *tal, - struct validation_handler *validation_handler, - struct rrdp_handler *rrdp_handler) + struct validation_handler *validation_handler) { return 0; } -- 2.47.2