}
#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;
}
//}
- 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);
* 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 {
}
- /** 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) {
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;
}
/** 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 {
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);
&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;
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. */
}
}
ans->rcode = PKT_NODATA;
- return kr_ok();
+ return AR_SOA;
} /* else */
/* The data probably exists -> don't add this NSEC