]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
struct kr_zonecut::nsset: migrate from map_t to trie_t
authorVladimír Čunát <vladimir.cunat@nic.cz>
Tue, 10 Apr 2018 17:19:55 +0000 (19:19 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Thu, 12 Apr 2018 15:49:03 +0000 (17:49 +0200)
daemon/engine.c
daemon/lua/config.lua
daemon/lua/kres-gen.lua
daemon/lua/kres-gen.sh
lib/generic/pack.h
lib/nsrep.c
lib/resolve.c
lib/zonecut.c
lib/zonecut.h
modules/hints/hints.c
tests/test_zonecut.c

index e62d71135a4791b2acfdb8a3a15ab9103842d203..91390c452322e7713d69bc7bbb0c301ccf9d2789 100644 (file)
@@ -594,9 +594,8 @@ static int init_resolver(struct engine *engine)
        knot_edns_init(engine->resolver.opt_rr, KR_EDNS_PAYLOAD, 0, KR_EDNS_VERSION, engine->pool);
        /* Use default TLS padding */
        engine->resolver.tls_padding = -1;
-       /* Set default root hints */
+       /* Empty init; filled via ./lua/config.lua */
        kr_zonecut_init(&engine->resolver.root_hints, (const uint8_t *)"", engine->pool);
-       kr_zonecut_set_sbelt(&engine->resolver, &engine->resolver.root_hints);
        /* Open NS rtt + reputation cache */
        lru_create(&engine->resolver.cache_rtt, LRU_RTT_SIZE, engine->pool, NULL);
        lru_create(&engine->resolver.cache_rep, LRU_REP_SIZE, engine->pool, NULL);
index be414a7cd861d98aa6ca3b3dd76eb52e9bd3f341..448d6dd634de598afa23ec9d3cad7a025e3bc2af 100644 (file)
@@ -19,7 +19,8 @@ if not cache.current_size then
        cache.size = 100 * MB
 end
 
-if kres.context().root_hints.nsset.root == nil then
+-- If no addresses for root servers are set, load them from the default file
+if require('ffi').C.kr_zonecut_is_empty(kres.context().root_hints) then
        _hint_root_file()
 end
 
index c2d1bce1748e2accbcce99a9d60df046bd7efa30..aaca2da688e17c2bf9ef790848635f69c0f7e06e 100644 (file)
@@ -119,12 +119,13 @@ typedef struct {
        size_t len;
        size_t cap;
 } ranked_rr_array_t;
+typedef struct trie trie_t;
 struct kr_zonecut {
        knot_dname_t *name;
        knot_rrset_t *key;
        knot_rrset_t *trust_anchor;
        struct kr_zonecut *parent;
-       map_t nsset;
+       trie_t *nsset;
        knot_mm_t *pool;
 };
 typedef struct {
@@ -286,6 +287,7 @@ int kr_ranked_rrarray_add(ranked_rr_array_t *, const knot_rrset_t *, uint8_t, _B
 void kr_qflags_set(struct kr_qflags *, struct kr_qflags);
 void kr_qflags_clear(struct kr_qflags *, struct kr_qflags);
 int kr_zonecut_add(struct kr_zonecut *, const knot_dname_t *, const knot_rdata_t *);
+_Bool kr_zonecut_is_empty(struct kr_zonecut *);
 void kr_zonecut_set(struct kr_zonecut *, const knot_dname_t *);
 uint64_t kr_now();
 knot_rrset_t *kr_ta_get(map_t *, const knot_dname_t *);
index b8266f97539c93c26c0e67e52049e29d279f6087..0fbffaae1ee97f4b2590a80683ba973cd387243b 100755 (executable)
@@ -57,6 +57,7 @@ typedef void (*trace_callback_f)(struct kr_request *);
        struct ranked_rr_array_entry
        ranked_rr_array_entry_t
        ranked_rr_array_t
+       trie_t
        struct kr_zonecut
        kr_qarray_t
        struct kr_rplan
@@ -154,6 +155,7 @@ EOF
        kr_qflags_set
        kr_qflags_clear
        kr_zonecut_add
+       kr_zonecut_is_empty
        kr_zonecut_set
        kr_now
 # Trust anchors
index 4b16c9799cc5ef7df30cd90ca73845be977335b2..90c1b7218872e4f49f86012a6a2cdc4a2cdac32b 100644 (file)
@@ -192,23 +192,30 @@ static inline int pack_obj_del(pack_t *pack, const uint8_t *obj, pack_objlen_t l
        return -1;
 }
 
-/** Clone a pack into a mempool (can be NULL).
- * @return NULL on allocation failure. */
-static inline pack_t * pack_clone(const pack_t *src, knot_mm_t *pool)
+/** Clone a pack, replacing destination pack; (*dst == NULL) is valid input.
+ * @return kr_error(ENOMEM) on allocation failure. */
+static inline int pack_clone(pack_t **dst, const pack_t *src, knot_mm_t *pool)
 {
-       pack_t *dst = mm_alloc(pool, sizeof(pack_t));
-       if (!dst) return dst;
-       pack_init(*dst);
-       /* Clone data only if needed */
-       if (!pack_head(*src)) return dst;
-       int ret = array_reserve_mm(*dst, src->len, kr_memreserve, pool);
+       if (!dst || !src) {
+               assert(false);
+               return kr_error(EINVAL);
+       }
+       /* Get a valid pack_t. */
+       if (!*dst) {
+               *dst = mm_alloc(pool, sizeof(pack_t));
+               if (!*dst) return kr_error(ENOMEM);
+               pack_init(**dst);
+               /* Clone data only if needed */
+               if (src->len == 0) return kr_ok();
+       }
+       /* Replace the contents of the pack_t. */
+       int ret = array_reserve_mm(**dst, src->len, kr_memreserve, pool);
        if (ret < 0) {
-               mm_free(pool, dst);
-               return NULL;
+               return kr_error(ENOMEM);
        }
-       memcpy(dst->at, src->at, src->len);
-       dst->len = src->len;
-       return dst;
+       memcpy((*dst)->at, src->at, src->len);
+       (*dst)->len = src->len;
+       return kr_ok();
 }
 
 #ifdef __cplusplus
index 628adf3ce85ca2b5b7c570bcdfaa9a223ffe5b39..0420bdae0b6f48f53cde90229541840ecb0c5471 100644 (file)
@@ -82,7 +82,7 @@ static void update_nsrep_set(struct kr_nsrep *ns, const knot_dname_t *name, uint
 
 #undef ADDR_SET
 
-static unsigned eval_addr_set(pack_t *addr_set, struct kr_context *ctx,
+static unsigned eval_addr_set(const pack_t *addr_set, struct kr_context *ctx,
                              unsigned score, uint8_t *addr[])
 {
        kr_nsrep_rtt_lru_t *rtt_cache = ctx->cache_rtt;
@@ -209,9 +209,8 @@ get_next_iterator :
        return rtt_cache_entry_score[0];
 }
 
-static int eval_nsrep(const char *k, void *v, void *baton)
+static int eval_nsrep(const knot_dname_t *owner, const pack_t *addr_set, struct kr_query *qry)
 {
-       struct kr_query *qry = baton;
        struct kr_nsrep *ns = &qry->ns;
        struct kr_context *ctx = ns->ctx;
        unsigned score = KR_NS_MAX_SCORE;
@@ -220,8 +219,8 @@ static int eval_nsrep(const char *k, void *v, void *baton)
 
        /* Fetch NS reputation */
        if (ctx->cache_rep) {
-               unsigned *cached = lru_get_try(ctx->cache_rep, k,
-                                              knot_dname_size((const uint8_t *)k));
+               unsigned *cached = lru_get_try(ctx->cache_rep, (const char *)owner,
+                                              knot_dname_size(owner));
                if (cached) {
                        reputation = *cached;
                }
@@ -229,7 +228,6 @@ static int eval_nsrep(const char *k, void *v, void *baton)
 
        /* Favour nameservers with unknown addresses to probe them,
         * otherwise discover the current best address for the NS. */
-       pack_t *addr_set = (pack_t *)v;
        if (addr_set->len == 0) {
                score = KR_NS_UNKNOWN;
                /* If the server doesn't have IPv6, give it disadvantage. */
@@ -261,19 +259,19 @@ static int eval_nsrep(const char *k, void *v, void *baton)
                return kr_ok();
        } else if (score <= ns->score &&
           (score < KR_NS_LONG  || qry->flags.NO_THROTTLE)) {
-               update_nsrep_set(ns, (const knot_dname_t *)k, addr_choice, score);
+               update_nsrep_set(ns, owner, addr_choice, score);
                ns->reputation = reputation;
        } else if ((kr_rand_uint(100) < 10) &&
                   (kr_rand_uint(KR_NS_MAX_SCORE) >= score)) {
                /* With 10% chance probe server with a probability
                 * given by its RTT / MAX_RTT. */
-               update_nsrep_set(ns, (const knot_dname_t *)k, addr_choice, score);
+               update_nsrep_set(ns, owner, addr_choice, score);
                ns->reputation = reputation;
                return 1; /* Stop evaluation */
        } else if (ns->score > KR_NS_MAX_SCORE) {
                /* Check if any server was already selected.
                 * If no, pick current server and continue evaluation. */
-               update_nsrep_set(ns, (const knot_dname_t *)k, addr_choice, score);
+               update_nsrep_set(ns, owner, addr_choice, score);
                ns->reputation = reputation;
        }
 
@@ -339,7 +337,18 @@ int kr_nsrep_elect(struct kr_query *qry, struct kr_context *ctx)
 
        struct kr_nsrep *ns = &qry->ns;
        ELECT_INIT(ns, ctx);
-       int ret = map_walk(&qry->zone_cut.nsset, eval_nsrep, qry);
+
+       int ret = kr_ok();
+       trie_it_t *it;
+       for (it = trie_it_begin(qry->zone_cut.nsset); !trie_it_finished(it);
+                                                       trie_it_next(it)) {
+               ret = eval_nsrep(/* we trust it's a correct dname */
+                                (const knot_dname_t *)trie_it_key(it, NULL),
+                                (const pack_t *)*trie_it_val(it), qry);
+               if (ret) break;
+       }
+       trie_it_free(it);
+
        if (qry->ns.score <= KR_NS_MAX_SCORE && qry->ns.score >= KR_NS_LONG) {
                /* This is a low-reliability probe,
                 * go with TCP to get ICMP reachability check. */
@@ -357,7 +366,7 @@ int kr_nsrep_elect_addr(struct kr_query *qry, struct kr_context *ctx)
        /* Get address list for this NS */
        struct kr_nsrep *ns = &qry->ns;
        ELECT_INIT(ns, ctx);
-       pack_t *addr_set = map_get(&qry->zone_cut.nsset, (const char *)ns->name);
+       pack_t *addr_set = kr_zonecut_find(&qry->zone_cut, ns->name);
        if (!addr_set) {
                return kr_error(ENOENT);
        }
index e655f39c25387a9460f555aaddcac6e96f2e4f9c..d5240d86ee6037d09bfb7c6569d7f81e7c25c860 100644 (file)
@@ -268,7 +268,7 @@ static int ns_fetch_cut(struct kr_query *qry, const knot_dname_t *requested_name
        }
        /* Check if any DNSKEY found for cached cut */
        if (qry->flags.DNSSEC_WANT && cut_found.key == NULL &&
-           !kr_zonecut_has_glue(&cut_found)) {
+           kr_zonecut_is_empty(&cut_found)) {
                /* Cut found and there are no proofs of zone insecurity.
                 * But no DNSKEY found and no glue fetched.
                 * We have got circular dependency - must fetch A\AAAA
@@ -1428,7 +1428,7 @@ ns_election:
                }
                kr_nsrep_elect(qry, request->ctx);
                if (qry->ns.score > KR_NS_MAX_SCORE) {
-                       if (!qry->zone_cut.nsset.root) {
+                       if (kr_zonecut_is_empty(&qry->zone_cut)) {
                                VERBOSE_MSG(qry, "=> no NS with an address\n");
                        } else {
                                VERBOSE_MSG(qry, "=> no valid NS left\n");
index 9645b018eb61c2dcb7f19cb0049456cc5b4a7604..73218d0368bc486012acae0b92bb76c7f75db131 100644 (file)
@@ -60,15 +60,25 @@ int kr_zonecut_init(struct kr_zonecut *cut, const knot_dname_t *name, knot_mm_t
        cut->key  = NULL;
        cut->trust_anchor = NULL;
        cut->parent = NULL;
-       cut->nsset = map_make(pool);
-       return kr_ok();
+       cut->nsset = trie_create(pool);
+       return cut->name && cut->nsset ? kr_ok() : kr_error(ENOMEM);
 }
 
-static int free_addr_set(const char *k, void *v, void *baton)
+/** Completely free a pack_t. */
+static inline void free_addr_set(pack_t *pack, knot_mm_t *pool)
+{
+       if (unlikely(!pack)) {
+               /* promised we don't store NULL packs */
+               assert(false);
+               return;
+       }
+       pack_clear_mm(*pack, mm_free, pool);
+       mm_free(pool, pack);
+}
+/** Trivial wrapper for use in trie_apply, due to ugly casting. */
+static int free_addr_set_cb(trie_val_t *v, void *pool)
 {
-       pack_t *pack = v;
-       pack_clear_mm(*pack, mm_free, baton);
-       mm_free(baton, pack);
+       free_addr_set(*v, pool);
        return kr_ok();
 }
 
@@ -78,8 +88,11 @@ void kr_zonecut_deinit(struct kr_zonecut *cut)
                return;
        }
        mm_free(cut->pool, cut->name);
-       map_walk(&cut->nsset, free_addr_set, cut->pool);
-       map_clear(&cut->nsset);
+       if (cut->nsset) {
+               trie_apply(cut->nsset, free_addr_set_cb, cut->pool);
+               trie_free(cut->nsset);
+               cut->nsset = NULL;
+       }
        knot_rrset_free(&cut->key, cut->pool);
        knot_rrset_free(&cut->trust_anchor, cut->pool);
        cut->name = NULL;
@@ -99,43 +112,31 @@ void kr_zonecut_set(struct kr_zonecut *cut, const knot_dname_t *name)
        cut->trust_anchor = ta;
 }
 
-static int copy_addr_set(const char *k, void *v, void *baton)
-{
-       pack_t *addr_set = v;
-       struct kr_zonecut *dst = baton;
-       /* Clone addr_set pack */
-       pack_t *new_set = mm_alloc(dst->pool, sizeof(*new_set));
-       if (!new_set) {
-               return kr_error(ENOMEM);
-       }
-       pack_init(*new_set);
-       /* Clone data only if needed */
-       if (addr_set->len > 0) {
-               new_set->at = mm_alloc(dst->pool, addr_set->len);
-               if (!new_set->at) {
-                       mm_free(dst->pool, new_set);
-                       return kr_error(ENOMEM);
-               }
-               memcpy(new_set->at, addr_set->at, addr_set->len);
-               new_set->len = addr_set->len;
-               new_set->cap = addr_set->len;
-       }
-       /* Reinsert */
-       if (map_set(&dst->nsset, k, new_set) != 0) {
-               pack_clear_mm(*new_set, mm_free, dst->pool);
-               mm_free(dst->pool, new_set);
-               return kr_error(ENOMEM);
-       }
-       return kr_ok();
-}
-
 int kr_zonecut_copy(struct kr_zonecut *dst, const struct kr_zonecut *src)
 {
        if (!dst || !src) {
                return kr_error(EINVAL);
        }
-       /* We're not touching src nsset, I promise */
-       return map_walk((map_t *)&src->nsset, copy_addr_set, dst);
+       if (!dst->nsset) {
+               dst->nsset = trie_create(dst->pool);
+       }
+       /* Copy the contents, one by one. */
+       int ret = kr_ok();
+       trie_it_t *it;
+       for (it = trie_it_begin(src->nsset); !trie_it_finished(it); trie_it_next(it)) {
+               size_t klen;
+               const char * const k = trie_it_key(it, &klen);
+               pack_t **new_pack = (pack_t **)trie_get_ins(dst->nsset, k, klen);
+               if (!new_pack) {
+                       ret = kr_error(ENOMEM);
+                       break;
+               }
+               const pack_t *old_pack = *trie_it_val(it);
+               ret = pack_clone(new_pack, old_pack, dst->pool);
+               if (ret) break;
+       }
+       trie_it_free(it);
+       return ret;
 }
 
 int kr_zonecut_copy_trust(struct kr_zonecut *dst, const struct kr_zonecut *src)
@@ -168,18 +169,16 @@ int kr_zonecut_copy_trust(struct kr_zonecut *dst, const struct kr_zonecut *src)
 
 int kr_zonecut_add(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rdata_t *rdata)
 {
-       if (!cut || !ns) {
+       if (!cut || !ns || !cut->nsset) {
                return kr_error(EINVAL);
        }
-       /* Fetch/insert nameserver. */
-       pack_t *pack = kr_zonecut_find(cut, ns);
-       if (pack == NULL) {
-               pack = mm_alloc(cut->pool, sizeof(*pack));
-               if (!pack || (map_set(&cut->nsset, (const char *)ns, pack) != 0)) {
-                       mm_free(cut->pool, pack);
-                       return kr_error(ENOMEM);
-               }
-               pack_init(*pack);
+       /* Get a pack_t for the ns. */
+       pack_t **pack = (pack_t **)trie_get_ins(cut->nsset, (const char *)ns, knot_dname_size(ns));
+       if (!pack) return kr_error(ENOMEM);
+       if (*pack == NULL) {
+               *pack = mm_alloc(cut->pool, sizeof(pack_t));
+               if (*pack == NULL) return kr_error(ENOMEM);
+               pack_init(**pack);
        }
        /* Insert data (if has any) */
        if (rdata == NULL) {
@@ -188,15 +187,15 @@ int kr_zonecut_add(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rd
        /* Check for duplicates */
        uint16_t rdlen = knot_rdata_rdlen(rdata);
        uint8_t *raw_addr = knot_rdata_data(rdata);
-       if (pack_obj_find(pack, raw_addr, rdlen)) {
+       if (pack_obj_find(*pack, raw_addr, rdlen)) {
                return kr_ok();
        }
        /* Push new address */
-       int ret = pack_reserve_mm(*pack, 1, rdlen, kr_memreserve, cut->pool);
+       int ret = pack_reserve_mm(**pack, 1, rdlen, kr_memreserve, cut->pool);
        if (ret != 0) {
                return kr_error(ENOMEM);
        }
-       return pack_obj_push(pack, raw_addr, rdlen);
+       return pack_obj_push(*pack, raw_addr, rdlen);
 }
 
 int kr_zonecut_del(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rdata_t *rdata)
@@ -217,8 +216,10 @@ int kr_zonecut_del(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rd
        }
        /* No servers left, remove NS from the set. */
        if (pack->len == 0) {
-               free_addr_set((const char *)ns, pack, cut->pool);
-               return map_del(&cut->nsset, (const char *)ns);
+               free_addr_set(pack, cut->pool);
+               ret = trie_del(cut->nsset, (const char *)ns, knot_dname_size(ns), NULL);
+               assert(ret == 0); /* only KNOT_ENOENT and that *can't* happen */
+               return (ret == 0) ? kr_ok() : kr_error(ret);
        }
 
        return ret;
@@ -231,12 +232,15 @@ int kr_zonecut_del_all(struct kr_zonecut *cut, const knot_dname_t *ns)
        }
 
        /* Find the address list; then free and remove it. */
-       pack_t *pack = kr_zonecut_find(cut, ns);
-       if (pack == NULL) {
+       pack_t *pack;
+       int ret = trie_del(cut->nsset, (const char *)ns, knot_dname_size(ns),
+                          (trie_val_t *)&pack);
+       if (ret) { /* deletion failed */
+               assert(ret == KNOT_ENOENT);
                return kr_error(ENOENT);
        }
-       free_addr_set((const char *)ns, pack, cut->pool);
-       return map_del(&cut->nsset, (const char *)ns);
+       free_addr_set(pack, cut->pool);
+       return kr_ok();
 }
 
 pack_t *kr_zonecut_find(struct kr_zonecut *cut, const knot_dname_t *ns)
@@ -244,58 +248,39 @@ pack_t *kr_zonecut_find(struct kr_zonecut *cut, const knot_dname_t *ns)
        if (!cut || !ns) {
                return NULL;
        }
-
-       const char *key = (const char *)ns;
-       map_t *nsset = &cut->nsset;
-       return map_get(nsset, key);
+       trie_val_t *val = trie_get_try(cut->nsset, (const char *)ns, knot_dname_size(ns));
+       /* we get pointer to the pack_t pointer */
+       return val ? (pack_t *)*val : NULL;
 }
 
-static int has_glue(const char *k, void *v, void *baton)
+static int has_address(trie_val_t *v, void *baton_)
 {
-       bool *glue_found = (bool *)baton;
-       if (*glue_found) {
-               assert(false);
-               return 1; /* short-circuit */
-       }
-
-       pack_t *pack = (pack_t *)v;
-       if (pack != NULL && pack->len != 0) {
-               *glue_found = true;
-               return 1; /* short-circuit */
-       }
-
-       return kr_ok();
+       const pack_t *pack = *v;
+       const bool found = pack != NULL && pack->len != 0;
+       return found;
 }
 
-bool kr_zonecut_has_glue(struct kr_zonecut *cut)
+bool kr_zonecut_is_empty(struct kr_zonecut *cut)
 {
-       if (!cut) {
-               return false;
+       if (!cut || !cut->nsset) {
+               assert(false);
+               return true;
        }
-
-       bool glue_found = false;
-       map_t *nsset = &cut->nsset;
-
-       map_walk(nsset, has_glue, &glue_found);
-       return glue_found;
+       return !trie_apply(cut->nsset, has_address, NULL);
 }
 
 int kr_zonecut_set_sbelt(struct kr_context *ctx, struct kr_zonecut *cut)
 {
-       if (!ctx || !cut) {
+       if (!ctx || !cut || !ctx->root_hints.nsset) {
                return kr_error(EINVAL);
        }
 
-       update_cut_name(cut, U8(""));
-       map_walk(&cut->nsset, free_addr_set, cut->pool);
-       map_clear(&cut->nsset);
+       trie_apply(cut->nsset, free_addr_set_cb, cut->pool);
+       trie_clear(cut->nsset);
 
+       update_cut_name(cut, U8(""));
        /* Copy root hints from resolution context. */
-       int ret = 0;
-       if (ctx->root_hints.nsset.root) {
-               ret = kr_zonecut_copy(cut, &ctx->root_hints);
-       }
-       return ret;
+       return kr_zonecut_copy(cut, &ctx->root_hints);
 }
 
 /** Fetch address for zone cut.  Any rank is accepted (i.e. glue as well). */
index d36f9f2b1f728b1e66e3c468619fb9b1b3a5d838..f1ab0c31cfda2e413c58024e20b681528afafb33 100644 (file)
 
 #pragma once
 
-#include "lib/generic/map.h"
-#include "lib/generic/pack.h"
-#include "lib/defines.h"
 #include "lib/cache/api.h"
+#include "lib/defines.h"
+#include "lib/generic/pack.h"
+#include "lib/generic/trie.h"
 
 struct kr_rplan;
 struct kr_context;
@@ -32,7 +32,7 @@ struct kr_zonecut {
        knot_rrset_t* key;  /**< Zone cut DNSKEY. */
        knot_rrset_t* trust_anchor; /**< Current trust anchor. */
        struct kr_zonecut *parent; /**< Parent zone cut. */
-       map_t nsset;        /**< Map of nameserver => address_set. */
+       trie_t *nsset;        /**< Map of nameserver => address_set (pack_t). */
        knot_mm_t *pool;     /**< Memory pool. */
 };
 
@@ -62,11 +62,13 @@ void kr_zonecut_deinit(struct kr_zonecut *cut);
 KR_EXPORT
 void kr_zonecut_set(struct kr_zonecut *cut, const knot_dname_t *name);
 
-/** 
+/**
  * Copy zone cut, including all data. Does not copy keys and trust anchor.
  * @param dst destination zone cut
  * @param src source zone cut
- * @return 0 or an error code
+ * @return 0 or an error code; If it fails with kr_error(ENOMEM),
+ * it may be in a half-filled state, but it's safe to deinit...
+ * @note addresses for names in `src` get replaced and others are left as they were.
  */
 KR_EXPORT
 int kr_zonecut_copy(struct kr_zonecut *dst, const struct kr_zonecut *src);
@@ -151,9 +153,11 @@ int kr_zonecut_find_cached(struct kr_context *ctx, struct kr_zonecut *cut,
                           const knot_dname_t *name, const struct kr_query *qry,
                           bool * restrict secured);
 /**
- * Check if any glue addresses are present in zone cut
+ * Check if any address is present in the zone cut.
  *
  * @param cut zone cut to check
  * @return true/false
  */
-bool kr_zonecut_has_glue(struct kr_zonecut *cut);
+KR_EXPORT
+bool kr_zonecut_is_empty(struct kr_zonecut *cut);
+
index ad3f66e0a3375b49bac8bfec15d69adb27fff34c..c7eb28ee365b13e2b2a53115909976da58db5f11 100644 (file)
@@ -506,27 +506,24 @@ static char* hint_get(void *env, struct kr_module *module, const char *args)
        return result;
 }
 
-/** Retrieve hint list. */
-static int pack_hint(const char *k, void *v, void *baton)
-{
-       char nsname_str[KNOT_DNAME_MAXLEN] = {'\0'};
-       knot_dname_to_str(nsname_str, (const uint8_t *)k, sizeof(nsname_str));
-       JsonNode *root_node = baton;
-       JsonNode *addr_list = pack_addrs((pack_t *)v);
-       if (!addr_list) {
-               return kr_error(ENOMEM);
-       }
-       json_append_member(root_node, nsname_str, addr_list);
-       return kr_ok();
-}
-
 /** @internal Pack all hints into serialized JSON. */
 static char* pack_hints(struct kr_zonecut *hints) {
        char *result = NULL;
        JsonNode *root_node = json_mkobject();
-       if (map_walk(&hints->nsset, pack_hint, root_node) == 0) {
-               result = json_encode(root_node);
-       }
+       trie_it_t *it;
+       for (it = trie_it_begin(hints->nsset); !trie_it_finished(it); trie_it_next(it)) {
+               char nsname_str[KNOT_DNAME_MAXLEN] = {'\0'};
+               knot_dname_to_str(nsname_str,
+                                       /* here we trust that it's a correct dname */
+                                       (const knot_dname_t *)trie_it_key(it, NULL),
+                                       sizeof(nsname_str));
+               JsonNode *addr_list = pack_addrs((pack_t *)*trie_it_val(it));
+               if (!addr_list) goto error;
+               json_append_member(root_node, nsname_str, addr_list);
+       }
+       result = json_encode(root_node);
+error:
+       trie_it_free(it);
        json_delete(root_node);
        return result;
 }
index 1f22ac1d6af4d057da8209c10e4e5aa25066beac..4877744fa917026851cb66b9ab234837ddc7540d 100644 (file)
@@ -37,19 +37,22 @@ static void test_zonecut_params(void **state)
 
 static void test_zonecut_copy(void **state)
 {
-       const knot_dname_t *root = (const uint8_t *)"";
+       const knot_dname_t *n_root = (const uint8_t *)"";
        struct kr_zonecut cut1, cut2;
-       kr_zonecut_init(&cut1, root, NULL);
-       kr_zonecut_init(&cut2, root, NULL);
+       kr_zonecut_init(&cut1, n_root, NULL);
+       kr_zonecut_init(&cut2, n_root, NULL);
        /* Insert some values */
-       assert_int_equal(kr_zonecut_add(&cut1, (const uint8_t *)"dead", NULL), 0);
-       assert_int_equal(kr_zonecut_add(&cut1, (const uint8_t *)"beef", NULL), 0);
+       const knot_dname_t
+               *n_1 = (const uint8_t *)"\4dead",
+               *n_2 = (const uint8_t *)"\3bee\1f";
+       assert_int_equal(kr_zonecut_add(&cut1, n_1, NULL), 0);
+       assert_int_equal(kr_zonecut_add(&cut1, n_2, NULL), 0);
        /* Copy */
        assert_int_equal(kr_zonecut_copy(&cut2, &cut1), 0);
        /* Check if exist */
-       assert_non_null(kr_zonecut_find(&cut2, (const uint8_t *)"dead"));
-       assert_non_null(kr_zonecut_find(&cut2, (const uint8_t *)"beef"));
-       assert_null(kr_zonecut_find(&cut2, (const uint8_t *)"corn"));
+       assert_non_null(kr_zonecut_find(&cut2, n_1));
+       assert_non_null(kr_zonecut_find(&cut2, n_2));
+       assert_null(kr_zonecut_find(&cut2, (const uint8_t *)"\5death"));
        kr_zonecut_deinit(&cut1);
        kr_zonecut_deinit(&cut2);
 }