From: Marek VavruĊĦa Date: Thu, 1 Oct 2015 14:55:22 +0000 (+0200) Subject: lib/zonecut: use SBELT only when necessary, prefer cached information X-Git-Tag: v1.0.0-beta1~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3e7844f87c71df4646c2dc124d7f72ae7ca402fc;p=thirdparty%2Fknot-resolver.git lib/zonecut: use SBELT only when necessary, prefer cached information before the algorithm was happy with root hints for all queries starting at root, however they're often overloaded and result in timeouts the updated code provides SBELT only for root NS query lookup and tries to use cached information as much as possible --- diff --git a/lib/resolve.c b/lib/resolve.c index 40c62b461..cc031b12e 100644 --- a/lib/resolve.c +++ b/lib/resolve.c @@ -77,7 +77,7 @@ 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) { - int ret = 0; + int ret = kr_error(ENOENT); /* Find closest zone cut from cache */ struct kr_cache_txn txn; @@ -92,8 +92,6 @@ static int ns_fetch_cut(struct kr_query *qry, struct kr_request *req, bool secur 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; } @@ -122,6 +120,12 @@ static int ns_resolve_addr(struct kr_query *qry, struct kr_request *param) } /* 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; @@ -134,9 +138,14 @@ static int ns_resolve_addr(struct kr_query *qry, struct kr_request *param) 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) @@ -378,7 +387,19 @@ static int zone_cut_check(struct kr_request *request, struct kr_query *qry, knot } 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)) { @@ -494,7 +515,8 @@ ns_election: /* 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 */ } diff --git a/lib/zonecut.c b/lib/zonecut.c index 1bd0e1a59..36046c391 100644 --- a/lib/zonecut.c +++ b/lib/zonecut.c @@ -257,32 +257,29 @@ int kr_zonecut_set_sbelt(struct kr_context *ctx, struct kr_zonecut *cut) } 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. */ @@ -330,11 +327,6 @@ static int fetch_ns(struct kr_context *ctx, struct kr_zonecut *cut, const knot_d } } - /* Always keep SBELT as a backup for root */ - if (name[0] == '\0') { - kr_zonecut_set_sbelt(ctx, cut); - } - return kr_ok(); } @@ -411,6 +403,5 @@ int kr_zonecut_find_cached(struct kr_context *ctx, struct kr_zonecut *cut, const 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); } diff --git a/lib/zonecut.h b/lib/zonecut.h index 5ea58d2ca..91b951544 100644 --- a/lib/zonecut.h +++ b/lib/zonecut.h @@ -126,7 +126,7 @@ int kr_zonecut_set_sbelt(struct kr_context *ctx, struct kr_zonecut *cut); * @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); diff --git a/tests/kresd.j2 b/tests/kresd.j2 index 2f787b5cf..7ddcccee9 100644 --- a/tests/kresd.j2 +++ b/tests/kresd.j2 @@ -1,9 +1,10 @@ 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)