]> git.ipfire.org Git - thirdparty/FORT-validator.git/commitdiff
Separate TA caching logic from RPP caching logic
authorAlberto Leiva Popper <ydahhrk@gmail.com>
Sat, 21 Sep 2024 01:04:29 +0000 (19:04 -0600)
committerAlberto Leiva Popper <ydahhrk@gmail.com>
Sat, 21 Sep 2024 01:04:29 +0000 (19:04 -0600)
(Was getting shot in the foot by overly reusing code.)

Testing and course correcting, week 2. Unstable.

Fixes (from the previous commit)

> 2. Fall back to rsync only on RRDP download failure; it's wasteful to
>    also do it on RRDP validation failure.

RPPs:
RRDP download failure triggers rsync download fallback.
RPP validation failure no longer triggers rsync download
fallback.

TAs:
HTTP download failure triggers rsync download fallback.
HTTP validation failure still triggers rsync download fallback.
(Because it's the TA, and needs to be treated more
paranoically.)

This commit is also a startup for

> 3. Must commit repository content at the RPP level, not at the module
>    level. (One failing RPP should not invalidate the whole module.)

Because I'm headed into a more explicit separation between "Repository"
and "RPP."

17 files changed:
src/cache.c
src/cache.h
src/cachent.c
src/cachent.h
src/cert_stack.c
src/cert_stack.h
src/object/certificate.c
src/object/certificate.h
src/object/tal.c
src/print_file.c
src/thread_var.c
src/thread_var.h
src/types/map.c
src/types/map.h
src/types/url.c
src/types/url.h
test/cache_test.c

index 25d9514d2182348df01c9da4fad72ff3ae9d1174..5b07e973949752b0e062540ce4bc0cea38f19a14 100644 (file)
@@ -19,6 +19,7 @@
 #include "rpp.h"
 #include "rsync.h"
 #include "types/path.h"
+#include "types/url.h"
 
 /* XXX force RRDP if one RPP fails to validate by rsync? */
 
@@ -594,124 +595,115 @@ cancel: pb_cleanup(&pb);
 }
 
 /* @uri is either a caRepository or a rpkiNotify */
