summaryrefslogtreecommitdiff
path: root/contrib/unbound/util/data
diff options
context:
space:
mode:
authorCy Schubert <cy@FreeBSD.org>2019-12-31 15:50:41 +0000
committerCy Schubert <cy@FreeBSD.org>2019-12-31 15:50:41 +0000
commit0eefd3079a04edf4cf315403beb0344724567f42 (patch)
treeac77aee886bf3d3af45942d2573720d128c5688e /contrib/unbound/util/data
parent493c98c6d2b52d2066a913203e4cbcee5a6080c2 (diff)
parente2fe726866d062155f6b1aae749375475ef19191 (diff)
downloadsrc-test2-0eefd3079a04edf4cf315403beb0344724567f42.tar.gz
src-test2-0eefd3079a04edf4cf315403beb0344724567f42.zip
Notes
Diffstat (limited to 'contrib/unbound/util/data')
-rw-r--r--contrib/unbound/util/data/dname.c12
-rw-r--r--contrib/unbound/util/data/msgencode.c72
-rw-r--r--contrib/unbound/util/data/msgencode.h4
-rw-r--r--contrib/unbound/util/data/msgparse.c4
-rw-r--r--contrib/unbound/util/data/msgreply.c4
5 files changed, 67 insertions, 29 deletions
diff --git a/contrib/unbound/util/data/dname.c b/contrib/unbound/util/data/dname.c
index c7360f75f32a..9f25e1efe204 100644
--- a/contrib/unbound/util/data/dname.c
+++ b/contrib/unbound/util/data/dname.c
@@ -75,6 +75,8 @@ dname_valid(uint8_t* dname, size_t maxlen)
{
size_t len = 0;
size_t labellen;
+ if(maxlen == 0)
+ return 0; /* too short, shortest is '0' root label */
labellen = *dname++;
while(labellen) {
if(labellen&0xc0)
@@ -327,16 +329,26 @@ dname_pkt_hash(sldns_buffer* pkt, uint8_t* dname, hashvalue_type h)
void dname_pkt_copy(sldns_buffer* pkt, uint8_t* to, uint8_t* dname)
{
/* copy over the dname and decompress it at the same time */
+ size_t comprcount = 0;
size_t len = 0;
uint8_t lablen;
lablen = *dname++;
while(lablen) {
if(LABEL_IS_PTR(lablen)) {
+ if(comprcount++ > MAX_COMPRESS_PTRS) {
+ /* too many compression pointers */
+ *to = 0; /* end the result prematurely */
+ return;
+ }
/* follow pointer */
dname = sldns_buffer_at(pkt, PTR_OFFSET(lablen, *dname));
lablen = *dname++;
continue;
}
+ if(lablen > LDNS_MAX_LABELLEN) {
+ *to = 0; /* end the result prematurely */
+ return;
+ }
log_assert(lablen <= LDNS_MAX_LABELLEN);
len += (size_t)lablen+1;
if(len >= LDNS_MAX_DOMAINLEN) {
diff --git a/contrib/unbound/util/data/msgencode.c b/contrib/unbound/util/data/msgencode.c
index 4c0a5550be13..a51a4b9b85d8 100644
--- a/contrib/unbound/util/data/msgencode.c
+++ b/contrib/unbound/util/data/msgencode.c
@@ -639,15 +639,37 @@ positive_answer(struct reply_info* rep, uint16_t qtype) {
return 0;
}
-int
-reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
- uint16_t id, uint16_t flags, sldns_buffer* buffer, time_t timenow,
- struct regional* region, uint16_t udpsize, int dnssec)
+static int
+negative_answer(struct reply_info* rep) {
+ size_t i;
+ int ns_seen = 0;
+ if(FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NXDOMAIN)
+ return 1;
+ if(FLAGS_GET_RCODE(rep->flags) == LDNS_RCODE_NOERROR &&
+ rep->an_numrrsets != 0)
+ return 0; /* positive */
+ if(FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NOERROR &&
+ FLAGS_GET_RCODE(rep->flags) != LDNS_RCODE_NXDOMAIN)
+ return 0;
+ for(i=rep->an_numrrsets; i<rep->an_numrrsets+rep->ns_numrrsets; i++){
+ if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_SOA)
+ return 1;
+ if(ntohs(rep->rrsets[i]->rk.type) == LDNS_RR_TYPE_NS)
+ ns_seen = 1;
+ }
+ if(ns_seen) return 0; /* could be referral, NS, but no SOA */
+ return 1;
+}
+
+int
+reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
+ uint16_t id, uint16_t flags, sldns_buffer* buffer, time_t timenow,
+ struct regional* region, uint16_t udpsize, int dnssec, int minimise)
{
uint16_t ancount=0, nscount=0, arcount=0;
struct compress_tree_node* tree = 0;
int r;
- size_t rr_offset;
+ size_t rr_offset;
sldns_buffer_clear(buffer);
if(udpsize < sldns_buffer_limit(buffer))
@@ -663,7 +685,7 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
/* insert query section */
if(rep->qdcount) {
- if((r=insert_query(qinfo, &tree, buffer, region)) !=
+ if((r=insert_query(qinfo, &tree, buffer, region)) !=
RETVAL_OK) {
if(r == RETVAL_TRUNC) {
/* create truncated message */
@@ -707,8 +729,8 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
}
/* insert answer section */
- if((r=insert_section(rep, rep->an_numrrsets, &ancount, buffer,
- 0, timenow, region, &tree, LDNS_SECTION_ANSWER, qinfo->qtype,
+ if((r=insert_section(rep, rep->an_numrrsets, &ancount, buffer,
+ 0, timenow, region, &tree, LDNS_SECTION_ANSWER, qinfo->qtype,
dnssec, rr_offset)) != RETVAL_OK) {
if(r == RETVAL_TRUNC) {
/* create truncated message */
@@ -722,9 +744,9 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
sldns_buffer_write_u16_at(buffer, 6, ancount);
/* if response is positive answer, auth/add sections are not required */
- if( ! (MINIMAL_RESPONSES && positive_answer(rep, qinfo->qtype)) ) {
+ if( ! (minimise && positive_answer(rep, qinfo->qtype)) ) {
/* insert auth section */
- if((r=insert_section(rep, rep->ns_numrrsets, &nscount, buffer,
+ if((r=insert_section(rep, rep->ns_numrrsets, &nscount, buffer,
rep->an_numrrsets, timenow, region, &tree,
LDNS_SECTION_AUTHORITY, qinfo->qtype,
dnssec, rr_offset)) != RETVAL_OK) {
@@ -739,20 +761,22 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
}
sldns_buffer_write_u16_at(buffer, 8, nscount);
- /* insert add section */
- if((r=insert_section(rep, rep->ar_numrrsets, &arcount, buffer,
- rep->an_numrrsets + rep->ns_numrrsets, timenow, region,
- &tree, LDNS_SECTION_ADDITIONAL, qinfo->qtype,
- dnssec, rr_offset)) != RETVAL_OK) {
- if(r == RETVAL_TRUNC) {
- /* no need to set TC bit, this is the additional */
- sldns_buffer_write_u16_at(buffer, 10, arcount);
- sldns_buffer_flip(buffer);
- return 1;
+ if(! (minimise && negative_answer(rep))) {
+ /* insert add section */
+ if((r=insert_section(rep, rep->ar_numrrsets, &arcount, buffer,
+ rep->an_numrrsets + rep->ns_numrrsets, timenow, region,
+ &tree, LDNS_SECTION_ADDITIONAL, qinfo->qtype,
+ dnssec, rr_offset)) != RETVAL_OK) {
+ if(r == RETVAL_TRUNC) {
+ /* no need to set TC bit, this is the additional */
+ sldns_buffer_write_u16_at(buffer, 10, arcount);
+ sldns_buffer_flip(buffer);
+ return 1;
+ }
+ return 0;
}
- return 0;
+ sldns_buffer_write_u16_at(buffer, 10, arcount);
}
- sldns_buffer_write_u16_at(buffer, 10, arcount);
}
sldns_buffer_flip(buffer);
return 1;
@@ -763,7 +787,7 @@ calc_edns_field_size(struct edns_data* edns)
{
size_t rdatalen = 0;
struct edns_option* opt;
- if(!edns || !edns->edns_present)
+ if(!edns || !edns->edns_present)
return 0;
for(opt = edns->opt_list; opt; opt = opt->next) {
rdatalen += 4 + opt->opt_len;
@@ -850,7 +874,7 @@ reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
}
if(!reply_info_encode(qinf, rep, id, flags, pkt, timenow, region,
- udpsize, dnssec)) {
+ udpsize, dnssec, MINIMAL_RESPONSES)) {
log_err("reply encode: out of memory");
return 0;
}
diff --git a/contrib/unbound/util/data/msgencode.h b/contrib/unbound/util/data/msgencode.h
index eea129d98d59..30dc515cbe59 100644
--- a/contrib/unbound/util/data/msgencode.h
+++ b/contrib/unbound/util/data/msgencode.h
@@ -85,12 +85,14 @@ int reply_info_answer_encode(struct query_info* qinf, struct reply_info* rep,
* @param region: to store temporary data in.
* @param udpsize: size of the answer, 512, from EDNS, or 64k for TCP.
* @param dnssec: if 0 DNSSEC records are omitted from the answer.
+ * @param minimise: if true, the answer is a minimal response, with
+ * authority and additional removed if possible.
* @return: nonzero is success, or
* 0 on error: malloc failure (no log_err has been done).
*/
int reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
uint16_t id, uint16_t flags, struct sldns_buffer* buffer, time_t timenow,
- struct regional* region, uint16_t udpsize, int dnssec);
+ struct regional* region, uint16_t udpsize, int dnssec, int minimise);
/**
* Encode query packet. Assumes the buffer is large enough.
diff --git a/contrib/unbound/util/data/msgparse.c b/contrib/unbound/util/data/msgparse.c
index 13cad8a26630..fb312370366d 100644
--- a/contrib/unbound/util/data/msgparse.c
+++ b/contrib/unbound/util/data/msgparse.c
@@ -1061,18 +1061,18 @@ parse_edns_from_pkt(sldns_buffer* pkt, struct edns_data* edns,
size_t rdata_len;
uint8_t* rdata_ptr;
log_assert(LDNS_QDCOUNT(sldns_buffer_begin(pkt)) == 1);
+ memset(edns, 0, sizeof(*edns));
if(LDNS_ANCOUNT(sldns_buffer_begin(pkt)) != 0 ||
LDNS_NSCOUNT(sldns_buffer_begin(pkt)) != 0) {
if(!skip_pkt_rrs(pkt, ((int)LDNS_ANCOUNT(sldns_buffer_begin(pkt)))+
((int)LDNS_NSCOUNT(sldns_buffer_begin(pkt)))))
- return 0;
+ return LDNS_RCODE_FORMERR;
}
/* check edns section is present */
if(LDNS_ARCOUNT(sldns_buffer_begin(pkt)) > 1) {
return LDNS_RCODE_FORMERR;
}
if(LDNS_ARCOUNT(sldns_buffer_begin(pkt)) == 0) {
- memset(edns, 0, sizeof(*edns));
edns->udp_size = 512;
return 0;
}
diff --git a/contrib/unbound/util/data/msgreply.c b/contrib/unbound/util/data/msgreply.c
index 32aec4bf4c95..4320f312d6f3 100644
--- a/contrib/unbound/util/data/msgreply.c
+++ b/contrib/unbound/util/data/msgreply.c
@@ -243,10 +243,10 @@ rdata_copy(sldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to,
break;
}
if(len) {
+ log_assert(len <= pkt_len);
memmove(to, sldns_buffer_current(pkt), len);
to += len;
sldns_buffer_skip(pkt, (ssize_t)len);
- log_assert(len <= pkt_len);
pkt_len -= len;
}
rdf++;
@@ -819,7 +819,7 @@ log_dns_msg(const char* str, struct query_info* qinfo, struct reply_info* rep)
sldns_buffer* buf = sldns_buffer_new(65535);
struct regional* region = regional_create();
if(!reply_info_encode(qinfo, rep, 0, rep->flags, buf, 0,
- region, 65535, 1)) {
+ region, 65535, 1, 0)) {
log_info("%s: log_dns_msg: out of memory", str);
} else {
char* s = sldns_wire2str_pkt(sldns_buffer_begin(buf),