From 01b7fda7549fffd7542c01b7469296ec776653ec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Vavru=C5=A1a?= <marek.vavrusa@nic.cz>
Date: Sat, 3 Oct 2015 14:31:19 +0200
Subject: [PATCH] lib/resolve: fixed bug with root NS/DNSKEY priming qry

---
 lib/resolve.c | 21 ++++++++++++++++-----
 lib/zonecut.c |  3 ---
 2 files changed, 16 insertions(+), 8 deletions(-)

diff --git a/lib/resolve.c b/lib/resolve.c
index cc031b12e..f415b9e16 100644
--- a/lib/resolve.c
+++ b/lib/resolve.c
@@ -138,10 +138,15 @@ static int ns_resolve_addr(struct kr_query *qry, struct kr_request *param)
 	if (!next) {
 		return kr_error(ENOMEM);
 	}
-	/* At the root level with no NS addresses, revert to SBELT. */
+	/* At the root level with no NS addresses, add SBELT subrequest. */
 	int ret = 0;
 	if (qry->zone_cut.name[0] == '\0') {
-		ret = kr_zonecut_set_sbelt(ctx, &qry->zone_cut);
+		ret = kr_zonecut_set_sbelt(ctx, &next->zone_cut);
+		if (ret == 0) { /* Copy TA and key since it's the same cut to avoid lookup. */
+			kr_zonecut_copy_trust(&next->zone_cut, &qry->zone_cut);
+			kr_zonecut_set_sbelt(ctx, &qry->zone_cut); /* Add SBELT to parent in case query fails. */
+			qry->flags |= QUERY_NO_THROTTLE; /* Pick even bad SBELT servers */
+		}
 	} else {
 		next->flags |= QUERY_AWAIT_CUT;
 	}
@@ -422,7 +427,7 @@ static int zone_cut_check(struct kr_request *request, struct kr_query *qry, knot
 		WITH_DEBUG {
 		char qname_str[KNOT_DNAME_MAXLEN];
 		knot_dname_to_str(qname_str, qry->zone_cut.name, sizeof(qname_str));
-		DEBUG_MSG(">< TA: using '%s'\n", qname_str);
+		DEBUG_MSG(">< TA: '%s'\n", qname_str);
 		}
 	}
 	if (want_secured && !qry->zone_cut.trust_anchor) {
@@ -504,6 +509,11 @@ ns_election:
 	if (qry->flags & (QUERY_AWAIT_IPV4|QUERY_AWAIT_IPV6)) {
 		kr_nsrep_elect_addr(qry, request->ctx);
 	} else if (!(qry->flags & QUERY_TCP)) { /* Keep address when TCP retransmit. */
+		/* Root DNSKEY must be fetched from the hints to avoid chicken and egg problem. */
+		if (qry->sname[0] == '\0' && qry->stype == KNOT_RRTYPE_DNSKEY) {
+			DEBUG_MSG("=> priming root DNSKEY\n");
+			kr_zonecut_set_sbelt(request->ctx, &qry->zone_cut);
+		}
 		kr_nsrep_elect(qry, request->ctx);
 		if (qry->ns.score > KR_NS_MAX_SCORE) {
 			DEBUG_MSG("=> no valid NS left\n");
@@ -541,8 +551,9 @@ ns_election:
 			break;
 		}
 		inet_ntop(addr->sa_family, kr_nsrep_inaddr(qry->ns.addr[i]), ns_str, sizeof(ns_str));
-		DEBUG_MSG("%c> querying: '%s' score: %u zone cut: '%s' m12n: '%s' type: '%s'\n",
-		          i == 0 ? '=' : '+', ns_str, qry->ns.score, zonecut_str, qname_str, type_str);
+		DEBUG_MSG("%s: '%s' score: %u zone cut: '%s' m12n: '%s' type: '%s'\n",
+		          i == 0 ? "=> querying" : "   optional",
+		          ns_str, qry->ns.score, zonecut_str, qname_str, type_str);
 	}
 	}
 
diff --git a/lib/zonecut.c b/lib/zonecut.c
index 36046c391..b55688781 100644
--- a/lib/zonecut.c
+++ b/lib/zonecut.c
@@ -276,9 +276,6 @@ int kr_zonecut_set_sbelt(struct kr_context *ctx, struct kr_zonecut *cut)
 			}
 		}
 	}
-
-	/* Set trust anchor. */
-	knot_rrset_free(&cut->trust_anchor, cut->pool);
 	return ret;
 }
 
-- 
GitLab