mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-31 03:49:35 -05:00
Fix lookup of domains with parent-child zonecut data differences.
git-svn-id: file:///svn/unbound/trunk@1929 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
eeb6bf49d0
commit
59c529bada
15 changed files with 455 additions and 26 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
50
services/cache/dns.c
vendored
50
services/cache/dns.c
vendored
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
213
testdata/iter_pcdiff.rpl
vendored
Normal file
213
testdata/iter_pcdiff.rpl
vendored
Normal file
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue