313 lines
12 KiB
Diff
313 lines
12 KiB
Diff
|
From 12d6612439271b2ca5c894ab2edda5364d6c4bfa Mon Sep 17 00:00:00 2001
|
||
|
From: Tomas Hozza <thozza@redhat.com>
|
||
|
Date: Mon, 15 Jun 2015 18:42:10 +0200
|
||
|
Subject: [PATCH 1/2] SOA negative TTL is capped at minimumttl in its rdata
|
||
|
section. - cache-max-negative-ttl config option, default 3600.
|
||
|
|
||
|
git-svn-id: http://unbound.nlnetlabs.nl/svn/trunk@3431 be551aaa-1e26-0410-a405-d3ace91eadb9
|
||
|
Signed-off-by: Tomas Hozza <thozza@redhat.com>
|
||
|
---
|
||
|
doc/example.conf.in | 3 +++
|
||
|
doc/unbound-control.8.in | 3 ++-
|
||
|
doc/unbound.conf.5.in | 4 ++++
|
||
|
testcode/unitmsgparse.c | 3 +++
|
||
|
testdata/iter_domain_sale.rpl | 3 ++-
|
||
|
testdata/iter_domain_sale_nschange.rpl | 6 ++++--
|
||
|
util/config_file.c | 5 +++++
|
||
|
util/config_file.h | 2 ++
|
||
|
util/configlexer.lex | 1 +
|
||
|
util/configparser.y | 12 +++++++++++-
|
||
|
util/data/msgparse.h | 2 ++
|
||
|
util/data/msgreply.c | 29 ++++++++++++++++++++++++++---
|
||
|
12 files changed, 65 insertions(+), 8 deletions(-)
|
||
|
|
||
|
diff --git a/doc/example.conf.in b/doc/example.conf.in
|
||
|
index 60ed5c8..31b965c 100644
|
||
|
--- a/doc/example.conf.in
|
||
|
+++ b/doc/example.conf.in
|
||
|
@@ -135,6 +135,9 @@ server:
|
||
|
# cache. Items are not cached for longer. In seconds.
|
||
|
# cache-max-ttl: 86400
|
||
|
|
||
|
+ # the time to live (TTL) value cap for negative responses in the cache
|
||
|
+ # cache-max-negative-ttl: 3600
|
||
|
+
|
||
|
# the time to live (TTL) value for cached roundtrip times, lameness and
|
||
|
# EDNS version information for hosts. In seconds.
|
||
|
# infra-host-ttl: 900
|
||
|
diff --git a/doc/unbound-control.8.in b/doc/unbound-control.8.in
|
||
|
index f6eae24..749a9fe 100644
|
||
|
--- a/doc/unbound-control.8.in
|
||
|
+++ b/doc/unbound-control.8.in
|
||
|
@@ -177,7 +177,8 @@ harden\-glue, harden\-dnssec\-stripped, harden\-below\-nxdomain,
|
||
|
harden\-referral\-path, prefetch, prefetch\-key, log\-queries,
|
||
|
hide\-identity, hide\-version, identity, version, val\-log\-level,
|
||
|
val\-log\-squelch, ignore\-cd\-flag, add\-holddown, del\-holddown,
|
||
|
-keep\-missing, tcp\-upstream, ssl\-upstream, max\-udp\-size.
|
||
|
+keep\-missing, tcp\-upstream, ssl\-upstream, max\-udp\-size,
|
||
|
+cache\-max\-ttl, cache\-min\-ttl, cache\-max\-negative\-ttl.
|
||
|
.TP
|
||
|
.B get_option \fIopt
|
||
|
Get the value of the option. Give the option name without a trailing ':'.
|
||
|
diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in
|
||
|
index 9b088f3..5856ae7 100644
|
||
|
--- a/doc/unbound.conf.5.in
|
||
|
+++ b/doc/unbound.conf.5.in
|
||
|
@@ -290,6 +290,10 @@ Zero makes sure the data in the cache is as the domain owner intended,
|
||
|
higher values, especially more than an hour or so, can lead to trouble as
|
||
|
the data in the cache does not match up with the actual data any more.
|
||
|
.TP
|
||
|
+.B cache\-max\-negative\-ttl: \fI<seconds>
|
||
|
+Time to live maximum for negative responses, these have a SOA in the
|
||
|
+authority section that is limited in time. Default is 3600.
|
||
|
+.TP
|
||
|
.B infra\-host\-ttl: \fI<seconds>
|
||
|
Time to live for entries in the host cache. The host cache contains
|
||
|
roundtrip timing, lameness and EDNS support information. Default is 900.
|
||
|
diff --git a/testcode/unitmsgparse.c b/testcode/unitmsgparse.c
|
||
|
index b33a240..d3d9359 100644
|
||
|
--- a/testcode/unitmsgparse.c
|
||
|
+++ b/testcode/unitmsgparse.c
|
||
|
@@ -497,9 +497,11 @@ testfromdrillfile(sldns_buffer* pkt, struct alloc_cache* alloc,
|
||
|
|
||
|
void msgparse_test(void)
|
||
|
{
|
||
|
+ time_t origttl = MAX_NEG_TTL;
|
||
|
sldns_buffer* pkt = sldns_buffer_new(65553);
|
||
|
sldns_buffer* out = sldns_buffer_new(65553);
|
||
|
struct alloc_cache super_a, alloc;
|
||
|
+ MAX_NEG_TTL = 86400;
|
||
|
/* init */
|
||
|
alloc_init(&super_a, NULL, 0);
|
||
|
alloc_init(&alloc, &super_a, 2);
|
||
|
@@ -536,4 +538,5 @@ void msgparse_test(void)
|
||
|
alloc_clear(&super_a);
|
||
|
sldns_buffer_free(pkt);
|
||
|
sldns_buffer_free(out);
|
||
|
+ MAX_NEG_TTL = origttl;
|
||
|
}
|
||
|
diff --git a/testdata/iter_domain_sale.rpl b/testdata/iter_domain_sale.rpl
|
||
|
index 724b51d..ff61278 100644
|
||
|
--- a/testdata/iter_domain_sale.rpl
|
||
|
+++ b/testdata/iter_domain_sale.rpl
|
||
|
@@ -238,7 +238,8 @@ SECTION QUESTION
|
||
|
nx1.example.com. IN A
|
||
|
SECTION ANSWER
|
||
|
SECTION AUTHORITY
|
||
|
-example.com. 3600 IN SOA a. b. 1 2 3 4 5
|
||
|
+; at TTL 5 because TTL is capped at min-ttl of 5 in rdata of SOA
|
||
|
+example.com. 5 IN SOA a. b. 1 2 3 4 5
|
||
|
example.com. 1800 IN NS ns.example.com.
|
||
|
SECTION ADDITIONAL
|
||
|
ns.example.com. 1800 IN A 1.2.3.4
|
||
|
diff --git a/testdata/iter_domain_sale_nschange.rpl b/testdata/iter_domain_sale_nschange.rpl
|
||
|
index a7d9f11..bc396f6 100644
|
||
|
--- a/testdata/iter_domain_sale_nschange.rpl
|
||
|
+++ b/testdata/iter_domain_sale_nschange.rpl
|
||
|
@@ -285,7 +285,8 @@ SECTION QUESTION
|
||
|
nx1.example.com. IN A
|
||
|
SECTION ANSWER
|
||
|
SECTION AUTHORITY
|
||
|
-example.com. 3600 IN SOA a. b. 1 2 3 4 5
|
||
|
+; at TTL 5 because TTL capped at ttl of minttl in rdata of SOA.
|
||
|
+example.com. 5 IN SOA a. b. 1 2 3 4 5
|
||
|
example.com. 3600 IN NS nsb.example.com.
|
||
|
SECTION ADDITIONAL
|
||
|
nsb.example.com. 3600 IN A 1.2.3.4
|
||
|
@@ -306,7 +307,8 @@ SECTION QUESTION
|
||
|
nx1.example.com. IN A
|
||
|
SECTION ANSWER
|
||
|
SECTION AUTHORITY
|
||
|
-example.com. 3600 IN SOA a. b. 1 2 3 4 5
|
||
|
+; at TTL 5 because TTL capped at ttl of minttl in rdata of SOA.
|
||
|
+example.com. 5 IN SOA a. b. 1 2 3 4 5
|
||
|
example.com. 1800 IN NS nsb.example.com.
|
||
|
SECTION ADDITIONAL
|
||
|
nsb.example.com. 3600 IN A 1.2.3.4
|
||
|
diff --git a/util/config_file.c b/util/config_file.c
|
||
|
index 5c4e897..ca29a02 100644
|
||
|
--- a/util/config_file.c
|
||
|
+++ b/util/config_file.c
|
||
|
@@ -131,6 +131,7 @@ config_create(void)
|
||
|
cfg->bogus_ttl = 60;
|
||
|
cfg->min_ttl = 0;
|
||
|
cfg->max_ttl = 3600 * 24;
|
||
|
+ cfg->max_negative_ttl = 3600;
|
||
|
cfg->prefetch = 0;
|
||
|
cfg->prefetch_key = 0;
|
||
|
cfg->infra_cache_slabs = 4;
|
||
|
@@ -378,6 +379,8 @@ int config_set_option(struct config_file* cfg, const char* opt,
|
||
|
else S_YNO("prefetch-key:", prefetch_key)
|
||
|
else if(strcmp(opt, "cache-max-ttl:") == 0)
|
||
|
{ IS_NUMBER_OR_ZERO; cfg->max_ttl = atoi(val); MAX_TTL=(time_t)cfg->max_ttl;}
|
||
|
+ else if(strcmp(opt, "cache-max-negative-ttl:") == 0)
|
||
|
+ { IS_NUMBER_OR_ZERO; cfg->max_negative_ttl = atoi(val); MAX_NEG_TTL=(time_t)cfg->max_negative_ttl;}
|
||
|
else if(strcmp(opt, "cache-min-ttl:") == 0)
|
||
|
{ IS_NUMBER_OR_ZERO; cfg->min_ttl = atoi(val); MIN_TTL=(time_t)cfg->min_ttl;}
|
||
|
else if(strcmp(opt, "infra-cache-min-rtt:") == 0) {
|
||
|
@@ -629,6 +632,7 @@ config_get_option(struct config_file* cfg, const char* opt,
|
||
|
else O_YNO(opt, "prefetch-key", prefetch_key)
|
||
|
else O_YNO(opt, "prefetch", prefetch)
|
||
|
else O_DEC(opt, "cache-max-ttl", max_ttl)
|
||
|
+ else O_DEC(opt, "cache-max-negative-ttl", max_negative_ttl)
|
||
|
else O_DEC(opt, "cache-min-ttl", min_ttl)
|
||
|
else O_DEC(opt, "infra-host-ttl", host_ttl)
|
||
|
else O_DEC(opt, "infra-cache-slabs", infra_cache_slabs)
|
||
|
@@ -1198,6 +1202,7 @@ config_apply(struct config_file* config)
|
||
|
{
|
||
|
MAX_TTL = (time_t)config->max_ttl;
|
||
|
MIN_TTL = (time_t)config->min_ttl;
|
||
|
+ MAX_NEG_TTL = (time_t)config->max_negative_ttl;
|
||
|
RTT_MIN_TIMEOUT = config->infra_cache_min_rtt;
|
||
|
EDNS_ADVERTISED_SIZE = (uint16_t)config->edns_buffer_size;
|
||
|
MINIMAL_RESPONSES = config->minimal_responses;
|
||
|
diff --git a/util/config_file.h b/util/config_file.h
|
||
|
index ca512d7..a5cb19b 100644
|
||
|
--- a/util/config_file.h
|
||
|
+++ b/util/config_file.h
|
||
|
@@ -185,6 +185,8 @@ struct config_file {
|
||
|
int max_ttl;
|
||
|
/** the number of seconds minimum TTL used for RRsets and messages */
|
||
|
int min_ttl;
|
||
|
+ /** the number of seconds maximal negative TTL for SOA in auth */
|
||
|
+ int max_negative_ttl;
|
||
|
/** if prefetching of messages should be performed. */
|
||
|
int prefetch;
|
||
|
/** if prefetching of DNSKEYs should be performed. */
|
||
|
diff --git a/util/configlexer.lex b/util/configlexer.lex
|
||
|
index dbde811..1045320 100644
|
||
|
--- a/util/configlexer.lex
|
||
|
+++ b/util/configlexer.lex
|
||
|
@@ -239,6 +239,7 @@ msg-cache-slabs{COLON} { YDVAR(1, VAR_MSG_CACHE_SLABS) }
|
||
|
rrset-cache-size{COLON} { YDVAR(1, VAR_RRSET_CACHE_SIZE) }
|
||
|
rrset-cache-slabs{COLON} { YDVAR(1, VAR_RRSET_CACHE_SLABS) }
|
||
|
cache-max-ttl{COLON} { YDVAR(1, VAR_CACHE_MAX_TTL) }
|
||
|
+cache-max-negative-ttl{COLON} { YDVAR(1, VAR_CACHE_MAX_NEGATIVE_TTL) }
|
||
|
cache-min-ttl{COLON} { YDVAR(1, VAR_CACHE_MIN_TTL) }
|
||
|
infra-host-ttl{COLON} { YDVAR(1, VAR_INFRA_HOST_TTL) }
|
||
|
infra-lame-ttl{COLON} { YDVAR(1, VAR_INFRA_LAME_TTL) }
|
||
|
diff --git a/util/configparser.y b/util/configparser.y
|
||
|
index 396ea3c..825927a 100644
|
||
|
--- a/util/configparser.y
|
||
|
+++ b/util/configparser.y
|
||
|
@@ -118,6 +118,7 @@ extern struct config_parser_state* cfg_parser;
|
||
|
%token VAR_DNSTAP_LOG_CLIENT_RESPONSE_MESSAGES
|
||
|
%token VAR_DNSTAP_LOG_FORWARDER_QUERY_MESSAGES
|
||
|
%token VAR_DNSTAP_LOG_FORWARDER_RESPONSE_MESSAGES
|
||
|
+%token VAR_CACHE_MAX_NEGATIVE_TTL
|
||
|
|
||
|
%%
|
||
|
toplevelvars: /* empty */ | toplevelvars toplevelvar ;
|
||
|
@@ -177,7 +178,7 @@ content_server: server_num_threads | server_verbosity | server_port |
|
||
|
server_minimal_responses | server_rrset_roundrobin | server_max_udp_size |
|
||
|
server_so_reuseport | server_delay_close | server_unblock_lan_zones |
|
||
|
server_dns64_prefix | server_dns64_synthall |
|
||
|
- server_infra_cache_min_rtt
|
||
|
+ server_infra_cache_min_rtt | server_cache_max_negative_ttl
|
||
|
;
|
||
|
stubstart: VAR_STUB_ZONE
|
||
|
{
|
||
|
@@ -991,6 +992,15 @@ server_cache_max_ttl: VAR_CACHE_MAX_TTL STRING_ARG
|
||
|
free($2);
|
||
|
}
|
||
|
;
|
||
|
+server_cache_max_negative_ttl: VAR_CACHE_MAX_NEGATIVE_TTL STRING_ARG
|
||
|
+ {
|
||
|
+ OUTYY(("P(server_cache_max_negative_ttl:%s)\n", $2));
|
||
|
+ if(atoi($2) == 0 && strcmp($2, "0") != 0)
|
||
|
+ yyerror("number expected");
|
||
|
+ else cfg_parser->cfg->max_negative_ttl = atoi($2);
|
||
|
+ free($2);
|
||
|
+ }
|
||
|
+ ;
|
||
|
server_cache_min_ttl: VAR_CACHE_MIN_TTL STRING_ARG
|
||
|
{
|
||
|
OUTYY(("P(server_cache_min_ttl:%s)\n", $2));
|
||
|
diff --git a/util/data/msgparse.h b/util/data/msgparse.h
|
||
|
index 221a45a..549cc2d 100644
|
||
|
--- a/util/data/msgparse.h
|
||
|
+++ b/util/data/msgparse.h
|
||
|
@@ -76,6 +76,8 @@ struct regional;
|
||
|
extern time_t MAX_TTL;
|
||
|
/** Minimum TTL that is allowed. */
|
||
|
extern time_t MIN_TTL;
|
||
|
+/** Maximum Negative TTL that is allowed */
|
||
|
+extern time_t MAX_NEG_TTL;
|
||
|
/** Negative cache time (for entries without any RRs.) */
|
||
|
#define NORR_TTL 5 /* seconds */
|
||
|
|
||
|
diff --git a/util/data/msgreply.c b/util/data/msgreply.c
|
||
|
index 68bcfd0..d197ad7 100644
|
||
|
--- a/util/data/msgreply.c
|
||
|
+++ b/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
|
||
|
@@ -152,10 +154,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;
|
||
|
@@ -164,6 +179,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)
|
||
|
@@ -253,7 +276,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;
|
||
|
}
|
||
|
@@ -264,7 +287,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;
|
||
|
}
|
||
|
--
|
||
|
2.4.3
|
||
|
|