]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Disambiguate `query_cname()` and `query_dname()` usage
authorColin Vidal <colin@isc.org>
Mon, 22 Jun 2026 11:27:09 +0000 (13:27 +0200)
committerMichał Kępień <michal@isc.org>
Fri, 10 Jul 2026 07:26:46 +0000 (09:26 +0200)
Make explicit the fact that `query_cname()` and `query_dname()` must be
called only from a context where the resolver is answering a question
which is _not_ respectively `CNAME` or `DNAME`.

lib/dns/resolver.c
lib/ns/query.c

index a094eeb430bfd10b799802c867705e8a1d36037a..f27a8a63c1ec0c501ccd5935007e965d7c75b231 100644 (file)
@@ -5480,6 +5480,23 @@ has_000_label(dns_rdataset_t *nsecset) {
        return false;
 }
 
+/*
+ * After a (non-error) negative-cache add, 'rdataset' is bound to whatever
+ * rdataset the cache authoritatively holds for the queried name and type.
+ * Map that to the result code the fetch should report:
+ *
+ *   - A negative cache entry (the one we just added, or a pre-existing one):
+ *     DNS_R_NCACHENXDOMAIN or DNS_R_NCACHENXRRSET, depending on NXDOMAIN vs
+ *     NODATA.
+ *
+ *   - A positive rdataset that was already cached at higher trust, which
+ *     caused our negative entry to be discarded (e.g. a CNAME or DNAME cached
+ *     by a concurrent query): ISC_R_SUCCESS, because that cached positive
+ *     answer is what gets returned.  Note the specific case for CNAME and
+ *     DNAME *if* the query type is not the same as the rdataset type. There
+ *     is a chain to follow *only* if the query type doesn't ask for the CNAME
+ *     or the DNAME.
+ */
 static void
 fctx_setresult(fetchctx_t *fctx) {
        isc_result_t result = ISC_R_SUCCESS;
index 2a68906ae9fd37d06d3b350f7dad5bf54b780ecd..615f3b8e05c1cd2a6c6235636bc4e9703e1126d1 100644 (file)
@@ -9811,7 +9811,7 @@ cleanup:
 }
 
 /*
- * Handle CNAME responses.
+ * Handle CNAME responses of a query which its type is _not_ CNAME.
  */
 static isc_result_t
 query_cname(query_ctx_t *qctx) {
@@ -9826,6 +9826,8 @@ query_cname(query_ctx_t *qctx) {
 
        CALL_HOOK(NS_QUERY_CNAME_BEGIN, qctx);
 
+       REQUIRE(qctx->result != DNS_R_CNAME);
+
        result = query_zerottl_refetch(qctx);
        if (result != ISC_R_COMPLETE) {
                goto cleanup;
@@ -9913,7 +9915,7 @@ cleanup:
 }
 
 /*
- * Handle DNAME responses.
+ * Handle DNAME responses of a query which its type is _not_ DNAME.
  */
 static isc_result_t
 query_dname(query_ctx_t *qctx) {
@@ -9933,6 +9935,8 @@ query_dname(query_ctx_t *qctx) {
 
        CALL_HOOK(NS_QUERY_DNAME_BEGIN, qctx);
 
+       REQUIRE(qctx->result != DNS_R_DNAME);
+
        /*
         * Compare the current qname to the found name.  We need
         * to know how many labels and bits are in common because