diff options
author | Cy Schubert <cy@FreeBSD.org> | 2019-12-31 15:50:41 +0000 |
---|---|---|
committer | Cy Schubert <cy@FreeBSD.org> | 2019-12-31 15:50:41 +0000 |
commit | 0eefd3079a04edf4cf315403beb0344724567f42 (patch) | |
tree | ac77aee886bf3d3af45942d2573720d128c5688e /contrib/unbound/util/data | |
parent | 493c98c6d2b52d2066a913203e4cbcee5a6080c2 (diff) | |
parent | e2fe726866d062155f6b1aae749375475ef19191 (diff) | |
download | src-test2-0eefd3079a04edf4cf315403beb0344724567f42.tar.gz src-test2-0eefd3079a04edf4cf315403beb0344724567f42.zip |
Notes
Diffstat (limited to 'contrib/unbound/util/data')
-rw-r--r-- | contrib/unbound/util/data/dname.c | 12 | ||||
-rw-r--r-- | contrib/unbound/util/data/msgencode.c | 72 | ||||
-rw-r--r-- | contrib/unbound/util/data/msgencode.h | 4 | ||||
-rw-r--r-- | contrib/unbound/util/data/msgparse.c | 4 | ||||
-rw-r--r-- | contrib/unbound/util/data/msgreply.c | 4 |
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), |