]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
Fix lookup of domains with parent-child zonecut data differences.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 8 Dec 2009 13:37:59 +0000 (13:37 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 8 Dec 2009 13:37:59 +0000 (13:37 +0000)
git-svn-id: file:///svn/unbound/trunk@1929 be551aaa-1e26-0410-a405-d3ace91eadb9

15 files changed:
daemon/remote.c
doc/Changelog
iterator/iter_delegpt.c
iterator/iter_delegpt.h
iterator/iter_fwd.c
iterator/iter_hints.c
iterator/iter_utils.c
iterator/iter_utils.h
iterator/iterator.c
services/cache/dns.c
testdata/iter_pcdiff.rpl [new file with mode: 0644]
util/data/msgreply.c
util/data/msgreply.h
util/data/packed_rrset.c
util/data/packed_rrset.h

index 3c0cb2e677021f87bae1f8598a320bf2072caaf4..cd0c4a429c9d70e125fb73d911b44399e9ece74f 100644 (file)
@@ -1280,7 +1280,7 @@ parse_delegpt(SSL* ssl, struct regional* region, char* args, uint8_t* root)
                        return NULL;
                }
                /* add address */
-               if(!delegpt_add_addr(dp, region, &addr, addrlen, 0, 1)) {
+               if(!delegpt_add_addr(dp, region, &addr, addrlen, 0, 0, 1)) {
                        (void)ssl_printf(ssl, "error out of memory\n");
                        return NULL;
                }
index b69f9f08c9c7ff669e12ba31b7f4ae6dc492a23a..14cb1c981d962f205161d37fe5eab7b19f1bfcb5 100644 (file)
@@ -1,3 +1,8 @@
+8 December 2009: Wouter
+       - Fix for lookup of parent-child disagreement domains, where the
+         parent-side glue works but it does not provide proper NS, A or AAAA
+         for itself, fixing domains such as motorcaravanners.eu.
+
 7 December 2009: Wouter
        - Bug#287: Fix segfault when unbound-control remove nonexistent local
          data.  Added check to tests.
index c5bc66385cd169038b1ca5cd598fdcf87eedb402..d9a2fca97ba210eb668006544286dabcdd1144b2 100644 (file)
@@ -78,7 +78,7 @@ struct delegpt* delegpt_copy(struct delegpt* dp, struct regional* region)
        }
        for(a = dp->target_list; a; a = a->next_target) {
                if(!delegpt_add_addr(copy, region, &a->addr, a->addrlen, 
-                       a->bogus, 0))
+                       a->bogus, a->lame, 0))
                        return NULL;
        }
        return copy;
