diff --git a/daemon/engine.c b/daemon/engine.c index e62d71135a4791b2acfdb8a3a15ab9103842d203..91390c452322e7713d69bc7bbb0c301ccf9d2789 100644 --- a/daemon/engine.c +++ b/daemon/engine.c @@ -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); diff --git a/daemon/lua/config.lua b/daemon/lua/config.lua index be414a7cd861d98aa6ca3b3dd76eb52e9bd3f341..448d6dd634de598afa23ec9d3cad7a025e3bc2af 100644 --- a/daemon/lua/config.lua +++ b/daemon/lua/config.lua @@ -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 diff --git a/daemon/lua/kres-gen.lua b/daemon/lua/kres-gen.lua index c2d1bce1748e2accbcce99a9d60df046bd7efa30..aaca2da688e17c2bf9ef790848635f69c0f7e06e 100644 --- a/daemon/lua/kres-gen.lua +++ b/daemon/lua/kres-gen.lua @@ -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 *); diff --git a/daemon/lua/kres-gen.sh b/daemon/lua/kres-gen.sh index b8266f97539c93c26c0e67e52049e29d279f6087..0fbffaae1ee97f4b2590a80683ba973cd387243b 100755 --- a/daemon/lua/kres-gen.sh +++ b/daemon/lua/kres-gen.sh @@ -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 diff --git a/lib/generic/pack.h b/lib/generic/pack.h index 4b16c9799cc5ef7df30cd90ca73845be977335b2..90c1b7218872e4f49f86012a6a2cdc4a2cdac32b 100644 --- a/lib/generic/pack.h +++ b/lib/generic/pack.h @@ -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 diff --git a/lib/nsrep.c b/lib/nsrep.c index 628adf3ce85ca2b5b7c570bcdfaa9a223ffe5b39..0420bdae0b6f48f53cde90229541840ecb0c5471 100644 --- a/lib/nsrep.c +++ b/lib/nsrep.c @@ -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); } diff --git a/lib/resolve.c b/lib/resolve.c index e655f39c25387a9460f555aaddcac6e96f2e4f9c..d5240d86ee6037d09bfb7c6569d7f81e7c25c860 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -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 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t } 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"); diff --git a/lib/zonecut.c b/lib/zonecut.c index 9645b018eb61c2dcb7f19cb0049456cc5b4a7604..73218d0368bc486012acae0b92bb76c7f75db131 100644 --- a/lib/zonecut.c +++ b/lib/zonecut.c @@ -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). */ diff --git a/lib/zonecut.h b/lib/zonecut.h index d36f9f2b1f728b1e66e3c468619fb9b1b3a5d838..f1ab0c31cfda2e413c58024e20b681528afafb33 100644 --- a/lib/zonecut.h +++ b/lib/zonecut.h @@ -16,10 +16,10 @@ #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); + diff --git a/modules/hints/hints.c b/modules/hints/hints.c index ad3f66e0a3375b49bac8bfec15d69adb27fff34c..c7eb28ee365b13e2b2a53115909976da58db5f11 100644 --- a/modules/hints/hints.c +++ b/modules/hints/hints.c @@ -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; } diff --git a/tests/test_zonecut.c b/tests/test_zonecut.c index 1f22ac1d6af4d057da8209c10e4e5aa25066beac..4877744fa917026851cb66b9ab234837ddc7540d 100644 --- a/tests/test_zonecut.c +++ b/tests/test_zonecut.c @@ -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); }