Commit 089b70b0 authored by Vladimír Čunát's avatar Vladimír Čunát

struct kr_zonecut::nsset: migrate from map_t to trie_t

parent d9317141
...@@ -594,9 +594,8 @@ static int init_resolver(struct engine *engine) ...@@ -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); knot_edns_init(engine->resolver.opt_rr, KR_EDNS_PAYLOAD, 0, KR_EDNS_VERSION, engine->pool);
/* Use default TLS padding */ /* Use default TLS padding */
engine->resolver.tls_padding = -1; 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_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 */ /* Open NS rtt + reputation cache */
lru_create(&engine->resolver.cache_rtt, LRU_RTT_SIZE, engine->pool, NULL); lru_create(&engine->resolver.cache_rtt, LRU_RTT_SIZE, engine->pool, NULL);
lru_create(&engine->resolver.cache_rep, LRU_REP_SIZE, engine->pool, NULL); lru_create(&engine->resolver.cache_rep, LRU_REP_SIZE, engine->pool, NULL);
......
...@@ -19,7 +19,8 @@ if not cache.current_size then ...@@ -19,7 +19,8 @@ if not cache.current_size then
cache.size = 100 * MB cache.size = 100 * MB
end 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() _hint_root_file()
end end
......
...@@ -119,12 +119,13 @@ typedef struct { ...@@ -119,12 +119,13 @@ typedef struct {
size_t len; size_t len;
size_t cap; size_t cap;
} ranked_rr_array_t; } ranked_rr_array_t;
typedef struct trie trie_t;
struct kr_zonecut { struct kr_zonecut {
knot_dname_t *name; knot_dname_t *name;
knot_rrset_t *key; knot_rrset_t *key;
knot_rrset_t *trust_anchor; knot_rrset_t *trust_anchor;
struct kr_zonecut *parent; struct kr_zonecut *parent;
map_t nsset; trie_t *nsset;
knot_mm_t *pool; knot_mm_t *pool;
}; };
typedef struct { typedef struct {
...@@ -286,6 +287,7 @@ int kr_ranked_rrarray_add(ranked_rr_array_t *, const knot_rrset_t *, uint8_t, _B ...@@ -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_set(struct kr_qflags *, struct kr_qflags);
void kr_qflags_clear(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 *); 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 *); void kr_zonecut_set(struct kr_zonecut *, const knot_dname_t *);
uint64_t kr_now(); uint64_t kr_now();
knot_rrset_t *kr_ta_get(map_t *, const knot_dname_t *); knot_rrset_t *kr_ta_get(map_t *, const knot_dname_t *);
......
...@@ -57,6 +57,7 @@ typedef void (*trace_callback_f)(struct kr_request *); ...@@ -57,6 +57,7 @@ typedef void (*trace_callback_f)(struct kr_request *);
struct ranked_rr_array_entry struct ranked_rr_array_entry
ranked_rr_array_entry_t ranked_rr_array_entry_t
ranked_rr_array_t ranked_rr_array_t
trie_t
struct kr_zonecut struct kr_zonecut
kr_qarray_t kr_qarray_t
struct kr_rplan struct kr_rplan
...@@ -154,6 +155,7 @@ EOF ...@@ -154,6 +155,7 @@ EOF
kr_qflags_set kr_qflags_set
kr_qflags_clear kr_qflags_clear
kr_zonecut_add kr_zonecut_add
kr_zonecut_is_empty
kr_zonecut_set kr_zonecut_set
kr_now kr_now
# Trust anchors # Trust anchors
......
...@@ -192,23 +192,30 @@ static inline int pack_obj_del(pack_t *pack, const uint8_t *obj, pack_objlen_t l ...@@ -192,23 +192,30 @@ static inline int pack_obj_del(pack_t *pack, const uint8_t *obj, pack_objlen_t l
return -1; return -1;
} }
/** Clone a pack into a mempool (can be NULL). /** Clone a pack, replacing destination pack; (*dst == NULL) is valid input.
* @return NULL on allocation failure. */ * @return kr_error(ENOMEM) on allocation failure. */
static inline pack_t * pack_clone(const pack_t *src, knot_mm_t *pool) 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 || !src) {
if (!dst) return dst; assert(false);
pack_init(*dst); return kr_error(EINVAL);
/* Clone data only if needed */ }
if (!pack_head(*src)) return dst; /* Get a valid pack_t. */
int ret = array_reserve_mm(*dst, src->len, kr_memreserve, pool); 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) { if (ret < 0) {
mm_free(pool, dst); return kr_error(ENOMEM);
return NULL;
} }
memcpy(dst->at, src->at, src->len); memcpy((*dst)->at, src->at, src->len);
dst->len = src->len; (*dst)->len = src->len;
return dst; return kr_ok();
} }
#ifdef __cplusplus #ifdef __cplusplus
......
...@@ -82,7 +82,7 @@ static void update_nsrep_set(struct kr_nsrep *ns, const knot_dname_t *name, uint ...@@ -82,7 +82,7 @@ static void update_nsrep_set(struct kr_nsrep *ns, const knot_dname_t *name, uint
#undef ADDR_SET #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[]) unsigned score, uint8_t *addr[])
{ {
kr_nsrep_rtt_lru_t *rtt_cache = ctx->cache_rtt; kr_nsrep_rtt_lru_t *rtt_cache = ctx->cache_rtt;
...@@ -209,9 +209,8 @@ get_next_iterator : ...@@ -209,9 +209,8 @@ get_next_iterator :
return rtt_cache_entry_score[0]; 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_nsrep *ns = &qry->ns;
struct kr_context *ctx = ns->ctx; struct kr_context *ctx = ns->ctx;
unsigned score = KR_NS_MAX_SCORE; unsigned score = KR_NS_MAX_SCORE;
...@@ -220,8 +219,8 @@ static int eval_nsrep(const char *k, void *v, void *baton) ...@@ -220,8 +219,8 @@ static int eval_nsrep(const char *k, void *v, void *baton)
/* Fetch NS reputation */ /* Fetch NS reputation */
if (ctx->cache_rep) { if (ctx->cache_rep) {
unsigned *cached = lru_get_try(ctx->cache_rep, k, unsigned *cached = lru_get_try(ctx->cache_rep, (const char *)owner,
knot_dname_size((const uint8_t *)k)); knot_dname_size(owner));
if (cached) { if (cached) {
reputation = *cached; reputation = *cached;
} }
...@@ -229,7 +228,6 @@ static int eval_nsrep(const char *k, void *v, void *baton) ...@@ -229,7 +228,6 @@ static int eval_nsrep(const char *k, void *v, void *baton)
/* Favour nameservers with unknown addresses to probe them, /* Favour nameservers with unknown addresses to probe them,
* otherwise discover the current best address for the NS. */ * otherwise discover the current best address for the NS. */
pack_t *addr_set = (pack_t *)v;
if (addr_set->len == 0) { if (addr_set->len == 0) {
score = KR_NS_UNKNOWN; score = KR_NS_UNKNOWN;
/* If the server doesn't have IPv6, give it disadvantage. */ /* 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) ...@@ -261,19 +259,19 @@ static int eval_nsrep(const char *k, void *v, void *baton)
return kr_ok(); return kr_ok();
} else if (score <= ns->score && } else if (score <= ns->score &&
(score < KR_NS_LONG || qry->flags.NO_THROTTLE)) { (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; ns->reputation = reputation;
} else if ((kr_rand_uint(100) < 10) && } else if ((kr_rand_uint(100) < 10) &&
(kr_rand_uint(KR_NS_MAX_SCORE) >= score)) { (kr_rand_uint(KR_NS_MAX_SCORE) >= score)) {
/* With 10% chance probe server with a probability /* With 10% chance probe server with a probability
* given by its RTT / MAX_RTT. */ * 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; ns->reputation = reputation;
return 1; /* Stop evaluation */ return 1; /* Stop evaluation */
} else if (ns->score > KR_NS_MAX_SCORE) { } else if (ns->score > KR_NS_MAX_SCORE) {
/* Check if any server was already selected. /* Check if any server was already selected.
* If no, pick current server and continue evaluation. */ * 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; ns->reputation = reputation;
} }
...@@ -339,7 +337,18 @@ int kr_nsrep_elect(struct kr_query *qry, struct kr_context *ctx) ...@@ -339,7 +337,18 @@ int kr_nsrep_elect(struct kr_query *qry, struct kr_context *ctx)
struct kr_nsrep *ns = &qry->ns; struct kr_nsrep *ns = &qry->ns;
ELECT_INIT(ns, ctx); 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) { if (qry->ns.score <= KR_NS_MAX_SCORE && qry->ns.score >= KR_NS_LONG) {
/* This is a low-reliability probe, /* This is a low-reliability probe,
* go with TCP to get ICMP reachability check. */ * 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) ...@@ -357,7 +366,7 @@ int kr_nsrep_elect_addr(struct kr_query *qry, struct kr_context *ctx)
/* Get address list for this NS */ /* Get address list for this NS */
struct kr_nsrep *ns = &qry->ns; struct kr_nsrep *ns = &qry->ns;
ELECT_INIT(ns, ctx); 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) { if (!addr_set) {
return kr_error(ENOENT); return kr_error(ENOENT);
} }
......
...@@ -268,7 +268,7 @@ static int ns_fetch_cut(struct kr_query *qry, const knot_dname_t *requested_name ...@@ -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 */ /* Check if any DNSKEY found for cached cut */
if (qry->flags.DNSSEC_WANT && cut_found.key == NULL && 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. /* Cut found and there are no proofs of zone insecurity.
* But no DNSKEY found and no glue fetched. * But no DNSKEY found and no glue fetched.
* We have got circular dependency - must fetch A\AAAA * 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 ...@@ -1428,7 +1428,7 @@ int kr_resolve_produce(struct kr_request *request, struct sockaddr **dst, int *t
} }
kr_nsrep_elect(qry, request->ctx); kr_nsrep_elect(qry, request->ctx);
if (qry->ns.score > KR_NS_MAX_SCORE) { 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"); VERBOSE_MSG(qry, "=> no NS with an address\n");
} else { } else {
VERBOSE_MSG(qry, "=> no valid NS left\n"); VERBOSE_MSG(qry, "=> no valid NS left\n");
......
...@@ -60,15 +60,25 @@ int kr_zonecut_init(struct kr_zonecut *cut, const knot_dname_t *name, knot_mm_t ...@@ -60,15 +60,25 @@ int kr_zonecut_init(struct kr_zonecut *cut, const knot_dname_t *name, knot_mm_t
cut->key = NULL; cut->key = NULL;
cut->trust_anchor = NULL; cut->trust_anchor = NULL;
cut->parent = NULL; cut->parent = NULL;
cut->nsset = map_make(pool); cut->nsset = trie_create(pool);
return kr_ok(); 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; free_addr_set(*v, pool);
pack_clear_mm(*pack, mm_free, baton);
mm_free(baton, pack);
return kr_ok(); return kr_ok();
} }
...@@ -78,8 +88,11 @@ void kr_zonecut_deinit(struct kr_zonecut *cut) ...@@ -78,8 +88,11 @@ void kr_zonecut_deinit(struct kr_zonecut *cut)
return; return;
} }
mm_free(cut->pool, cut->name); mm_free(cut->pool, cut->name);
map_walk(&cut->nsset, free_addr_set, cut->pool); if (cut->nsset) {
map_clear(&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->key, cut->pool);
knot_rrset_free(&cut->trust_anchor, cut->pool); knot_rrset_free(&cut->trust_anchor, cut->pool);
cut->name = NULL; cut->name = NULL;
...@@ -99,43 +112,31 @@ void kr_zonecut_set(struct kr_zonecut *cut, const knot_dname_t *name) ...@@ -99,43 +112,31 @@ void kr_zonecut_set(struct kr_zonecut *cut, const knot_dname_t *name)
cut->trust_anchor = ta; 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) int kr_zonecut_copy(struct kr_zonecut *dst, const struct kr_zonecut *src)
{ {
if (!dst || !src) { if (!dst || !src) {
return kr_error(EINVAL); return kr_error(EINVAL);
} }
/* We're not touching src nsset, I promise */ if (!dst->nsset) {
return map_walk((map_t *)&src->nsset, copy_addr_set, dst); 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) 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) ...@@ -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) 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); return kr_error(EINVAL);
} }
/* Fetch/insert nameserver. */ /* Get a pack_t for the ns. */
pack_t *pack = kr_zonecut_find(cut, ns); pack_t **pack = (pack_t **)trie_get_ins(cut->nsset, (const char *)ns, knot_dname_size(ns));
if (pack == NULL) { if (!pack) return kr_error(ENOMEM);
pack = mm_alloc(cut->pool, sizeof(*pack)); if (*pack == NULL) {
if (!pack || (map_set(&cut->nsset, (const char *)ns, pack) != 0)) { *pack = mm_alloc(cut->pool, sizeof(pack_t));
mm_free(cut->pool, pack); if (*pack == NULL) return kr_error(ENOMEM);
return kr_error(ENOMEM); pack_init(**pack);
}
pack_init(*pack);
} }
/* Insert data (if has any) */ /* Insert data (if has any) */
if (rdata == NULL) { if (rdata == NULL) {
...@@ -188,15 +187,15 @@ int kr_zonecut_add(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rd ...@@ -188,15 +187,15 @@ int kr_zonecut_add(struct kr_zonecut *cut, const knot_dname_t *ns, const knot_rd
/* Check for duplicates */ /* Check for duplicates */
uint16_t rdlen = knot_rdata_rdlen(rdata); uint16_t rdlen = knot_rdata_rdlen(rdata);
uint8_t *raw_addr = knot_rdata_data(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(); return kr_ok();
} }
/* Push new address */ /* 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) { if (ret != 0) {
return kr_error(ENOMEM); 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) 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 ...@@ -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. */ /* No servers left, remove NS from the set. */
if (pack->len == 0) { if (pack->len == 0) {
free_addr_set((const char *)ns, pack, cut->pool); free_addr_set(pack, cut->pool);
return map_del(&cut->nsset, (const char *)ns); 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; return ret;
...@@ -231,12 +232,15 @@ int kr_zonecut_del_all(struct kr_zonecut *cut, const knot_dname_t *ns) ...@@ -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. */ /* Find the address list; then free and remove it. */
pack_t *pack = kr_zonecut_find(cut, ns); pack_t *pack;
if (pack == NULL) { 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); return kr_error(ENOENT);
} }
free_addr_set((const char *)ns, pack, cut->pool); free_addr_set(pack, cut->pool);
return map_del(&cut->nsset, (const char *)ns); return kr_ok();
} }
pack_t *kr_zonecut_find(struct kr_zonecut *cut, const knot_dname_t *ns) 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) ...@@ -244,58 +248,39 @@ pack_t *kr_zonecut_find(struct kr_zonecut *cut, const knot_dname_t *ns)
if (!cut || !ns) { if (!cut || !ns) {
return NULL; return NULL;
} }
trie_val_t *val = trie_get_try(cut->nsset, (const char *)ns, knot_dname_size(ns));
const char *key = (const char *)ns; /* we get pointer to the pack_t pointer */
map_t *nsset = &cut->nsset; return val ? (pack_t *)*val : NULL;
return map_get(nsset, key);
} }
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; const pack_t *pack = *v;
if (*glue_found) { const bool found = pack != NULL && pack->len != 0;
assert(false); return found;
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();
} }
bool kr_zonecut_has_glue(struct kr_zonecut *cut) bool kr_zonecut_is_empty(struct kr_zonecut *cut)
{ {
if (!cut) { if (!cut || !cut->nsset) {
return false; assert(false);
return true;
} }
return !trie_apply(cut->nsset, has_address, NULL);
bool glue_found = false;
map_t *nsset = &cut->nsset;
map_walk(nsset, has_glue, &glue_found);
return glue_found;
} }
int kr_zonecut_set_sbelt(struct kr_context *ctx, struct kr_zonecut *cut) 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); return kr_error(EINVAL);
} }
update_cut_name(cut, U8("")); trie_apply(cut->nsset, free_addr_set_cb, cut->pool);
map_walk(&cut->nsset, free_addr_set, cut->pool); trie_clear(cut->nsset);
map_clear(&cut->nsset);
update_cut_name(cut, U8(""));
/* Copy root hints from resolution context. */ /* Copy root hints from resolution context. */
int ret = 0; return kr_zonecut_copy(cut, &ctx->root_hints);
if (ctx->root_hints.nsset.root) {
ret = kr_zonecut_copy(cut, &ctx->root_hints);
}
return ret;
} }
/** Fetch address for zone cut. Any rank is accepted (i.e. glue as well). */ /** Fetch address for zone cut. Any rank is accepted (i.e. glue as well). */
......
...@@ -16,10 +16,10 @@ ...@@ -16,10 +16,10 @@
#pragma once #pragma once
#include "lib/generic/map.h"
#include "lib/generic/pack.h"
#include "lib/defines.h"
#include "lib/cache/api.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_rplan;
struct kr_context; struct kr_context;
...@@ -32,7 +32,7 @@ struct kr_zonecut { ...@@ -32,7 +32,7 @@ struct kr_zonecut {
knot_rrset_t* key; /**< Zone cut DNSKEY. */ knot_rrset_t* key; /**< Zone cut DNSKEY. */
knot_rrset_t* trust_anchor; /**< Current trust anchor. */ knot_rrset_t* trust_anchor; /**< Current trust anchor. */
struct kr_zonecut *parent; /**< Parent zone cut. */ 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. */ knot_mm_t *pool; /**< Memory pool. */
}; };
...@@ -62,11 +62,13 @@ void kr_zonecut_deinit(struct kr_zonecut *cut); ...@@ -62,11 +62,13 @@ void kr_zonecut_deinit(struct kr_zonecut *cut);
KR_EXPORT KR_EXPORT
void kr_zonecut_set(struct kr_zonecut *cut, const knot_dname_t *name); 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. * Copy zone cut, including all data. Does not copy keys and trust anchor.
* @param dst destination zone cut * @param dst destination zone cut
* @param src source 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 KR_EXPORT
int kr_zonecut_copy(struct kr_zonecut *dst, const struct kr_zonecut *src); 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, ...@@ -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, const knot_dname_t *name, const struct kr_query *qry,
bool * restrict secured); 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 * @param cut zone cut to check
* @return true/false * @return true/false
*/ */
bool kr_zonecut_has_glue(struct kr_zonecut *cut); KR_EXPORT
bool kr_zonecut_is_empty(struct kr_zonecut *cut);
...@@ -506,27 +506,24 @@ static char* hint_get(void *env, struct kr_module *module, const char *args) ...@@ -506,27 +506,24 @@ static char* hint_get(void *env, struct kr_module *module, const char *args)
return result; 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. */ /** @internal Pack all hints into serialized JSON. */
static char* pack_hints(struct kr_zonecut *hints) { static char* pack_hints(struct kr_zonecut *hints) {
char *result = NULL; char *result = NULL;
JsonNode *root_node = json_mkobject(); JsonNode *root_node = json_mkobject();
if (map_walk(&hints->nsset, pack_hint, root_node) == 0) { trie_it_t *it;
result = json_encode(root_node); 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;