@@ -147,7 +147,7 @@ delegpt_find_addr(struct delegpt* dp, struct sockaddr_storage* addr,
 int 
 delegpt_add_target(struct delegpt* dp, struct regional* region, 
        uint8_t* name, size_t namelen, struct sockaddr_storage* addr, 
-       socklen_t addrlen, int bogus, int nodup)
+       socklen_t addrlen, int bogus, int lame, int nodup)
 {
        struct delegpt_ns* ns = delegpt_find_ns(dp, name, namelen);
        if(!ns) {
@@ -159,12 +159,13 @@ delegpt_add_target(struct delegpt* dp, struct regional* region,
        else    ns->got4 = 1;
        if(ns->got4 && ns->got6)
                ns->resolved = 1;
-       return delegpt_add_addr(dp, region, addr, addrlen, bogus, nodup);
+       return delegpt_add_addr(dp, region, addr, addrlen, bogus, lame, nodup);
 }
 
 int 
 delegpt_add_addr(struct delegpt* dp, struct regional* region, 
-       struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int nodup)
+       struct sockaddr_storage* addr, socklen_t addrlen, int bogus, 
+       int lame, int nodup)
 {
        struct delegpt_addr* a;
        if(nodup) {
@@ -188,6 +189,7 @@ delegpt_add_addr(struct delegpt* dp, struct regional* region,
        a->addrlen = addrlen;
        a->attempts = 0;
        a->bogus = bogus;
+       a->lame = lame;
        return 1;
 }
 
@@ -332,10 +334,10 @@ delegpt_from_message(struct dns_msg* msg, struct regional* region)
                        continue;
 
                if(ntohs(s->rk.type) == LDNS_RR_TYPE_A) {
-                       if(!delegpt_add_rrset_A(dp, region, s, 0))
+                       if(!delegpt_add_rrset_A(dp, region, s, 0, 0))
                                return NULL;
                } else if(ntohs(s->rk.type) == LDNS_RR_TYPE_AAAA) {
-                       if(!delegpt_add_rrset_AAAA(dp, region, s, 0))
+                       if(!delegpt_add_rrset_AAAA(dp, region, s, 0, 0))
                                return NULL;
                }
        }
@@ -365,7 +367,7 @@ delegpt_rrset_add_ns(struct delegpt* dp, struct regional* region,
 
 int 
 delegpt_add_rrset_A(struct delegpt* dp, struct regional* region,
-       struct ub_packed_rrset_key* ak, int nodup)
+       struct ub_packed_rrset_key* ak, int lame, int nodup)
 {
         struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;
         size_t i;
@@ -380,7 +382,7 @@ delegpt_add_rrset_A(struct delegpt* dp, struct regional* region,
                 memmove(&sa.sin_addr, d->rr_data[i]+2, INET_SIZE);
                 if(!delegpt_add_target(dp, region, ak->rk.dname,
                         ak->rk.dname_len, (struct sockaddr_storage*)&sa,
-                        len, (d->security==sec_status_bogus), nodup))
+                        len, (d->security==sec_status_bogus), lame, nodup))
                         return 0;
         }
         return 1;
@@ -388,7 +390,7 @@ delegpt_add_rrset_A(struct delegpt* dp, struct regional* region,
 
 int 
 delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region,
-       struct ub_packed_rrset_key* ak, int nodup)
+       struct ub_packed_rrset_key* ak, int lame, int nodup)
 {
         struct packed_rrset_data* d=(struct packed_rrset_data*)ak->entry.data;
         size_t i;
@@ -403,7 +405,7 @@ delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* region,
                 memmove(&sa.sin6_addr, d->rr_data[i]+2, INET6_SIZE);
                 if(!delegpt_add_target(dp, region, ak->rk.dname,
                         ak->rk.dname_len, (struct sockaddr_storage*)&sa,
-                        len, (d->security==sec_status_bogus), nodup))
+                        len, (d->security==sec_status_bogus), lame, nodup))
                         return 0;
         }
         return 1;
@@ -418,9 +420,9 @@ delegpt_add_rrset(struct delegpt* dp, struct regional* region,
        if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_NS)
                return delegpt_rrset_add_ns(dp, region, rrset);
        else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_A)
-               return delegpt_add_rrset_A(dp, region, rrset, 0);
+               return delegpt_add_rrset_A(dp, region, rrset, 0, 0);
        else if(ntohs(rrset->rk.type) == LDNS_RR_TYPE_AAAA)
-               return delegpt_add_rrset_AAAA(dp, region, rrset, 0);
+               return delegpt_add_rrset_AAAA(dp, region, rrset, 0, 0);
        log_warn("Unknown rrset type added to delegpt");
        return 1;
 }
