diff --git a/lib/resolve.c b/lib/resolve.c index 2e80d9591eea558874e598d9f7d22cafadc46296..218fd46c01d3546411527fdf433c794deb798d44 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -77,20 +77,23 @@ static int invalidate_ns(struct kr_rplan *rplan, struct kr_query *qry) static int ns_fetch_cut(struct kr_query *qry, struct kr_request *req, bool secured) { - struct kr_cache_txn txn; int ret = 0; - /* If at/subdomain of parent zone cut, start top-down search */ - struct kr_query *parent = qry->parent; - if (parent && knot_dname_in(parent->zone_cut.name, qry->sname)) { - return kr_zonecut_set_sbelt(req->ctx, &qry->zone_cut); - } /* Find closest zone cut from cache */ + struct kr_cache_txn txn; if (kr_cache_txn_begin(&req->ctx->cache, &txn, NAMEDB_RDONLY) != 0) { ret = kr_zonecut_set_sbelt(req->ctx, &qry->zone_cut); } else { - ret = kr_zonecut_find_cached(req->ctx, &qry->zone_cut, qry->sname, &txn, qry->timestamp.tv_sec, secured); - kr_cache_txn_abort(&txn); + /* If at/subdomain of parent zone cut, start from its encloser. + * This is for case when we get to a dead end (and need glue from parent), or DS refetch. */ + struct kr_query *parent = qry->parent; + if (parent && qry->sname[0] != '\0' && knot_dname_in(parent->zone_cut.name, qry->sname)) { + const knot_dname_t *encloser = knot_wire_next_label(parent->zone_cut.name, NULL); + ret = kr_zonecut_find_cached(req->ctx, &qry->zone_cut, encloser, &txn, qry->timestamp.tv_sec, secured); + } else { + ret = kr_zonecut_find_cached(req->ctx, &qry->zone_cut, qry->sname, &txn, qry->timestamp.tv_sec, secured); + kr_cache_txn_abort(&txn); + } } return ret; }