backport r3782, fixing qname-minimisation with various broken DNS servers,
authorsthen <sthen@openbsd.org>
Wed, 22 Jun 2016 20:11:09 +0000 (20:11 +0000)
committersthen <sthen@openbsd.org>
Wed, 22 Jun 2016 20:11:09 +0000 (20:11 +0000)
often found at CDNs.

- Use QTYPE=A for QNAME minimisation.
- Keep track of number of time-outs when performing QNAME minimisation.
  Stop minimising when number of time-outs for a QNAME/QTYPE pair is
  more than three.

usr.sbin/unbound/doc/Changelog
usr.sbin/unbound/iterator/iterator.c
usr.sbin/unbound/iterator/iterator.h

index bbc983e..4b00940 100644 (file)
@@ -1,3 +1,9 @@
+13 June 2016: Ralph
+       - Use QTYPE=A for QNAME minimisation.
+       - Keep track of number of time-outs when performing QNAME minimisation.
+         Stop minimising when number of time-outs for a QNAME/QTYPE pair is
+         more than three.
+
 13 June 2016: Wouter
        - Fix #778: unbound 1.5.9: -h segfault (null deref).
 
index 139cae4..749fba6 100644 (file)
@@ -148,6 +148,7 @@ iter_new(struct module_qstate* qstate, int id)
        iq->qchase = qstate->qinfo;
        outbound_list_init(&iq->outlist);
        iq->minimise_count = 0;
+       iq->minimise_timeout_count = 0;
        if (qstate->env->cfg->qname_minimisation)
                iq->minimisation_state = INIT_MINIMISE_STATE;
        else
@@ -2008,7 +2009,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
                                iq->dp->name))) {
                        iq->qinfo_out.qname = iq->dp->name;
                        iq->qinfo_out.qname_len = iq->dp->namelen;
-                       iq->qinfo_out.qtype = LDNS_RR_TYPE_NS;
+                       iq->qinfo_out.qtype = LDNS_RR_TYPE_A;
                        iq->qinfo_out.qclass = iq->qchase.qclass;
                        iq->minimise_count = 0;
                }
@@ -2023,6 +2024,7 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
                iq->qinfo_out.qname = iq->qchase.qname;
                iq->qinfo_out.qname_len = iq->qchase.qname_len;
                iq->minimise_count++;
+               iq->minimise_timeout_count = 0;
 
                /* Limit number of iterations for QNAMEs with more
                 * than MAX_MINIMISE_COUNT labels. Send first MINIMISE_ONE_LAB
@@ -2059,8 +2061,9 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
                                &iq->qinfo_out.qname_len, 
                                labdiff-1);
                }
-               if(labdiff < 1 || 
-                       (labdiff < 2 && iq->qchase.qtype == LDNS_RR_TYPE_DS))
+               if(labdiff < 1 || (labdiff < 2 
+                       && (iq->qchase.qtype == LDNS_RR_TYPE_DS
+                       || iq->qchase.qtype == LDNS_RR_TYPE_A)))
                        /* Stop minimising this query, resolve "as usual" */
                        iq->minimisation_state = DONOT_MINIMISE_STATE;
                else {
@@ -2077,10 +2080,17 @@ processQueryTargets(struct module_qstate* qstate, struct iter_qstate* iq,
                                return 1;
                }
        }
-       if(iq->minimisation_state == SKIP_MINIMISE_STATE)
-               /* Do not increment qname, continue incrementing next 
-                * iteration */
-               iq->minimisation_state = MINIMISE_STATE;
+       if(iq->minimisation_state == SKIP_MINIMISE_STATE) {
+               iq->minimise_timeout_count++;
+               if(iq->minimise_timeout_count < MAX_MINIMISE_TIMEOUT_COUNT)
+                       /* Do not increment qname, continue incrementing next 
+                        * iteration */
+                       iq->minimisation_state = MINIMISE_STATE;
+               else
+                       /* Too many time-outs detected for this QNAME and QTYPE.
+                        * We give up, disable QNAME minimisation. */
+                       iq->minimisation_state = DONOT_MINIMISE_STATE;
+       }
        if(iq->minimisation_state == DONOT_MINIMISE_STATE)
                iq->qinfo_out = iq->qchase;
 
@@ -2158,7 +2168,7 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
        iq->num_current_queries--;
        if(iq->response == NULL) {
                /* Don't increment qname when QNAME minimisation is enabled */
-               if (qstate->env->cfg->qname_minimisation)
+               if(qstate->env->cfg->qname_minimisation)
                        iq->minimisation_state = SKIP_MINIMISE_STATE;
                iq->chase_to_rd = 0;
                iq->dnssec_lame_query = 0;
index 7c32a74..5585f57 100644 (file)
@@ -69,6 +69,9 @@ struct rbtree_t;
  * QNAMEs with a lot of labels.
 */
 #define MAX_MINIMISE_COUNT     10
+/* max number of time-outs for minimised query. Prevents resolving failures
+ * when the QNAME minimisation QTYPE is blocked. */
+#define MAX_MINIMISE_TIMEOUT_COUNT 3
 /**
  * number of labels from QNAME that are always send individually when using
  * QNAME minimisation, even when the number of labels of the QNAME is bigger
@@ -377,6 +380,11 @@ struct iter_qstate {
         * outgoing queries when QNAME minimisation is enabled.
         */
        int minimise_count;
+
+       /**
+        * Count number of time-outs. Used to prevent resolving failures when
+        * the QNAME minimisation QTYPE is blocked. */
+       int minimise_timeout_count;
 };
 
 /**