index 4445c1b0a930ac2fdceb1aed66321eb13237d5f4..b1d8264f4f1a308cdce6e4b4c58ce2c63dc8b8b6 100644 (file)
@@ -121,6 +121,8 @@ struct delegpt_addr {
        /** if true, the A or AAAA RR was bogus, so this address is bad.
         * Also check the dp->bogus to see if everything is bogus. */
        int bogus;
+       /** if true, this address is dispreferred: it is a lame IP address */
+       int lame;
 };
 
 /**
@@ -178,35 +180,38 @@ int delegpt_rrset_add_ns(struct delegpt* dp, struct regional* regional,
  * @param addr: the address.
  * @param addrlen: the length of addr.
  * @param bogus: security status for the address, pass true if bogus.
+ * @param lame: address is lame.
  * @param nodup: if true, no address duplicates are made by this add. 
  *     name duplicates are always filtered.
  * @return false on error.
  */
 int delegpt_add_target(struct delegpt* dp, struct regional* regional, 
        uint8_t* name, size_t namelen, struct sockaddr_storage* addr, 
-       socklen_t addrlen, int bogus, int nodup);
+       socklen_t addrlen, int bogus, int lame, int nodup);
 
 /**
  * Add A RRset to delegpt.
  * @param dp: delegation point.
  * @param regional: where to allocate the info.
  * @param rrset: RRset A to add.
+ * @param lame: rrset is lame, disprefer it.
  * @param nodup: if true, no duplicates are made by this add. takes time.
  * @return 0 on alloc error.
  */
 int delegpt_add_rrset_A(struct delegpt* dp, struct regional* regional, 
-       struct ub_packed_rrset_key* rrset, int nodup);
+       struct ub_packed_rrset_key* rrset, int lame, int nodup);
 
 /**
  * Add AAAA RRset to delegpt.
  * @param dp: delegation point.
  * @param regional: where to allocate the info.
  * @param rrset: RRset AAAA to add.
+ * @param lame: rrset is lame, disprefer it.
  * @param nodup: if true, no duplicates are made by this add. takes time.
  * @return 0 on alloc error.
  */
 int delegpt_add_rrset_AAAA(struct delegpt* dp, struct regional* regional, 
-       struct ub_packed_rrset_key* rrset, int nodup);
+       struct ub_packed_rrset_key* rrset, int lame, int nodup);
 
 /**
  * Add any RRset to delegpt.
@@ -226,11 +231,13 @@ int delegpt_add_rrset(struct delegpt* dp, struct regional* regional,
  * @param addr: the address.
  * @param addrlen: the length of addr.
  * @param bogus: if address is bogus.
+ * @param lame: if address is lame.
  * @param nodup: if true, no duplicates are made by this add. takes time.
  * @return false on error.
  */
 int delegpt_add_addr(struct delegpt* dp, struct regional* regional, 
-       struct sockaddr_storage* addr, socklen_t addrlen, int bogus, int nodup);
+       struct sockaddr_storage* addr, socklen_t addrlen, int bogus, 
+       int lame, int nodup);
 
 /** 
  * Find NS record in name list of delegation point.
index 488a7d3a194b695302bc0e505f3d58e7d7039084..a22662a8eba03ab9878ccf339a90c53b72582a4f 100644 (file)
@@ -212,7 +212,8 @@ read_fwds_addr(struct iter_forwards* fwd, struct config_stub* s,
                                s->name, p->str);
                        return 0;
                }
-               if(!delegpt_add_addr(dp, fwd->region, &addr, addrlen, 0, 1)) {
+               if(!delegpt_add_addr(dp, fwd->region, &addr, addrlen, 
+                       0, 0, 1)) {
                        log_err("out of memory");
                        return 0;
                }
index b45e57f03765dd1107f545102f57178439736ebf..15d7593333a0585b4ba06dc3646bf38c96a076ee 100644 (file)
@@ -86,7 +86,7 @@ ah(struct delegpt* dp, struct regional* r, const char* sv, const char* ip)
        if(!delegpt_add_ns(dp, r, ldns_rdf_data(rdf)) ||
           !extstrtoaddr(ip, &addr, &addrlen) ||
           !delegpt_add_target(dp, r, ldns_rdf_data(rdf), ldns_rdf_size(rdf),
-               &addr, addrlen, 0, 1)) {
+               &addr, addrlen, 0, 0, 1)) {
                ldns_rdf_deep_free(rdf);
                return 0;
        }
@@ -225,7 +225,8 @@ read_stubs_addr(struct iter_hints* hints, struct config_stub* s,
                                s->name, p->str);
                        return 0;
                }
-               if(!delegpt_add_addr(dp, hints->region, &addr, addrlen, 0, 1)) {
+               if(!delegpt_add_addr(dp, hints->region, &addr, addrlen, 
+                       0, 0, 1)) {
                        log_err("out of memory");
                        return 0;
                }
@@ -318,7 +319,7 @@ read_root_hints(struct iter_hints* hints, char* fname)
                                        ldns_rdf_data(ldns_rr_owner(rr)),
                                        ldns_rdf_size(ldns_rr_owner(rr)),
                                        (struct sockaddr_storage*)&sa, len, 
-                                       0, 1)) {
+                                       0, 0, 1)) {
                                log_err("out of memory reading root hints");
                                goto stop_read;
                        }
@@ -334,7 +335,7 @@ read_root_hints(struct iter_hints* hints, char* fname)
                                        ldns_rdf_data(ldns_rr_owner(rr)),
                                        ldns_rdf_size(ldns_rr_owner(rr)),
                                        (struct sockaddr_storage*)&sa, len,
-                                       0, 1)) {
+                                       0, 0, 1)) {
                                log_err("out of memory reading root hints");
                                goto stop_read;
                        }
index 718fbf62b727a1c8b51b28f80c9ffca7918a05e4..d364ae2a896e0a68d84efb9acef96590e898b687 100644 (file)
@@ -160,6 +160,7 @@ iter_apply_cfg(struct iter_env* iter_env, struct config_file* cfg)
  *             For non-blacklisted servers: huge timeout, but has traffic.
  *     USEFUL_SERVER_TOP_TIMEOUT ..
  *             dnsseclame servers get penalty
+ *             also for parent-side lame servers (lame in delegpt).
  *     USEFUL_SERVER_TOP_TIMEOUT*2 ..
  *             recursion lame servers get penalty
  *     UNKNOWN_SERVER_NICENESS 
@@ -202,6 +203,8 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
                        lost >= USEFUL_SERVER_MAX_LOST)
                                /* server is unresponsive */
                        return USEFUL_SERVER_TOP_TIMEOUT; 
