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;
}
+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.
}
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;
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) {
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) {
a->addrlen = addrlen;
a->attempts = 0;
a->bogus = bogus;
+ a->lame = lame;
return 1;
}
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;
}
}
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;
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;
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;
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;
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;
}
/** 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;
};
/**
* @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.
* @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.
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;
}
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;
}
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;
}
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;
}
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;
}
* 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
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)
else return rtt;
}
/* no server information present */
+ if(a->lame)
+ return USEFUL_SERVER_TOP_TIMEOUT+1; /* nonpref */
return UNKNOWN_SERVER_NICENESS;
}
}
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;
+}
*/
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 */
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. */
* (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.
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
--- /dev/null
+; 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
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)
{
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.
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)
{
/** 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.
/**
* 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 */
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