mirror of
https://github.com/NLnetLabs/unbound.git
synced 2026-10-01 06:04:55 +02:00
- Patch that resolves CNAMEs entered in local-data conf statements that
point to data on the internet, from Jinmei Tatuya (Infoblox). git-svn-id: file:///svn/unbound/trunk@3885 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
+66
-10
@@ -48,6 +48,7 @@
|
||||
#include "util/regional.h"
|
||||
#include "util/net_help.h"
|
||||
#include "sldns/sbuffer.h"
|
||||
#include "services/localzone.h"
|
||||
|
||||
/** return code that means the function ran out of memory. negative so it does
|
||||
* not conflict with DNS rcodes. */
|
||||
@@ -534,7 +535,14 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
|
||||
{
|
||||
int r;
|
||||
size_t i, setstart;
|
||||
*num_rrs = 0;
|
||||
/* we now allow this function to be called multiple times for the
|
||||
* same section, incrementally updating num_rrs. The caller is
|
||||
* responsible for initializing it (which is the case in the current
|
||||
* implementation).
|
||||
* Note: once approved, this comment and the following line should be
|
||||
* removed. */
|
||||
/**num_rrs = 0;*/
|
||||
|
||||
if(s != LDNS_SECTION_ADDITIONAL) {
|
||||
if(s == LDNS_SECTION_ANSWER && qtype == LDNS_RR_TYPE_ANY)
|
||||
dnssec = 1; /* include all types in ANY answer */
|
||||
@@ -581,17 +589,20 @@ static int
|
||||
insert_query(struct query_info* qinfo, struct compress_tree_node** tree,
|
||||
sldns_buffer* buffer, struct regional* region)
|
||||
{
|
||||
uint8_t* qname = qinfo->local_alias ?
|
||||
qinfo->local_alias->rrset->rk.dname : qinfo->qname;
|
||||
size_t qname_len = qinfo->local_alias ?
|
||||
qinfo->local_alias->rrset->rk.dname_len : qinfo->qname_len;
|
||||
if(sldns_buffer_remaining(buffer) <
|
||||
qinfo->qname_len+sizeof(uint16_t)*2)
|
||||
return RETVAL_TRUNC; /* buffer too small */
|
||||
/* the query is the first name inserted into the tree */
|
||||
if(!compress_tree_store(qinfo->qname,
|
||||
dname_count_labels(qinfo->qname),
|
||||
if(!compress_tree_store(qname, dname_count_labels(qname),
|
||||
sldns_buffer_position(buffer), region, NULL, tree))
|
||||
return RETVAL_OUTMEM;
|
||||
if(sldns_buffer_current(buffer) == qinfo->qname)
|
||||
sldns_buffer_skip(buffer, (ssize_t)qinfo->qname_len);
|
||||
else sldns_buffer_write(buffer, qinfo->qname, qinfo->qname_len);
|
||||
if(sldns_buffer_current(buffer) == qname)
|
||||
sldns_buffer_skip(buffer, (ssize_t)qname_len);
|
||||
else sldns_buffer_write(buffer, qname, qname_len);
|
||||
sldns_buffer_write_u16(buffer, qinfo->qtype);
|
||||
sldns_buffer_write_u16(buffer, qinfo->qclass);
|
||||
return RETVAL_OK;
|
||||
@@ -662,6 +673,33 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
|
||||
* for different roundrobins for sequential id client senders. */
|
||||
rr_offset = RRSET_ROUNDROBIN?ntohs(id):0;
|
||||
|
||||
/* "prepend" any local alias records in the answer section if this
|
||||
* response is supposed to be authoritative. Currently it should
|
||||
* be a single CNAME record (sanity-checked in worker_handle_request())
|
||||
* but it can be extended if and when we support more variations of
|
||||
* aliases. */
|
||||
if(qinfo->local_alias && (flags & BIT_AA)) {
|
||||
struct reply_info arep;
|
||||
time_t timezero = 0; /* to use the 'authoritative' TTL */
|
||||
memset(&arep, 0, sizeof(arep));
|
||||
arep.flags = rep->flags;
|
||||
arep.an_numrrsets = 1;
|
||||
arep.rrset_count = 1;
|
||||
arep.rrsets = &qinfo->local_alias->rrset;
|
||||
if((r=insert_section(&arep, 1, &ancount, buffer, 0,
|
||||
timezero, region, &tree, LDNS_SECTION_ANSWER,
|
||||
qinfo->qtype, dnssec, rr_offset)) != RETVAL_OK) {
|
||||
if(r == RETVAL_TRUNC) {
|
||||
/* create truncated message */
|
||||
sldns_buffer_write_u16_at(buffer, 6, ancount);
|
||||
LDNS_TC_SET(sldns_buffer_begin(buffer));
|
||||
sldns_buffer_flip(buffer);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* insert answer section */
|
||||
if((r=insert_section(rep, rep->an_numrrsets, &ancount, buffer,
|
||||
0, timenow, region, &tree, LDNS_SECTION_ANSWER, qinfo->qtype,
|
||||
@@ -782,6 +820,15 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
|
||||
}
|
||||
if(secure && (dnssec || (qflags&BIT_AD)))
|
||||
flags |= BIT_AD;
|
||||
/* restore AA bit if we have a local alias and the response can be
|
||||
* authoritative. Also clear AD bit if set as the local data is the
|
||||
* primary answer. */
|
||||
if(qinf->local_alias &&
|
||||
(FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR ||
|
||||
FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN)) {
|
||||
flags |= BIT_AA;
|
||||
flags &= ~BIT_AD;
|
||||
}
|
||||
log_assert(flags & BIT_QR); /* QR bit must be on in our replies */
|
||||
if(udpsize < LDNS_HEADER_SIZE)
|
||||
return 0;
|
||||
@@ -807,13 +854,17 @@ void
|
||||
qinfo_query_encode(sldns_buffer* pkt, struct query_info* qinfo)
|
||||
{
|
||||
uint16_t flags = 0; /* QUERY, NOERROR */
|
||||
const uint8_t* qname = qinfo->local_alias ?
|
||||
qinfo->local_alias->rrset->rk.dname : qinfo->qname;
|
||||
size_t qname_len = qinfo->local_alias ?
|
||||
qinfo->local_alias->rrset->rk.dname_len : qinfo->qname_len;
|
||||
sldns_buffer_clear(pkt);
|
||||
log_assert(sldns_buffer_remaining(pkt) >= 12+255+4/*max query*/);
|
||||
sldns_buffer_skip(pkt, 2); /* id done later */
|
||||
sldns_buffer_write_u16(pkt, flags);
|
||||
sldns_buffer_write_u16(pkt, 1); /* query count */
|
||||
sldns_buffer_write(pkt, "\000\000\000\000\000\000", 6); /* counts */
|
||||
sldns_buffer_write(pkt, qinfo->qname, qinfo->qname_len);
|
||||
sldns_buffer_write(pkt, qname, qname_len);
|
||||
sldns_buffer_write_u16(pkt, qinfo->qtype);
|
||||
sldns_buffer_write_u16(pkt, qinfo->qclass);
|
||||
sldns_buffer_flip(pkt);
|
||||
@@ -838,9 +889,14 @@ error_encode(sldns_buffer* buf, int r, struct query_info* qinfo,
|
||||
sldns_buffer_write(buf, &flags, sizeof(uint16_t));
|
||||
sldns_buffer_write(buf, &flags, sizeof(uint16_t));
|
||||
if(qinfo) {
|
||||
if(sldns_buffer_current(buf) == qinfo->qname)
|
||||
sldns_buffer_skip(buf, (ssize_t)qinfo->qname_len);
|
||||
else sldns_buffer_write(buf, qinfo->qname, qinfo->qname_len);
|
||||
const uint8_t* qname = qinfo->local_alias ?
|
||||
qinfo->local_alias->rrset->rk.dname : qinfo->qname;
|
||||
size_t qname_len = qinfo->local_alias ?
|
||||
qinfo->local_alias->rrset->rk.dname_len :
|
||||
qinfo->qname_len;
|
||||
if(sldns_buffer_current(buf) == qname)
|
||||
sldns_buffer_skip(buf, (ssize_t)qname_len);
|
||||
else sldns_buffer_write(buf, qname, qname_len);
|
||||
sldns_buffer_write_u16(buf, qinfo->qtype);
|
||||
sldns_buffer_write_u16(buf, qinfo->qclass);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user