+               else if(a->lame)
+                       return rtt+USEFUL_SERVER_TOP_TIMEOUT+1; /* nonpref */
                else if(rtt >= USEFUL_SERVER_TOP_TIMEOUT) /* not blacklisted*/
                        return USEFUL_SERVER_TOP_TIMEOUT+1; 
                else if(reclame)
@@ -211,6 +214,8 @@ iter_filter_unsuitable(struct iter_env* iter_env, struct module_env* env,
                else    return rtt;
        }
        /* no server information present */
+       if(a->lame)
+               return USEFUL_SERVER_TOP_TIMEOUT+1; /* nonpref */
        return UNKNOWN_SERVER_NICENESS;
 }
 
@@ -678,3 +683,54 @@ reply_equal(struct reply_info* p, struct reply_info* q)
        }
        return 1;
 }
+
+void 
+iter_store_inzone_glue(struct module_env* env, struct query_info* qinfo,
+       struct reply_info* rep)
+{
+       struct rrset_ref ref;
+       struct ub_packed_rrset_key* rrset;
+       if(qinfo->qtype != LDNS_RR_TYPE_A && qinfo->qtype != LDNS_RR_TYPE_AAAA)
+               return;
+       rrset = reply_find_rrset(rep, qinfo->qname, qinfo->qname_len,
+               qinfo->qtype, qinfo->qclass);
+       if(!rrset)
+               return;
+       /* got A or AAAA glue rrset. store it in case its handy */
+       rrset = packed_rrset_copy_alloc(rrset, env->alloc, *env->now);
+       if(!rrset) {
+               log_err("malloc failure in store_inzone_glue");
+               return;
+       }
+       rrset->rk.flags |= PACKED_RRSET_PARENT_SIDE;
+       rrset->entry.hash = rrset_key_hash(&rrset->rk);
+       ref.key = rrset;
+       ref.id = rrset->id;
+       /* ignore ret: it was in the cache, ref updated */
+       (void)rrset_cache_update(env->rrset_cache, &ref, env->alloc, *env->now);
+}
+
+int 
+iter_lookup_inzone_glue(struct module_env* env, struct delegpt* dp,
+       struct regional* region, struct query_info* qinfo)
+{
+       struct ub_packed_rrset_key* akey;
+       akey = rrset_cache_lookup(env->rrset_cache, qinfo->qname, 
+               qinfo->qname_len, qinfo->qtype, qinfo->qclass, 
+               PACKED_RRSET_PARENT_SIDE, *env->now, 0);
+       if(akey) {
+               if(qinfo->qtype == LDNS_RR_TYPE_A) {
+                       if(!delegpt_add_rrset_A(dp, region, akey, 1, 1)) {
+                               lock_rw_unlock(&akey->entry.lock);
+                               return 0;
+                       }
+               } else if(qinfo->qtype == LDNS_RR_TYPE_AAAA) {
+                       if(!delegpt_add_rrset_AAAA(dp, region, akey, 1, 1)) {
+                               lock_rw_unlock(&akey->entry.lock);
+                               return 0;
+                       }
+               }
+               lock_rw_unlock(&akey->entry.lock);
+       }
+       return 1;
+}
index 0cb106faed1690aba36105e1b4f2b64990189725..4cc3233801d69cf060b472c3f8fa84ed7bad8e7f 100644 (file)
@@ -210,4 +210,26 @@ int iter_msg_from_zone(struct dns_msg* msg, struct delegpt* dp,
  */
 int reply_equal(struct reply_info* p, struct reply_info* q);
 
+/**
+ * Store in-zone glue in seperate rrset cache entries for later last-resort
+ * lookups in case the child-side versions of this information fails.
+ * @param env: environment with cache, time, ...
+ * @param qinfo: query info. must match the information stored to avoid
+ *     Kaminsky-style trouble.
+ * @param rep: reply with possibly A or AAAA content to store.
+ */
+void iter_store_inzone_glue(struct module_env* env, struct query_info* qinfo,
+       struct reply_info* rep);
+
+/**
+ * Find in-zone glue from rrset cache again.
+ * @param env: query env with rrset cache and time.
+ * @param dp: delegation point to store result in.
+ * @param region: region to alloc result in.
+ * @param qinfo: query into that is pertinent.
+ * @return false on malloc failure.
+ */
+int iter_lookup_inzone_glue(struct module_env* env, struct delegpt* dp,
+       struct regional* region, struct query_info* qinfo);
+
 #endif /* ITERATOR_ITER_UTILS_H */
index 65b6493353b746218dc50647ae6d36058fd53e6e..a2491ae29d379aa5ecceec3c122a4986de6de75a 100644 (file)
@@ -1585,6 +1585,12 @@ processQueryResponse(struct module_qstate* qstate, struct iter_qstate* iq,
                                val_neg_addreferral(qstate->env->neg_cache, 
                                        iq->response->rep, iq->dp->name);
                }
+               /* store parent-side-in-zone-glue, if directly queried for */
+               if((qstate->qinfo.qtype == LDNS_RR_TYPE_A
+                       || qstate->qinfo.qtype == LDNS_RR_TYPE_AAAA)) {
+                       iter_store_inzone_glue(qstate->env,
+                               &iq->response->qinfo, iq->response->rep);
+               }
 
                /* Reset the event state, setting the current delegation 
                 * point to the referral. */
@@ -1866,6 +1872,11 @@ processTargetResponse(struct module_qstate* qstate, int id,
         * (regardless if it succeeded or not). */
        foriq->num_target_queries--;
 
+       /* perhaps we picked up interested cached addressed, like lame ones */
+       if(!iter_lookup_inzone_glue(forq->env, foriq->dp, forq->region, 
+               &iq->qchase))
+               log_err("out of memory adding lame glue");
+
        /* This response is relevant to the current query, so we 
         * add (attempt to add, anyway) this target(s) and reactivate 
         * the original event. 
index a152fa726c7c6737583b1a3aac7a51f13b88aedf..c0c83ec7f14d09146dc9beffde8560d4e219d846 100644 (file)
@@ -180,7 +180,7 @@ find_add_addrs(struct module_env* env, uint16_t qclass,
                akey = rrset_cache_lookup(env->rrset_cache, ns->name, 
                        ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);
                if(akey) {
-                       if(!delegpt_add_rrset_A(dp, region, akey, 0)) {
+                       if(!delegpt_add_rrset_A(dp, region, akey, 0, 0)) {
                                lock_rw_unlock(&akey->entry.lock);
                                return 0;
                        }
@@ -198,7 +198,7 @@ find_add_addrs(struct module_env* env, uint16_t qclass,
                akey = rrset_cache_lookup(env->rrset_cache, ns->name, 
                        ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
                if(akey) {
-                       if(!delegpt_add_rrset_AAAA(dp, region, akey, 0)) {
+                       if(!delegpt_add_rrset_AAAA(dp, region, akey, 0, 0)) {
                                lock_rw_unlock(&akey->entry.lock);
                                return 0;
                        }
@@ -213,6 +213,27 @@ find_add_addrs(struct module_env* env, uint16_t qclass,
                                lock_rw_unlock(&neg->entry.lock);
                        }
                }
+               /* see if we have parent-side-glue (dispreferred) */
+               akey = rrset_cache_lookup(env->rrset_cache, ns->name, 
+                       ns->namelen, LDNS_RR_TYPE_A, qclass, 
+                       PACKED_RRSET_PARENT_SIDE, now, 0);
+               if(akey) {
+                       if(!delegpt_add_rrset_A(dp, region, akey, 1, 1)) {
+                               lock_rw_unlock(&akey->entry.lock);
+                               return 0;
+                       }
+                       lock_rw_unlock(&akey->entry.lock);
+               }
+               akey = rrset_cache_lookup(env->rrset_cache, ns->name, 
+                       ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 
+                       PACKED_RRSET_PARENT_SIDE, now, 0);
+               if(akey) {
+                       if(!delegpt_add_rrset_AAAA(dp, region, akey, 1, 1)) {
+                               lock_rw_unlock(&akey->entry.lock);
+                               return 0;
+                       }
+                       lock_rw_unlock(&akey->entry.lock);
+               }
        }
        return 1;
 }