-static int
-try_uri(char const *uri, struct cache_node *root,
-    dl_cb download, validate_cb validate, void *arg)
+static struct cache_node *
+do_refresh(char const *uri, struct cache_node *root, dl_cb download)
 {
-       struct cache_node *rpp;
-       struct cache_mapping map;
-       int error;
+       struct cache_node *node;
 
        if (!uri)
-               return 1; /* Protocol unavailable; ignore */
+               return NULL; /* Protocol unavailable; ignore */
 
-       pr_val_debug("Trying %s (%s)...", uri, download ? "online" : "offline");
+       pr_val_debug("Trying %s (online)...", uri);
 
-       rpp = cachent_provide(root, uri);
-       if (!rpp)
-               return pr_val_err("Malformed URL: %s", uri);
-
-       if (download != NULL) {
-               if (rpp->flags & CNF_FRESH) {
-                       if (rpp->dlerr)
-                               return rpp->dlerr;
-               } else {
-                       rpp->flags |= CNF_FRESH;
-                       error = rpp->dlerr = download(rpp);
-                       if (error)
-                               return error;
-               }
+       node = cachent_provide(root, uri);
+       if (!node) {
+               pr_val_err("Malformed URL: %s", uri);
+               return NULL;
        }
 
-       map.url = rpp->url;
-       map.path = (download != NULL) ? get_tmppath(rpp) : rpp->path;
-       error = validate(&map, arg);
-       if (error) {
-               pr_val_debug("RPP validation failed.");
-               return error;
+       if (!(node->flags & CNF_FRESH)) {
+               node->flags |= CNF_FRESH;
+               node->dlerr = download(node);
        }
+       if (node->dlerr)
+               pr_val_debug("Refresh failed.");
 
-       pr_val_debug("RPP validated successfully.");
-       rpp->flags |= CNF_VALID;
-       return 0;
+       return node;
 }
 
-static int
-try_uris(struct strlist *uris, struct cache_node *root,
-    char const *prefix, dl_cb dl, validate_cb cb, void *arg)
+/* @url needs to outlive @map. */
+int
+cache_refresh_url(char *url, struct cache_mapping *map)
 {
-       char **str;
-       int error;
+       struct cache_node *node = NULL;
 
-       ARRAYLIST_FOREACH(uris, str)
-               if (str_starts_with(*str, prefix)) {
-                       error = try_uri(*str, root, dl, cb, arg);
-                       if (error <= 0)
-                               return error;
-               }
+       // XXX mutex
+       // XXX review result signs
 
-       return 1;
+       if (url_is_https(url))
+               node = do_refresh(url, cache.https, dl_http);
+       else if (url_is_rsync(url))
+               node = do_refresh(url, cache.rsync, dl_rsync);
+       if (!node)
+               return EINVAL;
+
+       // XXX might want to const url and path.
+       // Alternatively, strdup path so the caller can't corrupt our string.
+       map->url = url;
+       map->path = get_tmppath(node);
+       return (map->path != NULL) ? 0 : EINVAL;
 }
 
+/* @url needs to outlive @map. */
 int
-cache_download_uri(struct strlist *uris, validate_cb cb, void *arg)
+cache_fallback_url(char *url, struct cache_mapping *map)
 {
-       int error;
+       struct cache_node *node = NULL;
 
-       // XXX mutex
-       // XXX review result signs
-
-       /* Online attempts */
-       error = try_uris(uris, cache.https, "https://", dl_http, cb, arg);
-       if (error <= 0)
-               return error;
-       error = try_uris(uris, cache.rsync, "rsync://", dl_rsync, cb, arg);
-       if (error <= 0)
-               return error;
+       if (url_is_https(url))
+               node = cachent_provide(cache.https, url);
+       else if (url_is_rsync(url))
+               node = cachent_provide(cache.rsync, url);
+       if (!node)
+               return EINVAL;
 
-       /* Offline attempts */
-       error = try_uris(uris, cache.https, "https://", NULL, cb, arg);
-       if (error <= 0)
-               return error;
-       return try_uris(uris, cache.rsync, "rsync://", NULL, cb, arg);
+       map->url = url;
+       map->path = node->path;
+       return 0;
 }
 
 /*
- * XXX outdated comment
- *
- * Assumes the URIs represent different ways to access the same content.
- *
- * Sequentially (in the order dictated by their priorities) attempts to update
- * (in the cache) the content pointed by each URL.
- * If a download succeeds, calls cb on it. If cb succeeds, returns without
- * trying more URLs.
- *
- * If none of the URLs download and callback properly, attempts to find one
- * that's already cached, and callbacks it.
+ * Attempts to refresh the RPP described by @sias, returns the resulting
+ * repository's mapping.
  */
 int
-cache_download_alt(struct sia_uris *sias, validate_cb cb, void *arg)
+cache_refresh_sias(struct sia_uris *sias, struct cache_mapping *map)
 {
-       int error;
+       struct cache_node *hnode;
+       struct cache_node *rnode;
 
        // XXX Make sure somewhere validates rpkiManifest matches caRepository.
-       /* XXX mutex */
-
-       /* Online attempts */
+       // XXX mutex
        // XXX review result signs
        // XXX normalize rpkiNotify & caRepository?
-       error = try_uri(sias->rpkiNotify, cache.https, dl_rrdp, cb, arg);
-       if (error <= 0)
-               return error;
-       error = try_uri(sias->caRepository, cache.rsync, dl_rsync, cb, arg);
-       if (error <= 0)
-               return error;
 
-       /* Offline attempts */
-       error = try_uri(sias->rpkiNotify, cache.https, NULL, cb, arg);
-       if (error <= 0)
-               return error;
-       return try_uri(sias->caRepository, cache.rsync, NULL, cb, arg);
+       hnode = do_refresh(sias->rpkiNotify, cache.https, dl_rrdp);
+       if (hnode && !hnode->dlerr) {
+               map->url = hnode->url;
+               map->path = hnode->tmppath;
+               return 0;
+       }
+
+       rnode = do_refresh(sias->caRepository, cache.rsync, dl_rsync);
+       if (rnode && !rnode->dlerr) {
+               map->url = rnode->url;
+               map->path = rnode->tmppath;
+               return 0;
+       }
+
+       if (hnode && cachent_is_cached(hnode)) {
+               map->url = hnode->url;
+               map->path = hnode->path;
+               return 0;
+       }
+
+       if (hnode && cachent_is_cached(rnode)) {
+               map->url = hnode->url;
+               map->path = hnode->path;
+               return 0;
+       }
+
+       return EINVAL;
 }
 
 void
index fdf46a025d7a0074679dcd6b532562903faa4d9d..4cfbf321a24c8497d056646daff8f3f175f85eab 100644 (file)
@@ -2,7 +2,6 @@
 #define SRC_CACHE_LOCAL_CACHE_H_
 
 #include "types/map.h"
-#include "types/str.h"
 
 int cache_setup(void);         /* Init this module */
 void cache_teardown(void);     /* Destroy this module */
@@ -19,16 +18,9 @@ struct sia_uris {
 void sias_init(struct sia_uris *);
 void sias_cleanup(struct sia_uris *);
 
-/*
- * The callback should return
- *
- * - 0 on success ("Mapping handled successfully")
- * - > 0 on soft errors ("Try another mapping")
- * - < 0 on hard errors ("Abandon foreach")
- */
-typedef int (*validate_cb)(struct cache_mapping *, void *);
-int cache_download_uri(struct strlist *, validate_cb, void *);
-int cache_download_alt(struct sia_uris *, validate_cb, void *);
+int cache_refresh_url(char *, struct cache_mapping *);
+int cache_fallback_url(char *, struct cache_mapping *);
+int cache_refresh_sias(struct sia_uris *, struct cache_mapping *);
 
 void cache_print(void); /* Dump cache in stdout. Recursive; tests only */
 
index 72aa2bd865221683e119a8ddc611343824dcefe8..46c593e6a2aa2c521dfedb292883f74685756089 100644 (file)
@@ -33,6 +33,18 @@ cachent_root_https(void)
        return cachent_root("https://", "https");
 }
 
+bool
+cachent_is_cached(struct cache_node *node)
+{
+       if (cachent_is_https(node))
+               return node->flags & CNF_CACHED;
+
+       for (; node != NULL; node = node->parent)
+               if (node->flags & CNF_CACHED)
+                       return true;
+       return false;
+}
+
 /* Preorder. @cb returns whether the children should be traversed. */
 void
 cachent_traverse(struct cache_node *root, bool (*cb)(struct cache_node *))
index 8d297101aec38beac25d26f7b56a4f6123579dd4..2bed18f2a97e379d24608f7cd8b43319c0164e5d 100644 (file)
@@ -78,6 +78,11 @@ struct cache_node {
 struct cache_node *cachent_root_rsync(void);
 struct cache_node *cachent_root_https(void);
 
+#define cachent_is_rsync(node) ((node)->flags & CNF_RSYNC)
+#define cachent_is_https(node) (!cachent_is_rsync(node))
+
+bool cachent_is_cached(struct cache_node *);
+
 void cachent_traverse(struct cache_node *, bool (*cb)(struct cache_node *));
 
 struct cache_node *cachent_find(struct cache_node *, char const *,
index f863ec09c72b7dd457c30c256411f232946cddff..dbce82802899f113db3789e09b781ba46f638a2f 100644 (file)
@@ -249,8 +249,8 @@ create_separator(void)
 
 /* Steals ownership of @x509 on success. */
 int
-x509stack_push(struct cert_stack *stack, struct cache_mapping *map, X509 *x509,
-    enum rpki_policy policy, enum cert_type type)
+x509stack_push(struct cert_stack *stack, struct cache_mapping const *map,
+    X509 *x509, enum rpki_policy policy, enum cert_type type)
 {
        struct metadata_node *meta;
        struct defer_node *defer_separator;
index 5c818aef413cd3d1b35be6ab904ba78fcdf0d71f..411bac3af74dea67abe38bfef142faf650ea1815 100644 (file)
@@ -19,8 +19,8 @@ void certstack_destroy(struct cert_stack *);
 void deferstack_push(struct cert_stack *, struct cache_mapping *, struct rpp *);
 int deferstack_pop(struct cert_stack *, struct deferred_cert *cert);
 
-int x509stack_push(struct cert_stack *, struct cache_mapping *, X509 *,
-    enum rpki_policy, enum cert_type);
+int x509stack_push(struct cert_stack *, struct cache_mapping const *,
+    X509 *, enum rpki_policy, enum cert_type);
 void x509stack_cancel(struct cert_stack *);
 X509 *x509stack_peek(struct cert_stack *);
 struct resources *x509stack_peek_resources(struct cert_stack *);
index 1e1e5b1e45281d13886112fd0b9d3407831bf396..3968af308850f0a0566dc812c6ac231752ef2811 100644 (file)
@@ -24,6 +24,7 @@
 #include "object/manifest.h"
 #include "thread_var.h"
 #include "types/path.h"
+#include "types/str.h"
 #include "types/url.h"
 
 /*
@@ -794,7 +795,7 @@ end:
 }
 
 static int
-certificate_load(struct cache_mapping *map, X509 **result)
+certificate_load(struct cache_mapping const *map, X509 **result)
 {
        X509 *cert = NULL;
        BIO *bio;
@@ -1847,7 +1848,7 @@ certificate_validate_aia(char const *caIssuers, X509 *cert)
 }
 
 static int
-check_rpp(struct cache_mapping *map_rpp, void *rpkiManifest)
+check_rpp(struct cache_mapping const *map_rpp, char *rpkiManifest)
 {
        struct cache_mapping mft;
        struct rpp *pp;
@@ -1869,14 +1870,16 @@ end:    free(mft.path);
 
 /* Boilerplate code for CA certificate validation and recursive traversal. */
 int
-certificate_traverse(struct rpp *rpp_parent, struct cache_mapping *cert_map)
+certificate_traverse(struct rpp *rpp_parent,
+    struct cache_mapping const *cert_map)
 {
        struct validation *state;
        int total_parents;
        X509 *x509;
-       struct sia_uris sia_uris;
+       struct sia_uris sias;
        enum rpki_policy policy;
        enum cert_type certype;
+       struct cache_mapping rpp;
        int error;
 
        state = state_retrieve();
@@ -1920,26 +1923,32 @@ certificate_traverse(struct rpp *rpp_parent, struct cache_mapping *cert_map)
        if (error)
                goto revert_cert;
 
-       sias_init(&sia_uris);
+       sias_init(&sias);
        error = (certype == CERTYPE_TA)
-           ? certificate_validate_extensions_ta(x509, &sia_uris, &policy)
-           : certificate_validate_extensions_ca(x509, &sia_uris, &policy,
+           ? certificate_validate_extensions_ta(x509, &sias, &policy)
+           : certificate_validate_extensions_ca(x509, &sias, &policy,
                                                 rpp_parent);
        if (error)
-               goto revert_uris;
+               goto revert_sias;
 
        error = x509stack_push(validation_certstack(state), cert_map, x509,
            policy, certype);
        if (error)
-               goto revert_uris;
+               goto revert_sias;
        x509 = NULL; /* Ownership stolen */
 
-       error = cache_download_alt(&sia_uris, check_rpp, sia_uris.rpkiManifest);
+       error = cache_refresh_sias(&sias, &rpp);
+       if (error) {
+               x509stack_cancel(validation_certstack(state));
+               goto revert_sias;
+       }
+
+       error = check_rpp(&rpp, sias.rpkiManifest);
        if (error)
                x509stack_cancel(validation_certstack(state));
 
-revert_uris:
-       sias_cleanup(&sia_uris);
+revert_sias:
+       sias_cleanup(&sias);
 revert_cert:
        if (x509 != NULL)
                X509_free(x509);
index 9bc4e56e2eb4a71a678b2890e3a2b600a1cda5d1..5e9aa6f6cd2457c91de202fceb0850bf00deb125 100644 (file)
@@ -55,6 +55,6 @@ int certificate_validate_extensions_bgpsec(X509 *, unsigned char **,
  */
 int certificate_validate_aia(char const *, X509 *);
 
-int certificate_traverse(struct rpp *, struct cache_mapping *);
+int certificate_traverse(struct rpp *, struct cache_mapping const *);
 
 #endif /* SRC_OBJECT_CERTIFICATE_H_ */
index 489d2a8908881d9a37fc03231ebf3e94e579c963..0802e28a6ff566568f8ca03e827642e226412de9 100644 (file)
@@ -12,6 +12,8 @@
 #include "log.h"
 #include "thread_var.h"
 #include "types/path.h"
+#include "types/str.h"
+#include "types/url.h"
 
 struct tal {
        char const *file_name;
@@ -32,10 +34,13 @@ struct validation_thread {
 /* List of threads, one per TAL file */
 SLIST_HEAD(threads_list, validation_thread);
 
-struct handle_tal_args {
-       struct tal tal;
-       struct db_table *db;
-};
+#define TS_SUCCESS     0       /* TA looks sane. */
+#define TS_NEXT                1       /* TA seems compromised; try some other URL. */
+#define TS_FALLBACK    2       /* TA is broken; fall back to old cache. */
+typedef struct { int v; } ta_status;
+static ta_status ts_success    = { .v = TS_SUCCESS };
+static ta_status ts_next       = { .v = TS_NEXT };
+static ta_status ts_fallback   = { .v = TS_FALLBACK };
 
 static char *
 find_newline(char *str)
@@ -84,8 +89,7 @@ read_content(char *fc /* File Content */, struct tal *tal)
                if (is_blank(fc))
                        break;
 
-               if (str_starts_with(fc, "https://") ||
-                   str_starts_with(fc, "rsync://"))
+               if (url_is_https(fc) || url_is_rsync(fc))
                        strlist_add(&tal->urls, pstrdup(fc));
 
                fc = nl + cr + 1;
@@ -149,47 +153,31 @@ tal_get_spki(struct tal *tal, unsigned char const **buffer, size_t *len)
        *len = tal->spki_len;
 }
 
-/*
- * Performs the whole validation walkthrough that starts with Trust Anchor @ta,
- * which is assumed to have been extracted from TAL @arg->tal.
- */
-static int
-handle_ta(struct cache_mapping *ta, void *arg)
+static ta_status
+handle_ta(struct cache_mapping const *ta, struct validation *state)
 {
-       struct handle_tal_args *args = arg;
-       struct validation_handler validation_handler;
-       struct validation *state;
        struct cert_stack *certstack;
        struct deferred_cert deferred;
        int error;
 
-       validation_handler.handle_roa_v4 = handle_roa_v4;
-       validation_handler.handle_roa_v6 = handle_roa_v6;
-       validation_handler.handle_router_key = handle_router_key;
-       validation_handler.arg = args->db;
-
-       error = validation_prepare(&state, &args->tal, &validation_handler);
-       if (error)
-               return ENSURE_NEGATIVE(error);
-
-       if (!str_ends_with(ta->url, ".cer")) {
-               pr_op_err("TAL URI lacks '.cer' extension: %s", ta->url);
-               error = EINVAL;
-               goto end;
-       }
-
-       /* Handle root certificate. */
-       error = certificate_traverse(NULL, ta);
-       if (error) {
+       /* == Root certificate == */
+       if (certificate_traverse(NULL, ta) != 0) {
                switch (validation_pubkey_state(state)) {
                case PKS_INVALID:
-                       error = EINVAL;
-                       goto end;
+                       /* Signature invalid; probably an impersonator. */
+                       return ts_next;
                case PKS_VALID:
+                       /* No impersonator but still error: Broken tree. */
+                       /*
+                        * XXX Change to ts_next. This is the TA;
+                        * we can't really afford to panic-fallback.
+                        */
+                       return ts_fallback;
                case PKS_UNTESTED:
-                       error = ENSURE_NEGATIVE(error);
-                       goto end;
+                       /* We don't know; try some other URL. */
+                       return ts_next;
                }
+
                pr_crit("Unknown public key state: %u",
                    validation_pubkey_state(state));
        }
@@ -200,15 +188,14 @@ handle_ta(struct cache_mapping *ta, void *arg)
         * (the root validated successfully; subtrees are isolated problems.)
         */
 
-       /* Handle every other certificate. */
+       /* == Every other certificate == */
        certstack = validation_certstack(state);
 
        do {
                error = deferstack_pop(certstack, &deferred);
-               if (error == -ENOENT) {
-                       error = 0; /* No more certificates left; we're done */
-                       goto end;
-               } else if (error) /* All other errors are critical, currently */
+               if (error == -ENOENT)
+                       return ts_success; /* No more certificates left */
+               else if (error) /* All other errors are critical, currently */
                        pr_crit("deferstack_pop() returned illegal %d.", error);
 
                /*
@@ -220,16 +207,72 @@ handle_ta(struct cache_mapping *ta, void *arg)
                map_cleanup(&deferred.map);
                rpp_refput(deferred.pp);
        } while (true);
+}
 
-end:   validation_destroy(state);
-       return error;
+static void
+__do_file_validation(struct validation_thread *thread)
+{
+       struct tal tal;
+       struct validation_handler collector;
+       struct db_table *db;
+       struct validation *state;
+       char **url;
+       struct cache_mapping map;
+       ta_status status;
+
+       thread->error = tal_init(&tal, thread->tal_file);
+       if (thread->error)
+               return;
+
+       collector.handle_roa_v4 = handle_roa_v4;
+       collector.handle_roa_v6 = handle_roa_v6;
+       collector.handle_router_key = handle_router_key;
+       collector.arg = db = db_table_create();
+
+       thread->error = validation_prepare(&state, &tal, &collector);
+       if (thread->error) {
+               db_table_destroy(db);
+               goto end2;
+       }
+
+       ARRAYLIST_FOREACH(&tal.urls, url) {
+               if (cache_refresh_url(*url, &map) != 0)
+                       continue;
+
+               status = handle_ta(&map, state);
+               switch (status.v) {
+               case TS_SUCCESS:        goto end1;
+               case TS_FALLBACK:       goto fallback;
+               case TS_NEXT:           ; /* Fall through */
+               }
+       }
+
+fallback:
+       ARRAYLIST_FOREACH(&tal.urls, url) {
+               if (cache_fallback_url(*url, &map) != 0)
+                       continue;
+
+               status = handle_ta(&map, state);
+               switch (status.v) {
+               case TS_SUCCESS:        goto end1;
+               case TS_FALLBACK:       /* Already fallbacking */
+               case TS_NEXT:           ; /* Fall through */
+               }
+       }
+
+       pr_op_err("None of the TAL URIs yielded a successful traversal.");
+       thread->error = EINVAL;
+       db_table_destroy(db);
+       db = NULL;
+
+end1:  thread->db = db;
+end2:  tal_cleanup(&tal);
 }
 
 static void *
 do_file_validation(void *arg)
 {
        struct validation_thread *thread = arg;
-       struct handle_tal_args args;
        time_t start, finish;
 
        start = time(NULL);
@@ -237,26 +280,15 @@ do_file_validation(void *arg)
        fnstack_init();
        fnstack_push(thread->tal_file);
 
-       thread->error = tal_init(&args.tal, thread->tal_file);
-       if (thread->error)
-               goto end;
-
-       args.db = db_table_create();
-       thread->error = cache_download_uri(&args.tal.urls, handle_ta, &args);
-       if (thread->error) {
-               pr_op_err("None of the TAL URIs yielded a successful traversal.");
-               db_table_destroy(args.db);
-       } else {
-               thread->db = args.db;
-       }
+       __do_file_validation(thread);
 
-       tal_cleanup(&args.tal);
-end:   fnstack_cleanup();
+       fnstack_cleanup();
 
        finish = time(NULL);
        if (start != ((time_t) -1) && finish != ((time_t) -1))
                pr_op_debug("The %s tree took %.0lf seconds.",
-                   args.tal.file_name, difftime(finish, start));
+                   path_filename(thread->tal_file),
+                   difftime(finish, start));
        return NULL;
 }
 
index 7d0f534dedef734a5ad8c4c96b051467a738c92c..27476c9394263ffe352168749f886e846bd3d7b5 100644 (file)
@@ -13,6 +13,7 @@
 #include "rsync.h"
 #include "types/bio_seq.h"
 #include "types/path.h"
+#include "types/url.h"
 
 #define HDRSIZE 32
 
@@ -98,7 +99,7 @@ filename2bio(char const *filename)
        if (filename == NULL || strcmp(filename, "-") == 0)
                return BIO_new_fp(stdin, BIO_NOCLOSE);
 
-       if (str_starts_with(filename, "rsync://"))
+       if (url_is_rsync(filename))
                return rsync2bio(filename);
 
        return BIO_new_file(filename, "rb");
index 13d5ec5fcc97856d8fa40b1765a84d6334fbe533..ab09259c8bdff7e32160d5bde8a8f204ffe6a4a8 100644 (file)
@@ -158,7 +158,7 @@ fnstack_push(char const *file)
 
 /* See fnstack_push(). @map needs to outlive the push/pop. */
 void
-fnstack_push_map(struct cache_mapping *map)
+fnstack_push_map(struct cache_mapping const *map)
 {
        fnstack_push(map_val_get_printable(map));
 }
index 0d5d389c2767c790155a8db2bdbd66c45e062328..d2b0c72a695c25d25ba669191cbd8ca013b3922d 100644 (file)
@@ -12,7 +12,7 @@ void fnstack_init(void);
 void fnstack_cleanup(void);
 
 void fnstack_push(char const *);
-void fnstack_push_map(struct cache_mapping *);
+void fnstack_push_map(struct cache_mapping const *);
 char const *fnstack_peek(void);
 void fnstack_pop(void);
 
index 2a6c13af079d44051311a04a7c87e4502f1b7988..7377f402d5681d18aeba3a57f6c01d2a86f5b242 100644 (file)
@@ -6,7 +6,7 @@
 #include "types/path.h"
 
 static char const *
-map_get_printable(struct cache_mapping *map, enum filename_format format)
+map_get_printable(struct cache_mapping const *map, enum filename_format format)
 {
        switch (format) {
        case FNF_GLOBAL:
@@ -22,26 +22,26 @@ map_get_printable(struct cache_mapping *map, enum filename_format format)
 }
 
 char const *
-map_val_get_printable(struct cache_mapping *map)
+map_val_get_printable(struct cache_mapping const *map)
 {
        return map_get_printable(map, config_get_val_log_file_format());
 }
 
 char const *
-map_op_get_printable(struct cache_mapping *map)
+map_op_get_printable(struct cache_mapping const *map)
 {
        return map_get_printable(map, config_get_op_log_file_format());
 }
 
 void
-map_parent(struct cache_mapping *child, struct cache_mapping *parent)
+map_parent(struct cache_mapping const *child, struct cache_mapping *parent)
 {
        parent->url = path_parent(child->url);
        parent->path = path_parent(child->path);
 }
 
 struct cache_mapping *
-map_child(struct cache_mapping *parent, char const *name)
+map_child(struct cache_mapping const *parent, char const *name)
 {
        struct cache_mapping *child;
 
@@ -53,7 +53,7 @@ map_child(struct cache_mapping *parent, char const *name)
 }
 
 void
-map_copy(struct cache_mapping *dst, struct cache_mapping *src)
+map_copy(struct cache_mapping *dst, struct cache_mapping const *src)
 {
        dst->url = pstrdup(src->url);
        dst->path = pstrdup(src->path);
index c35b27ff2adadff015f375a258600c97b375c3eb..3ecc56fa6434ca3c24d2263b77594dc9e8f9eeeb 100644 (file)
@@ -9,13 +9,13 @@ struct cache_mapping {
        char *path;
 };
 
-char const *map_val_get_printable(struct cache_mapping *);
-char const *map_op_get_printable(struct cache_mapping *);
+char const *map_val_get_printable(struct cache_mapping const *);
+char const *map_op_get_printable(struct cache_mapping const *);
 
-void map_parent(struct cache_mapping *, struct cache_mapping *);
-struct cache_mapping *map_child(struct cache_mapping *, char const *);
+void map_parent(struct cache_mapping const *, struct cache_mapping *);
+struct cache_mapping *map_child(struct cache_mapping const *, char const *);
 
-void map_copy(struct cache_mapping *, struct cache_mapping *);
+void map_copy(struct cache_mapping *, struct cache_mapping const *);
 void map_cleanup(struct cache_mapping *);
 
 #endif /* SRC_TYPES_MAP_H_ */
index 3e03b68c8f8837b6da25fad735816b726367a165..46c4dffc30cd55c1bc7b33bd710832a2e334d935 100644 (file)
@@ -1,8 +1,21 @@
 #include "types/url.h"
 
 #include "alloc.h"
+#include "common.h"
 #include "types/path.h"
 
+bool
+url_is_rsync(char const *url)
+{
+       return str_starts_with(url, "rsync://");
+}
+
+bool
+url_is_https(char const *url)
+{
+       return str_starts_with(url, "https://");
+}
+
 /*
  * XXX use this:
  *
index 9ac9fffab99adfe0c55ca59f30ef27f08d7780f9..a2b0ea5d37cccf9478a13fec77db427a6491c7e7 100644 (file)
@@ -5,6 +5,9 @@
 
 #define RPKI_SCHEMA_LEN 8 /* strlen("rsync://"), strlen("https://") */
 
+bool url_is_rsync(char const *);
+bool url_is_https(char const *);
+
 char *url_normalize(char const *);
 bool url_same_origin(char const *, char const *);
 
index 6c47f9fda414c8e8c6e029e5c898245930a28e60..bb4c3cf0c8dc38c304df54a4ac858b0ded2b1f5e 100644 (file)
@@ -62,7 +62,7 @@ setup_test(void)
 }
 
 static int
-okay(struct cache_mapping *map, void *arg)
+okay(struct cache_mapping const *map, void *arg)
 {
        return 0;
 }
@@ -952,9 +952,9 @@ END_TEST
 //
 //     va_start(args, maps);
 //     while ((str = va_arg(args, char const *)) != NULL) {
-//             if (str_starts_with(str, "https://"))
+//             if (url_is_https(str))
 //                     type = MAP_HTTP;
-//             else if (str_starts_with(str, "rsync://"))
+//             else if (url_is_rsync(str))
 //                     type = MAP_RSYNC;
 //             else
 //                     ck_abort_msg("Bad protocol: %s", str);