]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
fixup AUTH prepend list.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 4 Sep 2007 14:06:43 +0000 (14:06 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 4 Sep 2007 14:06:43 +0000 (14:06 +0000)
git-svn-id: file:///svn/unbound/trunk@587 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
iterator/iterator.c
iterator/iterator.h

index aea42446e8a589767474ccc6c1c45a990852c04d..3594d21e7bcb2a3ff4eb0e7fc931f296cd6b2932 100644 (file)
@@ -8,6 +8,8 @@
        - DNAMEs no longer match their apex when synthesized from the cache.
        - find correct signer name for DNAME responses.
        - wildcarded DNAME test and fixup code to detect.
+       - prepend NSEC and NSEC3 rrsets in the iterator while chasing CNAMEs.
+         So that wildcarded CNAMEs get their NSEC with them to the answer.
 
 3 September 2007: Wouter
        - Fixed error in iterator that would cause assertion failure in 
index f2a04f20e74d2a53878bc72216316a1a7319c9d4..256e70393276b968a39733aea2678d83de90cfc3 100644 (file)
@@ -103,8 +103,10 @@ iter_new(struct module_qstate* qstate, int id)
        memset(iq, 0, sizeof(*iq));
        iq->state = INIT_REQUEST_STATE;
        iq->final_state = FINISHED_STATE;
-       iq->prepend_list = NULL;
-       iq->prepend_last = NULL;
+       iq->an_prepend_list = NULL;
+       iq->an_prepend_last = NULL;
+       iq->ns_prepend_list = NULL;
+       iq->ns_prepend_last = NULL;
        iq->dp = NULL;
        iq->depth = 0;
        iq->num_target_queries = 0;
@@ -221,49 +223,88 @@ error_response(struct module_qstate* qstate, int id, int rcode)
        return 0;
 }
 
