aboutsummaryrefslogtreecommitdiff
path: root/external/unbound/util/data/msgreply.c
diff options
context:
space:
mode:
Diffstat (limited to 'external/unbound/util/data/msgreply.c')
-rw-r--r--external/unbound/util/data/msgreply.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/external/unbound/util/data/msgreply.c b/external/unbound/util/data/msgreply.c
index dc27be905..b1d3df639 100644
--- a/external/unbound/util/data/msgreply.c
+++ b/external/unbound/util/data/msgreply.c
@@ -57,6 +57,8 @@
time_t MAX_TTL = 3600 * 24 * 10; /* ten days */
/** MIN TTL default for messages and rrsets */
time_t MIN_TTL = 0;
+/** MAX Negative TTL, for SOA records in authority section */
+time_t MAX_NEG_TTL = 3600; /* one hour */
/** allocate qinfo, return 0 on error */
static int
@@ -153,10 +155,23 @@ repinfo_alloc_rrset_keys(struct reply_info* rep, struct alloc_cache* alloc,
return 1;
}
+/** find the minimumttl in the rdata of SOA record */
+static time_t
+soa_find_minttl(struct rr_parse* rr)
+{
+ uint16_t rlen = sldns_read_uint16(rr->ttl_data+4);
+ if(rlen < 20)
+ return 0; /* rdata too small for SOA (dname, dname, 5*32bit) */
+ /* minimum TTL is the last 32bit value in the rdata of the record */
+ /* at position ttl_data + 4(ttl) + 2(rdatalen) + rdatalen - 4(timeval)*/
+ return (time_t)sldns_read_uint32(rr->ttl_data+6+rlen-4);
+}
+
/** do the rdata copy */
static int
rdata_copy(sldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to,
- struct rr_parse* rr, time_t* rr_ttl, uint16_t type)
+ struct rr_parse* rr, time_t* rr_ttl, uint16_t type,
+ sldns_pkt_section section)
{
uint16_t pkt_len;
const sldns_rr_descriptor* desc;
@@ -165,6 +180,14 @@ rdata_copy(sldns_buffer* pkt, struct packed_rrset_data* data, uint8_t* to,
/* RFC 2181 Section 8. if msb of ttl is set treat as if zero. */
if(*rr_ttl & 0x80000000U)
*rr_ttl = 0;
+ if(type == LDNS_RR_TYPE_SOA && section == LDNS_SECTION_AUTHORITY) {
+ /* negative response. see if TTL of SOA record larger than the
+ * minimum-ttl in the rdata of the SOA record */
+ if(*rr_ttl > soa_find_minttl(rr))
+ *rr_ttl = soa_find_minttl(rr);
+ if(*rr_ttl > MAX_NEG_TTL)
+ *rr_ttl = MAX_NEG_TTL;
+ }
if(*rr_ttl < MIN_TTL)
*rr_ttl = MIN_TTL;
if(*rr_ttl < data->ttl)
@@ -254,7 +277,7 @@ parse_rr_copy(sldns_buffer* pkt, struct rrset_parse* pset,
data->rr_data[i] = nextrdata;
nextrdata += rr->size;
if(!rdata_copy(pkt, data, data->rr_data[i], rr,
- &data->rr_ttl[i], pset->type))
+ &data->rr_ttl[i], pset->type, pset->section))
return 0;
rr = rr->next;
}
@@ -265,7 +288,7 @@ parse_rr_copy(sldns_buffer* pkt, struct rrset_parse* pset,
data->rr_data[i] = nextrdata;
nextrdata += rr->size;
if(!rdata_copy(pkt, data, data->rr_data[i], rr,
- &data->rr_ttl[i], LDNS_RR_TYPE_RRSIG))
+ &data->rr_ttl[i], LDNS_RR_TYPE_RRSIG, pset->section))
return 0;
rr = rr->next;
}