/** 1b. otherwise, find the longest prefix NS/xNAME (with OK time+rank). [...] */
k->dname = qry->sname;
const struct entry_h *eh = closest_NS(ctx, k);
+#if 0
if (!eh) { /* fall back to root hints? */
ret = kr_zonecut_set_sbelt(req->ctx, &qry->zone_cut);
if (ret) return KR_STATE_FAIL;
//qry->flags.AWAIT_CUT = false;
return ctx->state;
}
+#endif
switch (k->type) {
// FIXME xNAME: return/generate whatever is required
case KNOT_RRTYPE_NS:
return ctx->state;
}
+#if 0
/* Now `eh` points to the closest NS record that we've found,
* and that's the only place to start - we may either find
* a negative proof or we may query upstream from that point. */
kr_zonecut_set(&qry->zone_cut, k->dname);
ret = kr_make_query(qry, pkt); // FIXME: probably not yet - qname minimization
if (ret) return KR_STATE_FAIL;
+#endif
/* Note: up to here we can run on any cache backend,
*/
const uint32_t min_ttl = MAX(DEFAULT_MINTTL, req->ctx->cache.ttl_min);
+ ranked_rr_array_t *selected[] = kr_request_selected(req);
for (int psec = KNOT_ANSWER; psec <= KNOT_AUTHORITY; ++psec) {
- const ranked_rr_array_t *arr = psec == KNOT_ANSWER
- ? &req->answ_selected : &req->auth_selected;
+ const ranked_rr_array_t *arr = selected[psec];
/* uncached entries are located at the end */
for (ssize_t i = arr->len - 1; i >= 0; --i) {
ranked_rr_array_entry_t *entry = arr->at[i];
struct kr_cache_p *peek)
{
struct key k_storage, *k = &k_storage;
+
+ WITH_VERBOSE {
+ VERBOSE_MSG(NULL, "_peek_exact: ");
+ kr_rrtype_print(type, "", " ");
+ kr_dname_print(name, "", " ");
+ }
+
int ret = knot_dname_lf(k->buf, name, NULL);
if (ret) {
+ kr_log_verbose("ERROR!\n");
return KR_STATE_FAIL;
}
k->name_len = k->buf[0];
knot_db_val_t val = { };
ret = cache_op(cache, read, &key, &val, 1);
if (ret) {
+ kr_log_verbose("miss\n");
return ret;
}
const struct entry_h *eh = entry_h_consistent(val, ktype);
if (!eh || (type == KNOT_RRTYPE_NS && !eh->has_ns)) {
+ kr_log_verbose("miss\n");
return kr_error(ENOENT);
}
*peek = (struct kr_cache_p){
.data = val.data,
.data_bound = val.data + val.len,
};
+ kr_log_verbose("hit\n");
return kr_ok();
}
if (new_ttl < 0) break;
// FIXME: xNAME
//uint16_t ktype = exact_match ? KNOT_RRTYPE_CNAME : KNOT_RRTYPE_DNAME;
- if (eh->has_ns && !eh->is_negative) {
- /* any kr_rank is accepted, as insecure or even nonauth is OK */
- k->type = KNOT_RRTYPE_NS;
- return eh;
+ if (!eh->has_ns || eh->is_negative) {
+ break;
}
+ /* any kr_rank is accepted, as insecure or even nonauth is OK */
+ k->type = KNOT_RRTYPE_NS;
+ return eh;
}
case (-abs(ENOENT)):
break;
}
/** @internal From \a pkt, fetch glue records for name \a ns, and update the cut etc. */
-static void fetch_glue(knot_pkt_t *pkt, const knot_dname_t *ns, struct kr_request *req)
+static void fetch_glue(knot_pkt_t *pkt, const knot_dname_t *ns, bool in_bailiwick,
+ struct kr_request *req, const struct kr_query *qry)
{
+ ranked_rr_array_t *selected[] = kr_request_selected(req);
for (knot_section_t i = KNOT_ANSWER; i <= KNOT_ADDITIONAL; ++i) {
const knot_pktsection_t *sec = knot_pkt_section(pkt, i);
for (unsigned k = 0; k < sec->count; ++k) {
(rr->type != KNOT_RRTYPE_AAAA)) {
continue;
}
+
+ uint8_t rank = (in_bailiwick && i == KNOT_ANSWER)
+ ? (KR_RANK_INITIAL | KR_RANK_AUTH) : KR_RANK_OMIT;
+ (void) kr_ranked_rrarray_add(selected[i], rr, rank,
+ false, qry->uid, &req->pool);
+
if ((rr->type == KNOT_RRTYPE_A) &&
(req->ctx->options.NO_IPV4)) {
continue;
}
/** Attempt to find glue for given nameserver name (best effort). */
-static int has_glue(knot_pkt_t *pkt, const knot_dname_t *ns)
+static bool has_glue(knot_pkt_t *pkt, const knot_dname_t *ns)
{
for (knot_section_t i = KNOT_ANSWER; i <= KNOT_ADDITIONAL; ++i) {
const knot_pktsection_t *sec = knot_pkt_section(pkt, i);
const knot_rrset_t *rr = knot_pkt_rr(sec, k);
if (knot_dname_is_equal(ns, rr->owner) &&
(rr->type == KNOT_RRTYPE_A || rr->type == KNOT_RRTYPE_AAAA)) {
- return 1;
+ return true;
}
}
}
- return 0;
+ return false;
}
/** @internal Update the cut with another NS(+glue) record.
/* Fetch glue for each NS */
for (unsigned i = 0; i < rr->rrs.rr_count; ++i) {
const knot_dname_t *ns_name = knot_ns_name(&rr->rrs, i);
- int glue_records = has_glue(pkt, ns_name);
/* Glue is mandatory for NS below zone */
- if (!glue_records && knot_dname_in(rr->owner, ns_name)) {
- VERBOSE_MSG("<= authority: missing mandatory glue, rejecting\n");
+ if (knot_dname_in(rr->owner, ns_name) && !has_glue(pkt, ns_name)) {
+ VERBOSE_MSG("<= authority: missing mandatory glue, skipping NS ");
+ WITH_VERBOSE {
+ kr_dname_print(ns_name, "", "\n");
+ }
continue;
}
- kr_zonecut_add(cut, ns_name, NULL);
+ int ret = kr_zonecut_add(cut, ns_name, NULL);
+ assert(!ret);
+
/* Choose when to use glue records. */
+ bool in_bailiwick = knot_dname_in(current_cut, ns_name);
+ bool do_fetch;
if (qry->flags.PERMISSIVE) {
- fetch_glue(pkt, ns_name, req);
+ do_fetch = true;
} else if (qry->flags.STRICT) {
/* Strict mode uses only mandatory glue. */
- if (knot_dname_in(cut->name, ns_name))
- fetch_glue(pkt, ns_name, req);
+ do_fetch = knot_dname_in(cut->name, ns_name);
} else {
/* Normal mode uses in-bailiwick glue. */
- if (knot_dname_in(current_cut, ns_name))
- fetch_glue(pkt, ns_name, req);
+ do_fetch = in_bailiwick;
+ }
+ if (do_fetch) {
+ fetch_glue(pkt, ns_name, in_bailiwick, req, qry);
}
}
array_init(request->additional);
array_init(request->answ_selected);
array_init(request->auth_selected);
+ array_init(request->add_selected);
request->answ_validated = false;
request->auth_validated = false;
}
kr_nsrep_elect(qry, request->ctx);
if (qry->ns.score > KR_NS_MAX_SCORE) {
- VERBOSE_MSG(qry, "=> no valid NS left\n");
+ if (!qry->zone_cut.nsset.root) {
+ VERBOSE_MSG(qry, "=> no NS with an address\n");
+ } else {
+ VERBOSE_MSG(qry, "=> no valid NS left\n");
+ }
ITERATE_LAYERS(request, qry, reset);
kr_rplan_pop(rplan, qry);
return KR_STATE_PRODUCE;
int state;
ranked_rr_array_t answ_selected;
ranked_rr_array_t auth_selected;
+ ranked_rr_array_t add_selected;
rr_array_t additional;
bool answ_validated; /**< internal to validator; beware of caching, etc. */
bool auth_validated; /**< see answ_validated ^^ ; TODO */
knot_mm_t pool;
};
+/** Initializer for an array of *_selected. */
+#define kr_request_selected(req) { \
+ [KNOT_ANSWER] = &(req)->answ_selected, \
+ [KNOT_AUTHORITY] = &(req)->auth_selected, \
+ [KNOT_ADDITIONAL] = &(req)->add_selected, \
+ }
+
/**
* Begin name resolution.
*