]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Remember which manifests where fetched using RRDP, remove rrdp_handler.
authorpcarana <pc.moreno2099@gmail.com>
Wed, 11 Dec 2019 00:30:53 +0000 (18:30 -0600)
committerpcarana <pc.moreno2099@gmail.com>
Wed, 11 Dec 2019 00:30:53 +0000 (18:30 -0600)
+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.

19 files changed:
src/Makefile.am
src/http/http.c
src/main.c
src/object/certificate.c
src/object/tal.c
src/rrdp/db_rrdp.c
src/rrdp/db_rrdp.h
src/rrdp/rrdp_handler.c [deleted file]
src/rrdp/rrdp_handler.h [deleted file]
src/rrdp/rrdp_loader.c
src/rrdp/rrdp_parser.c
src/rrdp/rrdp_parser.h
src/rtr/db/vrps.c
src/rtr/db/vrps.h
src/state.c
src/state.h
src/visited_uris.c [new file with mode: 0644]
src/visited_uris.h [new file with mode: 0644]
test/tal_test.c

index d78bf133e2f81a3489cea23ca3102e5687c88163..1debbcf48edde4012ac61cbdb3033467e798f54a 100644 (file)
@@ -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
index 3d8480259cb1a0a9150c44c01ced488d363e601a..cd10ce1af1a7a37e96a5c69d87441c9ad59a8091 100644 (file)
@@ -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
index cac02d9f498f56576384a22bd3c5079e2b187ad3..722f753bddfe4375fcd7e2a1896bc2734bafa62a 100644 (file)
@@ -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;
index 3b3cfdf316b0ef1c47223d42e530d3c739b556dc..de8dcf3fcd56525277db55be1946be6489b0f7ff 100644 (file)
@@ -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 <local-repository>/rrdp/<session_id>).:
+        * - 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'",
index 9674c40fe0d14bcffb575a7b16af11479b0d054e..f81f9b4be0e96db84a1a54760eb68e5d4c572be7 100644 (file)
@@ -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);
 
index 86e36b3e80507d8c080883274b4172a6e9ef546a..820535767c6ac4fb32eff9766c1f27c4cbc6027f 100644 (file)
@@ -1,6 +1,7 @@
 #include "db_rrdp.h"
 
 #include <stdlib.h>
+#include <stdbool.h>
 #include <string.h>
 #include <time.h>
 #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)
 {
index 9aca0769257afd80aa26720052a746750ee552ac..0339bf8aff68f5fde5023d9ee6fb3af8ab086612 100644 (file)
@@ -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 (file)
index 94a9eb0..0000000
+++ /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 (file)
index db6f732..0000000
+++ /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_ */
index 1ff706bc73b59617895babeec6df13cb2899523b..ce7523ce3762dab3fae991f92666f89d9c45551a 100644 (file)
@@ -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;
 }
index 43fca005ec6b74b58fe26ea02e8184c245117f3d..f8839769c9ce8f5b7ad3b9b047b3cfb8fe0ac4de 100644 (file)
 #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;
index 21d23404253bab5ce68345800db0fdc47fc9be83..e4c267353d4a43b9bda321b1aefbffbeafe7255f 100644 (file)
@@ -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);
index f39b88190ac97972cd434e847c9bb9212d2570b6..386ae8dadd5bfd943522b35f3270b6feca5c24db 100644 (file)
@@ -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();
index a303f428abf1dd4c884544c8805e46a7a73edb6e..2c44b0e95c180c92bb9c372e7f397f1de7e129e4 100644 (file)
@@ -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);
 
index 40ee2d621ef67cd285fb5c31e2174467e9739c80..343f8a24091c43c95ed3d18b5164e6576eab1d6e 100644 (file)
@@ -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;
-}
index 8c21a0f0b375f2eafcc4ec32d2f8e470f81c2f87..495ae87349c31795c864236abb1b830a15d2e2aa 100644 (file)
@@ -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 (file)
index 0000000..51e0cc3
--- /dev/null
@@ -0,0 +1,132 @@
+#include "visited_uris.h"
+
+#include <sys/queue.h>
+#include <pthread.h>
+#include <stddef.h>
+#include <string.h>
+#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 (file)
index 0000000..1bf7795
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef SRC_VISITED_URIS_H_
+#define SRC_VISITED_URIS_H_
+
+#include <stdbool.h>
+
+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_ */
index ee762f25d5b2e6907c1bf67255227aea7e04f995..aedfabc646a7221a0f15a719027f67c516fb4e1f 100644 (file)
@@ -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;
 }