static int ns_fetch_cut(struct kr_query *qry, struct kr_request *req, bool secured)
{
- int ret = 0;
+ int ret = kr_error(ENOENT);
/* Find closest zone cut from cache */
struct kr_cache_txn txn;
ret = kr_zonecut_find_cached(req->ctx, &qry->zone_cut, qry->sname, &txn, qry->timestamp.tv_sec, secured);
}
kr_cache_txn_abort(&txn);
- } else {
- ret = kr_zonecut_set_sbelt(req->ctx, &qry->zone_cut);
}
return ret;
}
}
/* Bail out if the query is already pending or dependency loop. */
if (!next_type || kr_rplan_satisfies(qry->parent, qry->ns.name, KNOT_CLASS_IN, next_type)) {
+ /* Fall back to SBELT if root server query fails. */
+ if (!next_type && qry->zone_cut.name[0] == '\0') {
+ DEBUG_MSG("=> fallback to root hints\n");
+ kr_zonecut_set_sbelt(ctx, &qry->zone_cut);
+ return kr_error(EAGAIN);
+ }
/* No IPv4 nor IPv6, flag server as unuseable. */
DEBUG_MSG("=> unresolvable NS address, bailing out\n");
qry->ns.reputation |= KR_NS_NOIP4 | KR_NS_NOIP6;
if (!next) {
return kr_error(ENOMEM);
}
-
- next->flags |= QUERY_AWAIT_CUT;
- return kr_ok();
+ /* At the root level with no NS addresses, revert to SBELT. */
+ int ret = 0;
+ if (qry->zone_cut.name[0] == '\0') {
+ ret = kr_zonecut_set_sbelt(ctx, &qry->zone_cut);
+ } else {
+ next->flags |= QUERY_AWAIT_CUT;
+ }
+ return ret;
}
static int edns_put(knot_pkt_t *pkt)
}
int ret = ns_fetch_cut(qry, request, (qry->flags & QUERY_DNSSEC_WANT));
if (ret != 0) {
- return KNOT_STATE_FAIL;
+ /* No cached cut found, start from SBELT and issue priming query. */
+ if (ret == kr_error(ENOENT)) {
+ DEBUG_MSG("=> root priming query\n");
+ ret = kr_zonecut_set_sbelt(request->ctx, &qry->zone_cut);
+ if (ret != 0) {
+ return KNOT_STATE_FAIL;
+ }
+ zone_cut_subreq(rplan, qry, qry->zone_cut.name, KNOT_RRTYPE_NS);
+ qry->flags &= ~QUERY_AWAIT_CUT;
+ return KNOT_STATE_DONE;
+ } else {
+ return KNOT_STATE_FAIL;
+ }
}
/* Update minimized QNAME if zone cut changed */
if (qry->zone_cut.name[0] != '\0' && !(qry->flags & QUERY_NO_MINIMIZE)) {
/* Resolve address records */
if (qry->ns.addr[0].ip.sa_family == AF_UNSPEC) {
- if (ns_resolve_addr(qry, request) != 0) {
+ int ret = ns_resolve_addr(qry, request);
+ if (ret != 0) {
qry->flags &= ~(QUERY_AWAIT_IPV6|QUERY_AWAIT_IPV4|QUERY_TCP);
goto ns_election; /* Must try different NS */
}
}
update_cut_name(cut, U8(""));
+ map_walk(&cut->nsset, free_addr_set, cut->pool);
+ map_clear(&cut->nsset);
/* Copy root hints from resolution context. */
+ int ret = 0;
if (ctx->root_hints.nsset.root) {
- int ret = kr_zonecut_copy(cut, &ctx->root_hints);
- if (ret == 0) {
- ret = kr_zonecut_copy_trust(cut, &ctx->root_hints);
- }
- if (ret == 0) {
- return ret;
- }
- }
-
- /* Copy compiled-in root hints */
- for (unsigned i = 0; i < HINT_COUNT; ++i) {
- const struct hint_info *hint = &SBELT[i];
- knot_rdata_t rdata[knot_rdata_array_size(HINT_ADDRLEN)];
- knot_rdata_init(rdata, HINT_ADDRLEN, hint->addr, 0);
- int ret = kr_zonecut_add(cut, hint->name, rdata);
- if (ret != 0) {
- return ret;
+ ret = kr_zonecut_copy(cut, &ctx->root_hints);
+ } else {
+ /* Copy compiled-in root hints */
+ for (unsigned i = 0; i < HINT_COUNT; ++i) {
+ const struct hint_info *hint = &SBELT[i];
+ knot_rdata_t rdata[knot_rdata_array_size(HINT_ADDRLEN)];
+ knot_rdata_init(rdata, HINT_ADDRLEN, hint->addr, 0);
+ ret = kr_zonecut_add(cut, hint->name, rdata);
+ if (ret != 0) {
+ break;
+ }
}
}
/* Set trust anchor. */
knot_rrset_free(&cut->trust_anchor, cut->pool);
- return kr_ok();
+ return ret;
}
/** Fetch address for zone cut. */
}
}
- /* Always keep SBELT as a backup for root */
- if (name[0] == '\0') {
- kr_zonecut_set_sbelt(ctx, cut);
- }
-
return kr_ok();
}
name = knot_wire_next_label(name, NULL);
}
- /* Name server not found, start with SBELT. */
- return kr_zonecut_set_sbelt(ctx, cut);
+ return kr_error(ENOENT);
}
* @param txn cache transaction (read)
* @param timestamp transaction timestamp
* @param secured search nearest containing a DNSKEY
- * @return 0 or error code
+ * @return 0 or error code (ENOENT if it doesn't find anything)
*/
int kr_zonecut_find_cached(struct kr_context *ctx, struct kr_zonecut *cut, const knot_dname_t *name,
struct kr_cache_txn *txn, uint32_t timestamp, bool secured);
net = { '{{SELF_ADDR}}' }
modules = {'stats', 'policy', 'hints'}
cache.size = 1*MB
-hints.root({['k.root-servers.net'] = '{{ROOT_ADDR}}'})
option('NO_MINIMIZE', {{NO_MINIMIZE}})
option('ALLOW_LOCAL', true)
+hints.config('/dev/null')
+hints.root({['k.root-servers.net'] = '{{ROOT_ADDR}}'})
trust_anchors.add('{{TRUST_ANCHOR}}')
verbose(true)