]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
- Fix to enable that SERVFAIL is cached, for a short period, for more
authorW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Mon, 27 May 2024 11:53:16 +0000 (13:53 +0200)
committerW.C.A. Wijngaards <wouter@nlnetlabs.nl>
Mon, 27 May 2024 11:53:16 +0000 (13:53 +0200)
  cases. In the cases where limits are exceeded.

doc/Changelog
iterator/iterator.c

index 4b430c4f9cb18ff679f3ab31d7afc916be8218a3..5b7cba5bc4f1c390872cd7e7f86af927d969f123 100644 (file)
@@ -1,3 +1,7 @@
+27 May 2024: Wouter
+       - Fix to enable that SERVFAIL is cached, for a short period, for more
+         cases. In the cases where limits are exceeded.
+
 24 May 2024: Wouter
        - Fix #1064: Unbound 1.20 Cachedb broken?
 
index 7863e721498fc4524014521c6f282cea58a34b78..5a99ab0d74304d47318a3fb2eda8de70d07936d7 100644 (file)
@@ -1378,7 +1378,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
                        "restarts (eg. indirections)");
                if(iq->qchase.qname)
                        errinf_dname(qstate, "stop at", iq->qchase.qname);
-               return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+               return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
        }
 
        /* We enforce a maximum recursion/dependency depth -- in general, 
@@ -1654,7 +1654,7 @@ processInitRequest(struct module_qstate* qstate, struct iter_qstate* iq,
                                if(!iq->dp) {
                                        log_err("internal error: no hints dp");
                                        errinf(qstate, "no hints for this class");
-                                       return error_response(qstate, id, 
+                                       return error_response_cache(qstate, id,
                                                LDNS_RCODE_SERVFAIL);
                                }
                                iq->dp = delegpt_copy(iq->dp, qstate->region);
@@ -1974,7 +1974,8 @@ generate_target_query(struct module_qstate* qstate, struct iter_qstate* iq,
  *     if it is negative, there is no maximum number of targets.
  * @param num: returns the number of queries generated and processed, 
  *     which may be zero if there were no missing targets.
- * @return false on error.
+ * @return 0 on success, nonzero on error. 1 means temporary failure and
+ *     2 means the failure can be cached.
  */
 static int
 query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
@@ -1997,13 +1998,13 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
        else    toget = maxtargets;
        if(toget == 0) {
                *num = 0;
-               return 1;
+               return 0;
        }
 
        /* now that we are sure that a target query is going to be made,
         * check the limits. */
        if(iq->depth == ie->max_dependency_depth)
-               return 0;
+               return 1;
        if(iq->depth > 0 && iq->target_count &&
                iq->target_count[TARGET_COUNT_QUERIES] > MAX_TARGET_COUNT) {
                char s[LDNS_MAX_DOMAINLEN+1];
@@ -2011,7 +2012,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
                verbose(VERB_QUERY, "request %s has exceeded the maximum "
                        "number of glue fetches %d", s,
                        iq->target_count[TARGET_COUNT_QUERIES]);
-               return 0;
+               return 2;
        }
        if(iq->dp_target_count > MAX_DP_TARGET_COUNT) {
                char s[LDNS_MAX_DOMAINLEN+1];
@@ -2019,7 +2020,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
                verbose(VERB_QUERY, "request %s has exceeded the maximum "
                        "number of glue fetches %d to a single delegation point",
                        s, iq->dp_target_count);
-               return 0;
+               return 2;
        }
 
        /* select 'toget' items from the total of 'missing' items */
@@ -2048,7 +2049,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
                                *num = query_count;
                                if(query_count > 0)
                                        qstate->ext_state[id] = module_wait_subquery;
-                               return 0;
+                               return 1;
                        }
                        query_count++;
                        /* If the mesh query list is full, exit the loop here.
@@ -2078,7 +2079,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
                                *num = query_count;
                                if(query_count > 0)
                                        qstate->ext_state[id] = module_wait_subquery;
-                               return 0;
+                               return 1;
                        }
                        query_count++;
                        /* If the mesh query list is full, exit the loop. */
@@ -2102,7 +2103,7 @@ query_for_targets(struct module_qstate* qstate, struct iter_qstate* iq,
        if(query_count > 0)
                qstate->ext_state[id] = module_wait_subquery;
 
-       return 1;
+       return 0;
 }
 
 /**
@@ -2193,12 +2194,14 @@ processLastResort(struct module_qstate* qstate, struct iter_qstate* iq,
        }
        /* query for an extra name added by the parent-NS record */
        if(delegpt_count_missing_targets(iq->dp, NULL) > 0) {
-               int qs = 0;
+               int qs = 0, ret;
                verbose(VERB_ALGO, "try parent-side target name");
-               if(!query_for_targets(qstate, iq, ie, id, 1, &qs)) {
+               if((ret=query_for_targets(qstate, iq, ie, id, 1, &qs))!=0) {
                        errinf(qstate, "could not fetch nameserver");
                        errinf_dname(qstate, "at zone", iq->dp->name);
-                       return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+                       if(ret == 1)
+                               return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+                       return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
                }
                iq->num_target_queries += qs;
                target_count_increase(iq, qs);
@@ -2427,13 +2430,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
                verbose(VERB_QUERY, "request has exceeded the maximum "
                        "number of referrrals with %d", iq->referral_count);
                errinf(qstate, "exceeded the maximum of referrals");
-               return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+               return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
        }
        if(iq->sent_count > ie->max_sent_count) {
                verbose(VERB_QUERY, "request has exceeded the maximum "
                        "number of sends with %d", iq->sent_count);
                errinf(qstate, "exceeded the maximum number of sends");
-               return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+               return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
        }
 
        /* Check if we reached MAX_TARGET_NX limit without a fallback activation. */
@@ -2463,7 +2466,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
                                "already present for the delegation point, no "
                                "fallback possible");
                        errinf(qstate, "exceeded the maximum nameserver nxdomains");
