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:
Wouter Wijngaards 2009-12-08 13:37:59 +00:00
parent eeb6bf49d0
commit 59c529bada
15 changed files with 455 additions and 26 deletions

View 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;
}

View 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.

View 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;
}

View 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.

View 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;
}

View 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;
}

View 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;
}

View 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 */

View 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.

50
services/cache/dns.c vendored
View 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;
}

213
testdata/iter_pcdiff.rpl vendored Normal file
View 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

View 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)
{

View 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.

View 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)
{

View 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