@@ -232,7 +253,7 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
                akey = rrset_cache_lookup(env->rrset_cache, ns->name, 
                        ns->namelen, LDNS_RR_TYPE_A, qclass, 0, now, 0);
                if(akey) {
-                       if(!delegpt_add_rrset_A(dp, region, akey, 1)) {
+                       if(!delegpt_add_rrset_A(dp, region, akey, 0, 1)) {
                                lock_rw_unlock(&akey->entry.lock);
                                return 0;
                        }
@@ -250,7 +271,7 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
                akey = rrset_cache_lookup(env->rrset_cache, ns->name, 
                        ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 0, now, 0);
                if(akey) {
-                       if(!delegpt_add_rrset_AAAA(dp, region, akey, 1)) {
+                       if(!delegpt_add_rrset_AAAA(dp, region, akey, 0, 1)) {
                                lock_rw_unlock(&akey->entry.lock);
                                return 0;
                        }
@@ -265,6 +286,27 @@ cache_fill_missing(struct module_env* env, uint16_t qclass,
                                lock_rw_unlock(&neg->entry.lock);
                        }
                }
+               /* see if we have parent-side-glue (dispreferred) */
+               akey = rrset_cache_lookup(env->rrset_cache, ns->name, 
+                       ns->namelen, LDNS_RR_TYPE_A, qclass, 
+                       PACKED_RRSET_PARENT_SIDE, now, 0);
+               if(akey) {
+                       if(!delegpt_add_rrset_A(dp, region, akey, 1, 1)) {
+                               lock_rw_unlock(&akey->entry.lock);
+                               return 0;
+                       }
+                       lock_rw_unlock(&akey->entry.lock);
+               }
+               akey = rrset_cache_lookup(env->rrset_cache, ns->name, 
+                       ns->namelen, LDNS_RR_TYPE_AAAA, qclass, 
+                       PACKED_RRSET_PARENT_SIDE, now, 0);
+               if(akey) {
+                       if(!delegpt_add_rrset_AAAA(dp, region, akey, 1, 1)) {
+                               lock_rw_unlock(&akey->entry.lock);
+                               return 0;
+                       }
+                       lock_rw_unlock(&akey->entry.lock);
+               }
        }
        return 1;
 }
diff --git a/testdata/iter_pcdiff.rpl b/testdata/iter_pcdiff.rpl
new file mode 100644 (file)
index 0000000..18b984c
--- /dev/null
@@ -0,0 +1,213 @@
+; config options
+server:
+       target-fetch-policy: "0 0 0 0 0"
+
+stub-zone:
+       name: "."
+       stub-addr: 193.0.14.129         # K.ROOT-SERVERS.NET.
+CONFIG_END
+
+SCENARIO_BEGIN Test resolution with recursion and parent child differ.
+; and the child gives bad information.
+
+; K.ROOT-SERVERS.NET.
+RANGE_BEGIN 0 100
+       ADDRESS 193.0.14.129 
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+. IN NS
+SECTION ANSWER
+. IN NS        K.ROOT-SERVERS.NET.
+SECTION ADDITIONAL
+K.ROOT-SERVERS.NET.    IN      A       193.0.14.129
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION AUTHORITY
+com.   IN NS   a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net.    IN      A       192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION AUTHORITY
+net.   IN NS   e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net.    IN      A       192.12.94.30
+ENTRY_END
+
+RANGE_END
+
+; a.gtld-servers.net.
+RANGE_BEGIN 0 100
+       ADDRESS 192.5.6.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+com. IN NS
+SECTION ANSWER
+com.   IN NS   a.gtld-servers.net.
+SECTION ADDITIONAL
+a.gtld-servers.net.    IN      A       192.5.6.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.net.
+ENTRY_END
+RANGE_END
+
+; e.gtld-servers.net.
+RANGE_BEGIN 0 100
+       ADDRESS 192.12.94.30
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY QR NOERROR
+SECTION QUESTION
+net. IN NS
+SECTION ANSWER
+net.   IN NS   e.gtld-servers.net.
+SECTION ADDITIONAL
+e.gtld-servers.net.    IN      A       192.12.94.30
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode subdomain
+ADJUST copy_id copy_query
+REPLY QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.44
+ENTRY_END
+
+RANGE_END
+
+; ns.example.net.
+; The parent-IP version
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.44
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net.                IN      A       1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN A
+SECTION ANSWER
+ns.example.net. IN A   1.2.3.55
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+ns.example.net. IN AAAA
+SECTION AUTHORITY
+example.net.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net. IN A   1.2.3.55
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+example.com. IN NS
+SECTION ANSWER
+example.com.   IN NS   ns.example.net.
+ENTRY_END
+
+ENTRY_BEGIN
+MATCH opcode qtype qname
+ADJUST copy_id
+REPLY AA QR NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A  10.20.30.40
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.net.
+SECTION ADDITIONAL
+ns.example.net         IN A    1.2.3.55
+ENTRY_END
+RANGE_END
+
+; ns.example.net
+; The child IP version.   Does not respond to anything (servfail instead
+; of timeouts since this is easier to encode in .rpl file format).
+RANGE_BEGIN 0 100
+       ADDRESS 1.2.3.55
+ENTRY_BEGIN
+MATCH opcode 
+ADJUST copy_id copy_query
+REPLY QR SERVFAIL
+SECTION QUESTION
+example.net. IN NS
+SECTION ANSWER
+ENTRY_END
+
+RANGE_END
+
+STEP 1 QUERY
+ENTRY_BEGIN
+REPLY RD
+SECTION QUESTION
+www.example.com. IN A
+ENTRY_END
+
+; recursion happens here.
+STEP 20 CHECK_ANSWER
+ENTRY_BEGIN
+MATCH all
+REPLY QR RD RA NOERROR
+SECTION QUESTION
+www.example.com. IN A
+SECTION ANSWER
+www.example.com. IN A  10.20.30.40
+SECTION AUTHORITY
+example.com.   IN NS   ns.example.net.
+; scrubbed off
+;SECTION ADDITIONAL
+;ns.example.net        IN A    1.2.3.44
+ENTRY_END
+
+SCENARIO_END
index 0db11ac90c9c468b646515bf657634a100bb7596..c1fc407fbb10f8ab7813cecbd57acf6df7692777 100644 (file)
@@ -751,6 +751,22 @@ struct ub_packed_rrset_key* reply_find_rrset_section_ns(struct reply_info* rep,
        return NULL;
 }
 
+struct ub_packed_rrset_key* reply_find_rrset(struct reply_info* rep,
+       uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass)
+{
+       size_t i;
+       for(i=0; i<rep->rrset_count; i++) {
+               struct ub_packed_rrset_key* s = rep->rrsets[i];
+               if(ntohs(s->rk.type) == type && 
+                       ntohs(s->rk.rrset_class) == dclass && 
+                       namelen == s->rk.dname_len &&
+                       query_dname_compare(name, s->rk.dname) == 0) {
+                       return s;
+               }
+       }
+       return NULL;
+}
+
 void 
 log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep)
 {
index c14e9227cb516ba693bf04463ad0cce0485d6b57..855554be88d9cdef2513e36631a06c60292b0b95 100644 (file)
@@ -378,6 +378,18 @@ struct ub_packed_rrset_key* reply_find_rrset_section_an(struct reply_info* rep,
 struct ub_packed_rrset_key* reply_find_rrset_section_ns(struct reply_info* rep,
        uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass);
 
+/**
+ * Find rrset in reply, inside any section. Does not follow CNAMEs.
+ * @param rep: looks in answer,authority and additional section of this message.
+ * @param name: what to look for.
+ * @param namelen: length of name.
+ * @param type: looks for (host order).
+ * @param dclass: looks for (host order).
+ * @return: pointer to rrset, or NULL if not found.
+ */
+struct ub_packed_rrset_key* reply_find_rrset(struct reply_info* rep,
+       uint8_t* name, size_t namelen, uint16_t type, uint16_t dclass);
+
 /**
  * Debug send the query info and reply info to the log in readable form.
  * @param str: descriptive string printed with packet content.
index eedf757466a84d4eb0fd2c9c83bd10f4078776a0..c1791eda7d48b2386ac1ca6051c981acf88c7308 100644 (file)
@@ -304,6 +304,33 @@ packed_rrset_copy_region(struct ub_packed_rrset_key* key,
        return ck;
 }
 
+struct ub_packed_rrset_key* 
+packed_rrset_copy_alloc(struct ub_packed_rrset_key* key, 
+       struct alloc_cache* alloc, uint32_t now)
+{
+       struct packed_rrset_data* fd, *dd;
+       struct ub_packed_rrset_key* dk = alloc_special_obtain(alloc);
+       if(!dk) return NULL;
+       fd = (struct packed_rrset_data*)key->entry.data;
+       dk->entry.hash = key->entry.hash;
+       dk->rk = key->rk;
+       dk->rk.dname = (uint8_t*)memdup(key->rk.dname, key->rk.dname_len);
+       if(!dk->rk.dname) {
+               alloc_special_release(alloc, dk);
+               return NULL;
+       }
+       dd = (struct packed_rrset_data*)memdup(fd, packed_rrset_sizeof(fd));
+       if(!dd) {
+               free(dk->rk.dname);
+               alloc_special_release(alloc, dk);
+               return NULL;
+       }
+       packed_rrset_ptr_fixup(dd);
+       dk->entry.data = (void*)dd;
+       packed_rrset_ttl_add(dd, now);
+       return dk;
+}
+
 struct ub_packed_rrset_key* 
 ub_packed_rrset_heap_key(ldns_rr_list* rrset)
 {
index a80ce24cf87a354cec23d1cb8f085f571c1c5d7f..ad09cae63e5f8c2981f826c855135631a4b368cd 100644 (file)
@@ -51,6 +51,8 @@ typedef uint64_t rrset_id_t;
 
 /** this rrset is NSEC and is at zone apex (at child side of zonecut) */
 #define PACKED_RRSET_NSEC_AT_APEX 0x1
+/** this rrset is A/AAAA and is in-zone-glue (from parent side of zonecut) */
+#define PACKED_RRSET_PARENT_SIDE 0x2
 
 /**
  * The identifying information for an RRset.
@@ -69,6 +71,7 @@ struct packed_rrset_key {
        /**
         * Flags. 32bit to be easy for hashing:
         *      o PACKED_RRSET_NSEC_AT_APEX
+        *      o PACKED_RRSET_PARENT_SIDE
         */
        uint32_t flags;
        /** the rrset type in network format */
@@ -376,6 +379,17 @@ struct ub_packed_rrset_key* packed_rrset_copy_region(
        struct ub_packed_rrset_key* key, struct regional* region, 
        uint32_t now);
 
+/** 
+ * Allocate rrset with malloc (from region or you are holding the lock).
+ * @param key: key with data entry.
+ * @param alloc: alloc_cache to create rrset_keys
+ * @param now: adjust the TTLs to be abolsute (add to all TTLs).
+ * @return new region-alloced rrset key or NULL on alloc failure.
+ */
+struct ub_packed_rrset_key* packed_rrset_copy_alloc(
+       struct ub_packed_rrset_key* key, struct alloc_cache* alloc, 
+       uint32_t now);
+
 /**
  * Create a ub_packed_rrset_key allocated on the heap.
  * It therefore does not have the correct ID value, and cannot be used