-                       return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+                       return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
                }
                verbose(VERB_ALGO, "initiating parent-side fallback for "
                        "nxdomain nameserver lookups");
@@ -2506,7 +2509,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
                                "lookups (%d) with %d", MAX_TARGET_NX_FALLBACK,
                                iq->target_count[TARGET_COUNT_NX]);
                        errinf(qstate, "exceeded the maximum nameserver nxdomains");
-                       return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+                       return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
                }
 
                if(!iq->dp->has_parent_side_NS) {
@@ -2720,7 +2723,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
                verbose(VERB_ALGO, "auth zone lookup failed, no fallback,"
                        " servfail");
                errinf(qstate, "auth zone lookup failed, fallback is off");
-               return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+               return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
        }
        if(iq->dp->auth_dp) {
                /* we wanted to fallback, but had no delegpt, only the
@@ -2749,11 +2752,13 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
 
        /* if in 0x20 fallback get as many targets as possible */
        if(iq->caps_fallback) {
-               int extra = 0;
+               int extra = 0, ret;
                size_t naddr, nres, navail;
-               if(!query_for_targets(qstate, iq, ie, id, -1, &extra)) {
+               if((ret=query_for_targets(qstate, iq, ie, id, -1, &extra))!=0) {
                        errinf(qstate, "could not fetch nameservers for 0x20 fallback");
-                       return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+                       if(ret == 1)
+                               return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+                       return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
                }
                iq->num_target_queries += extra;
                target_count_increase(iq, extra);
@@ -2896,14 +2901,17 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
                         * to distinguish between generating (a) new target 
                         * query, or failing. */
                        if(delegpt_count_missing_targets(iq->dp, NULL) > 0) {
-                               int qs = 0;
+                               int qs = 0, ret;
                                verbose(VERB_ALGO, "querying for next "
                                        "missing target");
-                               if(!query_for_targets(qstate, iq, ie, id, 
-                                       1, &qs)) {
+                               if((ret=query_for_targets(qstate, iq, ie, id, 
+                                       1, &qs))!=0) {
                                        errinf(qstate, "could not fetch nameserver");
                                        errinf_dname(qstate, "at zone", iq->dp->name);
-                                       return error_response(qstate, id,
+                                       if(ret == 1)
+                                               return error_response(qstate, id,
+                                                       LDNS_RCODE_SERVFAIL);
+                                       return error_response_cache(qstate, id,
                                                LDNS_RCODE_SERVFAIL);
                                }
                                if(qs == 0 && 
@@ -3049,7 +3057,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
                        qstate->was_ratelimited = 1;
                        errinf_dname(qstate, "exceeded ratelimit for zone",
                                iq->dp->name);
-                       return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+                       return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
                }
                log_addr(VERB_QUERY, "error sending query to auth server",
                        &real_addr, real_addrlen);
@@ -3271,7 +3279,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
                                                iter_scrub_nxdomain(iq->response);
                                                return final_state(iq);
                                        }
-                                       return error_response(qstate, id,
+                                       return error_response_cache(qstate, id,
                                                LDNS_RCODE_SERVFAIL);
                                }
                                /* Best effort qname-minimisation. 
@@ -3606,7 +3614,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
                                " fallback possible, servfail");
                        errinf_dname(qstate, "response is bad, no fallback, "
                                "for auth zone", iq->dp->name);
-                       return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
+                       return error_response_cache(qstate, id, LDNS_RCODE_SERVFAIL);
                }
                verbose(VERB_ALGO, "auth zone response was bad, "
                        "fallback enabled");
@@ -4014,7 +4022,7 @@ processCollectClass(struct module_qstate* qstate, int id)
                if(iq->num_current_queries == 0) {
                        verbose(VERB_ALGO, "No root hints or fwds, giving up "
                                "on qclass ANY");
-                       return error_response(qstate, id, LDNS_RCODE_REFUSED);
+                       return error_response_cache(qstate, id, LDNS_RCODE_REFUSED);
                }
                /* return false, wait for queries to return */
        }
@@ -4381,7 +4389,7 @@ process_response(struct module_qstate* qstate, struct iter_qstate* iq,
                                        "getting different replies, failed");
                                outbound_list_remove(&iq->outlist, outbound);
                                errinf(qstate, "0x20 failed, then got different replies in fallback");
-                               (void)error_response(qstate, id, 
+                               (void)error_response_cache(qstate, id,
                                        LDNS_RCODE_SERVFAIL);
                                return;
                        }