From: Vladimír Čunát Date: Fri, 19 Jan 2018 16:10:32 +0000 (+0100) Subject: cache: fix answers from wildcards X-Git-Tag: v2.0.0~6^2~18 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=be1a389135dbd07367ea64f83e0046558b145272;p=thirdparty%2Fknot-resolver.git cache: fix answers from wildcards Also make the control flow more readable and tweak comments. --- diff --git a/lib/cache.c b/lib/cache.c index 603e93bbd..bc8ef4dc1 100644 --- a/lib/cache.c +++ b/lib/cache.c @@ -420,9 +420,8 @@ static int cache_peek_real(kr_layer_t *ctx, knot_pkt_t *pkt) } #endif - /* collecting multiple NSEC* + RRSIG records, in preparation for the answer - * + track the progress - */ + /** Collecting multiple NSEC* + RRSIG records, in preparation for the answer + * + track the progress */ struct answer ans; memset(&ans, 0, sizeof(ans)); ans.mm = &pkt->mm; @@ -461,12 +460,14 @@ static int cache_peek_real(kr_layer_t *ctx, knot_pkt_t *pkt) } //} - if (!ans.rcode) { - /* Nothing suitable found. */ + if (ans.rcode != PKT_NODATA && ans.rcode != PKT_NXDOMAIN) { + assert(ans.rcode == 0); /* Nothing suitable found. */ return ctx->state; } + /* At this point, sname was either covered or matched. */ + const bool sname_covered = ans.rcode == PKT_NXDOMAIN; - /* Name of the closest (provable) encloser. */ + /** Name of the closest (provable) encloser. */ const knot_dname_t *clencl_name = qry->sname; for (int l = sname_labels; l > clencl_labels; --l) clencl_name = knot_wire_next_label(clencl_name, NULL); @@ -476,15 +477,15 @@ static int cache_peek_real(kr_layer_t *ctx, knot_pkt_t *pkt) * 3a. We want to query for NSEC* of source of synthesis (SS) or its predecessor, * providing us with a proof of its existence or non-existence. */ - if (ans.rcode == PKT_NODATA) { + if (!sname_covered) { /* No wildcard checks needed, as we proved that sname exists. */ assert(ans.nsec_v == 1); // for now - } else if (ans.nsec_v == 1 && ans.rcode == PKT_NXDOMAIN) { + } else if (ans.nsec_v == 1 && sname_covered) { int ret = nsec1_src_synth(k, &ans, clencl_name, cover_low_kwz, cover_hi_kwz, qry, cache); if (ret < 0) return ctx->state; - if (ret == AR_SOA) goto do_soa; + if (ret == AR_SOA) goto do_soa; /* SS was covered or matched for NODATA */ assert(ret == 0); } else { @@ -493,10 +494,10 @@ static int cache_peek_real(kr_layer_t *ctx, knot_pkt_t *pkt) } - /** 3b. We need to find wildcarded answer, if SS wasn't covered. - * (common for NSEC*) + /** 3b. We need to find wildcarded answer, if sname was covered + * and we don't have a full proof yet. (common for NSEC*) */ - if (ans.rcode == PKT_NOERROR) { + if (sname_covered) { /* Construct key for exact qry->stype + source of synthesis. */ int ret = kr_dname_lf(k->buf, clencl_name, true); if (ret) { @@ -541,7 +542,10 @@ static int cache_peek_real(kr_layer_t *ctx, knot_pkt_t *pkt) const void *eh_bound = val.data + val.len; ret = entry2answer(&ans, AR_ANSWER, eh, eh_bound, qry->sname, qry->stype, new_ttl); + VERBOSE_MSG(qry, "=> NSEC wildcard: answer expanded, ret = %d, new TTL %d\n", + ret, (int)new_ttl); if (ret) return ctx->state; + ans.rcode = PKT_NOERROR; } diff --git a/lib/cache/impl.h b/lib/cache/impl.h index e176feddb..c4215716d 100644 --- a/lib/cache/impl.h +++ b/lib/cache/impl.h @@ -168,7 +168,7 @@ int rdataset_dematerialize(const knot_rdataset_t *rds, void * restrict data); /** Partially constructed answer when gathering RRsets from cache. */ struct answer { - int rcode; /**< PKT_NODATA, etc. ?? */ + int rcode; /**< PKT_NODATA, etc. */ uint8_t nsec_v; /**< 1 or 3 */ knot_mm_t *mm; /**< Allocator for rrsets */ struct answer_rrset { @@ -224,9 +224,10 @@ int nsec1_encloser(struct key *k, struct answer *ans, knot_db_val_t *cover_low_kwz, knot_db_val_t *cover_hi_kwz, const struct kr_query *qry, struct kr_cache *cache); -/** Source of synthesis check for NSEC (1). +/** Source of synthesis (SS) check for NSEC (1). * To understand the interface, see the call point. - * \return 0: continue; AR_SOA: skip to adding SOA; <0: exit cache immediately. */ + * \return 0: continue; <0: exit cache immediately; + * AR_SOA: skip to adding SOA (SS was covered or matched for NODATA). */ int nsec1_src_synth(struct key *k, struct answer *ans, const knot_dname_t *clencl_name, knot_db_val_t cover_low_kwz, knot_db_val_t cover_hi_kwz, const struct kr_query *qry, struct kr_cache *cache); diff --git a/lib/cache/nsec1.c b/lib/cache/nsec1.c index 4b04f473e..a05ea106a 100644 --- a/lib/cache/nsec1.c +++ b/lib/cache/nsec1.c @@ -415,7 +415,7 @@ int nsec1_src_synth(struct key *k, struct answer *ans, const knot_dname_t *clenc &exact_match, &wild_low_kwz, NULL, &new_ttl); if (err) { VERBOSE_MSG(qry, "=> NSEC wildcard: %s\n", err); - return -ABS(ENOENT); + return kr_ok(); } /* Materialize the record into answer (speculatively). */ const struct entry_h *nsec_eh = val.data; @@ -452,7 +452,7 @@ int nsec1_src_synth(struct key *k, struct answer *ans, const knot_dname_t *clenc if (is_sub && kr_nsec_children_in_zone_check(bm, bm_size) != 0) { VERBOSE_MSG(qry, "=> NSEC wildcard: covered but delegated (or error)\n"); - ret = -ABS(ENOENT); + ret = kr_ok(); goto clean_wild; } /* We have a record proving wildcard non-existence. */ @@ -479,7 +479,7 @@ int nsec1_src_synth(struct key *k, struct answer *ans, const knot_dname_t *clenc } } ans->rcode = PKT_NODATA; - return kr_ok(); + return AR_SOA; } /* else */ /* The data probably exists -> don't add this NSEC