]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
further subdivide caching functions
authorEvan Hunt <each@isc.org>
Sun, 2 Mar 2025 06:15:11 +0000 (22:15 -0800)
committerOndřej Surý <ondrej@isc.org>
Tue, 5 Aug 2025 10:16:36 +0000 (12:16 +0200)
rctx_cacherdataset() has been split into two functions:
- rctx_cache_secure() starts validation for rdatasets
  that need it; they are then cached by the validator
  completion callback validated()
- rctx_cache_insecure() caches rdatasets immediately; it
  is called when validation is disabled or the data
  to be cached is glue.

lib/dns/resolver.c

index 17de4964f39b3ec575fbcf6d521dd787983da8c7..25ac0fa9602862a6a5dc0766505bd73553d90550 100644 (file)
@@ -5844,10 +5844,9 @@ fixttls(dns_view_t *view, dns_rdataset_t *rdataset,
 }
 
 static isc_result_t
-rctx_cacherdataset(respctx_t *rctx, dns_message_t *message, dns_name_t *name,
-                  dns_dbnode_t *node, dns_rdataset_t *rdataset,
-                  dns_rdataset_t *sigrdataset, bool secure_domain,
-                  bool need_validation) {
+rctx_cache_secure(respctx_t *rctx, dns_message_t *message, dns_name_t *name,
+                 dns_dbnode_t *node, dns_rdataset_t *rdataset,
+                 dns_rdataset_t *sigrdataset, bool need_validation) {
        isc_result_t result;
        fetchctx_t *fctx = rctx->fctx;
        resquery_t *query = rctx->query;
@@ -5855,141 +5854,135 @@ rctx_cacherdataset(respctx_t *rctx, dns_message_t *message, dns_name_t *name,
        dns_fetchresponse_t *resp = ISC_LIST_HEAD(fctx->resps);
        unsigned int options = 0;
 
-       if (secure_domain && rdataset->trust != dns_trust_glue) {
-               /*
-                * RRSIGs are validated as part of validating
-                * the type they cover.
-                */
-               if (rdataset->type == dns_rdatatype_rrsig) {
-                       return ISC_R_SUCCESS;
-               }
+       /*
+        * RRSIGs are validated as part of validating the type they cover.
+        */
+       if (dns_rdatatype_issig(rdataset->type)) {
+               return ISC_R_SUCCESS;
+       }
 
-               /*
-                * Ignore unrelated non-answer rdatasets that are
-                * missing signatures.
-                */
-               if (sigrdataset == NULL && need_validation && !ANSWER(rdataset))
-               {
-                       return ISC_R_SUCCESS;
-               }
+       /*
+        * Ignore unrelated non-answer rdatasets that are missing
+        * signatures.
+        */
+       if (sigrdataset == NULL && need_validation && !ANSWER(rdataset)) {
+               return ISC_R_SUCCESS;
+       }
 
-               /*
-                * Mark this rdataset/sigrdataset pair as pending data.
-                * Track whether it was additional or not.
-                */
-               if (rdataset->trust == dns_trust_additional) {
-                       rdataset->trust = dns_trust_pending_additional;
-               } else {
-                       rdataset->trust = dns_trust_pending_answer;
-               }
+       /*
+        * Mark this rdataset/sigrdataset pair as "pending".
+        */
+       if (rdataset->trust == dns_trust_additional) {
+               rdataset->trust = dns_trust_pending_additional;
+       } else {
+               rdataset->trust = dns_trust_pending_answer;
+       }
 
-               if (sigrdataset != NULL) {
-                       sigrdataset->trust = rdataset->trust;
-               }
+       if (sigrdataset != NULL) {
+               sigrdataset->trust = rdataset->trust;
+       }
 
-               if (ANSWER(rdataset) && need_validation) {
-                       if (!dns_rdatatype_ismulti(fctx->type)) {
-                               /*
-                                * This is The Answer.  We will validate
-                                * it, but first we cache the rest of the
-                                * response - it may contain useful keys.
-                                */
-                               INSIST(rctx->vrdataset == NULL &&
-                                      rctx->vsigrdataset == NULL);
-                               rctx->vrdataset = rdataset;
-                               rctx->vsigrdataset = sigrdataset;
-                       } else {
-                               /*
-                                * This is one of (potentially) multiple
-                                * answers to an ANY query.  To keep things
-                                * simple, we just start the validator
-                                * right away rather than caching first and
-                                * having to remember which rdatasets
-                                * needed validation.
-                                */
-                               valcreate(fctx, message, query->addrinfo, name,
-                                         rdataset->type, rdataset,
-                                         sigrdataset);
-                       }
+       if (ANSWER(rdataset) && need_validation) {
+               if (!dns_rdatatype_ismulti(fctx->type)) {
+                       /*
+                        * This is The Answer.  We will validate it,
+                        * but first we finish caching the rest of the
+                        * response; it may contain useful keys.
+                        */
+                       INSIST(rctx->vrdataset == NULL &&
+                              rctx->vsigrdataset == NULL);
+                       rctx->vrdataset = rdataset;
+                       rctx->vsigrdataset = sigrdataset;
                } else {
-                       if (ANSWER(rdataset)) {
-                               /*
-                                * We're not validating, but the client might
-                                * be, so look for the NOQNAME proof.
-                                */
-                               findnoqname(fctx, message, name, rdataset);
-
-                               /*
-                                * If this was not an ANY/RRSIG/SIG query,
-                                * or if it was but we got a CNAME/DNAME,
-                                * then we need to set up rdatasets to
-                                * send back to the caller.
-                                */
-                               if (!dns_rdatatype_ismulti(fctx->type) ||
-                                   CHAINING(rdataset))
-                               {
-                                       ardataset = resp->rdataset;
-                                       asigset = resp->sigrdataset;
-                               }
-                       }
-
-                       if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0) {
-                               options = DNS_DBADD_PREFETCH;
-                       }
-                       if ((fctx->options & DNS_FETCHOPT_NOCACHED) != 0) {
-                               options |= DNS_DBADD_FORCE;
-                       }
+                       /*
+                        * This is one of (potentially) multiple answers to
+                        * an ANY query.  To keep things simple, we just
+                        * start the validator right away rather than
+                        * caching first and having to remember which
+                        * rdatasets needed validation.
+                        */
+                       valcreate(fctx, message, query->addrinfo, name,
+                                 rdataset->type, rdataset, sigrdataset);
+               }
+       } else {
+               if (ANSWER(rdataset)) {
+                       /*
+                        * We're not validating, but the client might
+                        * be, so look for the NOQNAME proof.
+                        */
+                       findnoqname(fctx, message, name, rdataset);
 
-                       result = dns_db_addrdataset(fctx->cache, node, NULL,
-                                                   rctx->now, rdataset,
-                                                   options, ardataset);
-                       if (result != DNS_R_UNCHANGED &&
-                           result != ISC_R_SUCCESS)
+                       /*
+                        * If this was not an ANY query - or if it was,
+                        * but we got a CNAME/DNAME - then we need to
+                        * set up rdatasets to send back to the caller.
+                        */
+                       if (resp != NULL &&
+                           (!dns_rdatatype_ismulti(fctx->type) ||
+                            CHAINING(rdataset)))
                        {
-                               return result;
+                               ardataset = resp->rdataset;
+                               asigset = resp->sigrdataset;
                        }
+               }
 
-                       if (sigrdataset == NULL) {
-                               return ISC_R_SUCCESS;
-                       }
+               if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0) {
+                       options = DNS_DBADD_PREFETCH;
+               }
+               if ((fctx->options & DNS_FETCHOPT_NOCACHED) != 0) {
+                       options |= DNS_DBADD_FORCE;
+               }
 
-                       if (result == DNS_R_UNCHANGED && !need_validation &&
-                           ardataset != NULL &&
-                           !dns_rdataset_equals(rdataset, ardataset))
-                       {
-                               /*
-                                * The cache wasn't updated because
-                                * something was already there. If the data
-                                * was the same as what we were trying to
-                                * add, then sigrdataset might still be
-                                * useful, and we should carry on caching
-                                * it. Otherwise, move on.
-                                */
-                               return ISC_R_SUCCESS;
-                       }
+               result = dns_db_addrdataset(fctx->cache, node, NULL, rctx->now,
+                                           rdataset, options, ardataset);
+               if (result != DNS_R_UNCHANGED && result != ISC_R_SUCCESS) {
+                       return result;
+               }
 
-                       result = dns_db_addrdataset(fctx->cache, node, NULL,
-                                                   rctx->now, sigrdataset,
-                                                   options, asigset);
-                       if (result != DNS_R_UNCHANGED &&
-                           result != ISC_R_SUCCESS)
-                       {
-                               return result;
-                       }
+               if (sigrdataset == NULL) {
+                       return ISC_R_SUCCESS;
                }
 
-               return ISC_R_SUCCESS;
+               if (result == DNS_R_UNCHANGED && !need_validation &&
+                   ardataset != NULL &&
+                   !dns_rdataset_equals(rdataset, ardataset))
+               {
+                       /*
+                        * The cache wasn't updated because something was
+                        * already there. If the data was the same as what
+                        * we were trying to add, then sigrdataset might
+                        * still be useful, and we should carry on caching
+                        * it. Otherwise, move on.
+                        */
+                       return ISC_R_SUCCESS;
+               }
+
+               result = dns_db_addrdataset(fctx->cache, node, NULL, rctx->now,
+                                           sigrdataset, options, asigset);
+               if (result != DNS_R_UNCHANGED && result != ISC_R_SUCCESS) {
+                       return result;
+               }
        }
 
+       return ISC_R_SUCCESS;
+}
+
+static isc_result_t
+rctx_cache_insecure(respctx_t *rctx, dns_message_t *message, dns_name_t *name,
+                   dns_dbnode_t *node, dns_rdataset_t *rdataset) {
+       isc_result_t result;
+       fetchctx_t *fctx = rctx->fctx;
+       dns_fetchresponse_t *resp = ISC_LIST_HEAD(fctx->resps);
+       dns_rdataset_t *added = NULL;
+
        /*
-        * We're not in a secure domain, or this is glue,
-        * so we can cache right away.
-        *
-        * If this wasn't an ANY/RRSIG/SIG query then send
-        * an answer back to the caller.
+        * If this was not an ANY query - or if it was, but we got a
+        * CNAME/DNAME - then we need to set up an rdataset to send
+        * back to the caller.
         */
-       dns_rdataset_t *added = NULL;
-       if (!dns_rdatatype_ismulti(fctx->type)) {
+       if (resp != NULL &&
+           (!dns_rdatatype_ismulti(fctx->type) || CHAINING(rdataset)))
+       {
                if (ANSWER(rdataset)) {
                        added = resp->rdataset;
                } else if (ANSWERSIG(rdataset)) {
@@ -5997,15 +5990,16 @@ rctx_cacherdataset(respctx_t *rctx, dns_message_t *message, dns_name_t *name,
                }
        }
 
+       /*
+        * If the trust level is glue, then we are adding data from a
+        * referral we got while executing the search algorithm.  New
+        * referral data always takes precedence over the existing cache
+        * contents.
+        */
+       unsigned int options = 0;
        if (rdataset->trust == dns_trust_glue &&
            dns_rdataset_matchestype(rdataset, dns_rdatatype_ns))
        {
-               /*
-                * If the trust level is glue, then we are adding data from
-                * a referral we got while executing the search algorithm.
-                * New referral data always takes precedence over the
-                * existing cache contents.
-                */
                options = DNS_DBADD_FORCE;
        } else if ((fctx->options & DNS_FETCHOPT_PREFETCH) != 0) {
                options = DNS_DBADD_PREFETCH;
@@ -6019,7 +6013,7 @@ rctx_cacherdataset(respctx_t *rctx, dns_message_t *message, dns_name_t *name,
        }
 
        /*
-        * Now we can add the rdataset.
+        * Cache the rdataset.
         */
        result = dns_db_addrdataset(fctx->cache, node, NULL, rctx->now,
                                    rdataset, options, added);
@@ -6091,10 +6085,19 @@ rctx_cachename(respctx_t *rctx, dns_message_t *message, dns_name_t *name) {
                 */
                fixttls(res->view, rdataset, sigrdataset);
 
-               /* Try to cache the rdataset */
-               result = rctx_cacherdataset(rctx, message, name, node, rdataset,
-                                           sigrdataset, secure_domain,
-                                           need_validation);
+               /*
+                * If this is a secure domain and we're not caching
+                * glue, start validators as needed. Otherwise, cache
+                * cache now.
+                */
+               if (secure_domain && rdataset->trust != dns_trust_glue) {
+                       result = rctx_cache_secure(rctx, message, name, node,
+                                                  rdataset, sigrdataset,
+                                                  need_validation);
+               } else {
+                       result = rctx_cache_insecure(rctx, message, name, node,
+                                                    rdataset);
+               }
                if (result != ISC_R_SUCCESS) {
                        goto cleanup;
                }