-/** prepend the prepend list in the answer section of dns_msg */
+/** prepend the prepend list in the answer and authority section of dns_msg */
 static int
 iter_prepend(struct iter_qstate* iq, struct dns_msg* msg, 
        struct region* region)
 {
        struct iter_prep_list* p;
        struct ub_packed_rrset_key** sets;
-       size_t num = 0;
-       for(p = iq->prepend_list; p; p = p->next)
-               num++;
-       if(num == 0)
+       size_t num_an = 0, num_ns = 0;;
+       for(p = iq->an_prepend_list; p; p = p->next)
+               num_an++;
+       for(p = iq->ns_prepend_list; p; p = p->next)
+               num_ns++;
+       if(num_an + num_ns == 0)
                return 1;
-       verbose(VERB_ALGO, "prepending %d rrsets", (int)num);
-       sets = region_alloc(region, (num+msg->rep->rrset_count) *
+       verbose(VERB_ALGO, "prepending %d rrsets", (int)num_an + (int)num_ns);
+       sets = region_alloc(region, (num_an+num_ns+msg->rep->rrset_count) *
                sizeof(struct ub_packed_rrset_key*));
        if(!sets) 
                return 0;
-       memcpy(sets+num, msg->rep->rrsets, msg->rep->rrset_count *
+       /* ANSWER section */
+       num_an = 0;
+       for(p = iq->an_prepend_list; p; p = p->next) {
+               sets[num_an++] = p->rrset;
+       }
+       memcpy(sets+num_an, msg->rep->rrsets, msg->rep->an_numrrsets *
                sizeof(struct ub_packed_rrset_key*));
-       num = 0;
-       for(p = iq->prepend_list; p; p = p->next) {
-               sets[num++] = p->rrset;
+       /* AUTH section */
+       num_ns = 0;
+       for(p = iq->ns_prepend_list; p; p = p->next) {
+               sets[msg->rep->an_numrrsets + num_an + num_ns++] = p->rrset;
        }
+       memcpy(sets + num_an + msg->rep->an_numrrsets + num_ns, 
+               msg->rep->rrsets + msg->rep->an_numrrsets, 
+               (msg->rep->ns_numrrsets + msg->rep->ar_numrrsets) *
+               sizeof(struct ub_packed_rrset_key*));
+
        /* if the rcode was NXDOMAIN, and we prepended DNAME/CNAMEs, then
         * it should now be NOERROR. */
        if(FLAGS_GET_RCODE(msg->rep->flags) == LDNS_RCODE_NXDOMAIN) {
                FLAGS_SET_RCODE(msg->rep->flags, LDNS_RCODE_NOERROR);
        }
-       msg->rep->rrset_count += num;
-       msg->rep->an_numrrsets += num;
+       msg->rep->rrset_count += num_an + num_ns;
+       msg->rep->an_numrrsets += num_an;
+       msg->rep->ns_numrrsets += num_ns;
        msg->rep->rrsets = sets;
        return 1;
 }
 
 /**
- * Add rrset to prepend list
+ * Add rrset to ANSWER prepend list
+ * @param qstate: query state.
+ * @param iq: iterator query state.
+ * @param rrset: rrset to add.
+ * @return false on failure (malloc).
+ */
+static int
+iter_add_prepend_answer(struct module_qstate* qstate, struct iter_qstate* iq,
+       struct ub_packed_rrset_key* rrset)
+{
+       struct iter_prep_list* p = (struct iter_prep_list*)region_alloc(
+               qstate->region, sizeof(struct iter_prep_list));
+       if(!p)
+               return 0;
+       p->rrset = rrset;
+       p->next = NULL;
+       /* add at end */
+       if(iq->an_prepend_last)
+               iq->an_prepend_last->next = p;
+       else    iq->an_prepend_list = p;
+       iq->an_prepend_last = p;
+       return 1;
+}
+
+/**
+ * Add rrset to AUTHORITY prepend list
  * @param qstate: query state.
  * @param iq: iterator query state.
  * @param rrset: rrset to add.
  * @return false on failure (malloc).
  */
 static int
-iter_add_prepend(struct module_qstate* qstate, struct iter_qstate* iq,
+iter_add_prepend_auth(struct module_qstate* qstate, struct iter_qstate* iq,
        struct ub_packed_rrset_key* rrset)
 {
        struct iter_prep_list* p = (struct iter_prep_list*)region_alloc(
@@ -273,10 +314,10 @@ iter_add_prepend(struct module_qstate* qstate, struct iter_qstate* iq,
        p->rrset = rrset;
        p->next = NULL;
        /* add at end */
-       if(iq->prepend_last)
-               iq->prepend_last->next = p;
-       else    iq->prepend_list = p;
-       iq->prepend_last = p;
+       if(iq->ns_prepend_last)
+               iq->ns_prepend_last->next = p;
+       else    iq->ns_prepend_list = p;
+       iq->ns_prepend_last = p;
        return 1;
 }
 
@@ -313,7 +354,7 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
                 * directly.  */
                if(ntohs(r->rk.type) == LDNS_RR_TYPE_DNAME &&
                        dname_strict_subdomain_c(*mname, r->rk.dname)) {
-                       if(!iter_add_prepend(qstate, iq, r))
+                       if(!iter_add_prepend_answer(qstate, iq, r))
                                return 0;
                        continue;
                }
@@ -321,13 +362,24 @@ handle_cname_response(struct module_qstate* qstate, struct iter_qstate* iq,
                if(ntohs(r->rk.type) == LDNS_RR_TYPE_CNAME &&
                        query_dname_compare(*mname, r->rk.dname) == 0) {
                        /* Add this relevant CNAME rrset to the prepend list.*/
-                       if(!iter_add_prepend(qstate, iq, r))
+                       if(!iter_add_prepend_answer(qstate, iq, r))
                                return 0;
                        get_cname_target(r, mname, mname_len);
                }
 
                /* Other rrsets in the section are ignored. */
        }
+       /* add authority rrsets to authority prepend, for wildcarded CNAMEs */
+       for(i=msg->rep->an_numrrsets; i<msg->rep->an_numrrsets +
+               msg->rep->ns_numrrsets; i++) {
+               struct ub_packed_rrset_key* r = msg->rep->rrsets[i];
+               /* only add NSEC/NSEC3, as they may be needed for validation */
+               if(ntohs(r->rk.type) == LDNS_RR_TYPE_NSEC ||
+                       ntohs(r->rk.type) == LDNS_RR_TYPE_NSEC3) {
+                       if(!iter_add_prepend_auth(qstate, iq, r))
+                               return 0;
+               }
+       }
        return 1;
 }
 
@@ -1366,7 +1418,7 @@ processFinished(struct module_qstate* qstate, struct iter_qstate* iq,
        /* if (mPrivateTTL > 0){IterUtils.setPrivateTTL(resp, mPrivateTTL); } */
 
        /* prepend any items we have accumulated */
-       if(iq->prepend_list) {
+       if(iq->an_prepend_list || iq->ns_prepend_list) {
                if(!iter_prepend(iq, iq->response, qstate->region)) {
                        log_err("prepend rrsets: out of memory");
                        return error_response(qstate, id, LDNS_RCODE_SERVFAIL);
index fa7146950b0aaaa5aa6e3526a11530c0cbed99b5..ef95d7e367b4d8ea5c85f3b4e817d544efe0f7f6 100644 (file)
@@ -182,9 +182,17 @@ struct iter_qstate {
         * This is a list of RRsets that must be prepended to the 
         * ANSWER section of a response before being sent upstream.
         */
-       struct iter_prep_list* prepend_list;
+       struct iter_prep_list* an_prepend_list;
        /** Last element of the prepend list */
-       struct iter_prep_list* prepend_last;
+       struct iter_prep_list* an_prepend_last;
+
+       /**
+        * This is the list of RRsets that must be prepended to the
+        * AUTHORITY section of the response before being sent upstream.
+        */
+       struct iter_prep_list* ns_prepend_list;
+       /** Last element of the authority prepend list */
+       struct iter_prep_list* ns_prepend_last;
 
        /** query name used for chasing the results. Initially the same as
         * the state qinfo, but after CNAMEs this will be different.