mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2026-02-14 23:19:01 +00:00
Make max staleness of stale cache entries configurable and default to one day.
This commit is contained in:
@@ -828,11 +828,12 @@ name on successive queries, for load-balancing. This turns off that
|
|||||||
behaviour, so that the records are always returned in the order
|
behaviour, so that the records are always returned in the order
|
||||||
that they are received from upstream.
|
that they are received from upstream.
|
||||||
.TP
|
.TP
|
||||||
.B --use-stale-cache
|
.B --use-stale-cache[=<max TTL excess in s>]
|
||||||
When set, if a DNS name exists in the cache, but its time-to-live has expired, dnsmasq will return the data anyway. (It attempts to refresh the
|
When set, if a DNS name exists in the cache, but its time-to-live has expired, dnsmasq will return the data anyway. (It attempts to refresh the
|
||||||
data with an upstream query after returning the stale data.) This can improve speed and reliability. It comes at the expense
|
data with an upstream query after returning the stale data.) This can improve speed and reliability. It comes at the expense
|
||||||
of sometimes returning out-of-date data and less efficient cache utilisation, since old data cannot be flushed when its TTL expires, so the cache becomes
|
of sometimes returning out-of-date data and less efficient cache utilisation, since old data cannot be flushed when its TTL expires, so the cache becomes
|
||||||
strictly least-recently-used.
|
mostly least-recently-used. To mitigate issues caused by massively outdated DNS replies, the maximum overaging of cached records can be specified in seconds
|
||||||
|
(defaulting to not serve anything older than one day). Setting the TTL excess time to zero will serve stale cache data regardless how long it has expired.
|
||||||
.TP
|
.TP
|
||||||
.B \-0, --dns-forward-max=<queries>
|
.B \-0, --dns-forward-max=<queries>
|
||||||
Set the maximum number of concurrent DNS queries. The default value is
|
Set the maximum number of concurrent DNS queries. The default value is
|
||||||
|
|||||||
16
src/cache.c
16
src/cache.c
@@ -380,9 +380,17 @@ static int is_outdated_cname_pointer(struct crec *crecp)
|
|||||||
|
|
||||||
static int is_expired(time_t now, struct crec *crecp)
|
static int is_expired(time_t now, struct crec *crecp)
|
||||||
{
|
{
|
||||||
/* Don't dump expired entries if we're using them, cache becomes strictly LRU in that case.
|
/* Don't dump expired entries if they are within the accepted timeout range.
|
||||||
Never use expired DS or DNSKEY entries. */
|
The cache becomes approx. LRU. Never use expired DS or DNSKEY entries.
|
||||||
if (option_bool(OPT_STALE_CACHE) && !(crecp->flags & (F_DS | F_DNSKEY)))
|
Possible values for daemon->cache_max_expiry:
|
||||||
|
-1 == serve cached content regardless how long ago it expired
|
||||||
|
0 == the option is disabled, expired content isn't served
|
||||||
|
<n> == serve cached content only if it expire less than <n> seconds
|
||||||
|
ago (where n is a positive integer) */
|
||||||
|
if (daemon->cache_max_expiry != 0 &&
|
||||||
|
(daemon->cache_max_expiry == -1 ||
|
||||||
|
difftime(now, crecp->ttd) < daemon->cache_max_expiry) &&
|
||||||
|
!(crecp->flags & (F_DS | F_DNSKEY)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (crecp->flags & F_IMMORTAL)
|
if (crecp->flags & F_IMMORTAL)
|
||||||
@@ -1762,7 +1770,7 @@ void dump_cache(time_t now)
|
|||||||
daemon->cachesize, daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED], daemon->metrics[METRIC_DNS_CACHE_INSERTED]);
|
daemon->cachesize, daemon->metrics[METRIC_DNS_CACHE_LIVE_FREED], daemon->metrics[METRIC_DNS_CACHE_INSERTED]);
|
||||||
my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"),
|
my_syslog(LOG_INFO, _("queries forwarded %u, queries answered locally %u"),
|
||||||
daemon->metrics[METRIC_DNS_QUERIES_FORWARDED], daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]);
|
daemon->metrics[METRIC_DNS_QUERIES_FORWARDED], daemon->metrics[METRIC_DNS_LOCAL_ANSWERED]);
|
||||||
if (option_bool(OPT_STALE_CACHE))
|
if (daemon->cache_max_expiry != 0)
|
||||||
my_syslog(LOG_INFO, _("queries answered from stale cache %u"), daemon->metrics[METRIC_DNS_STALE_ANSWERED]);
|
my_syslog(LOG_INFO, _("queries answered from stale cache %u"), daemon->metrics[METRIC_DNS_STALE_ANSWERED]);
|
||||||
#ifdef HAVE_AUTH
|
#ifdef HAVE_AUTH
|
||||||
my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
|
my_syslog(LOG_INFO, _("queries for authoritative zones %u"), daemon->metrics[METRIC_DNS_AUTH_ANSWERED]);
|
||||||
|
|||||||
@@ -60,6 +60,7 @@
|
|||||||
#define LOOP_TEST_DOMAIN "test" /* domain for loop testing, "test" is reserved by RFC 2606 and won't therefore clash */
|
#define LOOP_TEST_DOMAIN "test" /* domain for loop testing, "test" is reserved by RFC 2606 and won't therefore clash */
|
||||||
#define LOOP_TEST_TYPE T_TXT
|
#define LOOP_TEST_TYPE T_TXT
|
||||||
#define DEFAULT_FAST_RETRY 1000 /* ms, default delay before fast retry */
|
#define DEFAULT_FAST_RETRY 1000 /* ms, default delay before fast retry */
|
||||||
|
#define STALE_CACHE_EXPIRY 86400 /* 1 day in secs, default maximum expiry time for stale cache data */
|
||||||
|
|
||||||
/* compile-time options: uncomment below to enable or do eg.
|
/* compile-time options: uncomment below to enable or do eg.
|
||||||
make COPTS=-DHAVE_BROKEN_RTC
|
make COPTS=-DHAVE_BROKEN_RTC
|
||||||
|
|||||||
@@ -280,9 +280,8 @@ struct event_desc {
|
|||||||
#define OPT_FILTER_AAAA 68
|
#define OPT_FILTER_AAAA 68
|
||||||
#define OPT_STRIP_ECS 69
|
#define OPT_STRIP_ECS 69
|
||||||
#define OPT_STRIP_MAC 70
|
#define OPT_STRIP_MAC 70
|
||||||
#define OPT_STALE_CACHE 71
|
#define OPT_NORR 71
|
||||||
#define OPT_NORR 72
|
#define OPT_LAST 72
|
||||||
#define OPT_LAST 73
|
|
||||||
|
|
||||||
#define OPTION_BITS (sizeof(unsigned int)*8)
|
#define OPTION_BITS (sizeof(unsigned int)*8)
|
||||||
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
|
#define OPTION_SIZE ( (OPT_LAST/OPTION_BITS)+((OPT_LAST%OPTION_BITS)!=0) )
|
||||||
@@ -1201,6 +1200,7 @@ extern struct daemon {
|
|||||||
unsigned long soa_sn, soa_refresh, soa_retry, soa_expiry;
|
unsigned long soa_sn, soa_refresh, soa_retry, soa_expiry;
|
||||||
u32 metrics[__METRIC_MAX];
|
u32 metrics[__METRIC_MAX];
|
||||||
int fast_retry_time, fast_retry_timeout;
|
int fast_retry_time, fast_retry_timeout;
|
||||||
|
int cache_max_expiry;
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
struct ds_config *ds;
|
struct ds_config *ds;
|
||||||
char *timestamp_file;
|
char *timestamp_file;
|
||||||
|
|||||||
22
src/option.c
22
src/option.c
@@ -373,7 +373,7 @@ static const struct myoption opts[] =
|
|||||||
{ "quiet-tftp", 0, 0, LOPT_QUIET_TFTP },
|
{ "quiet-tftp", 0, 0, LOPT_QUIET_TFTP },
|
||||||
{ "port-limit", 1, 0, LOPT_RANDPORT_LIM },
|
{ "port-limit", 1, 0, LOPT_RANDPORT_LIM },
|
||||||
{ "fast-dns-retry", 2, 0, LOPT_FAST_RETRY },
|
{ "fast-dns-retry", 2, 0, LOPT_FAST_RETRY },
|
||||||
{ "use-stale-cache", 0, 0 , LOPT_STALE_CACHE },
|
{ "use-stale-cache", 2, 0 , LOPT_STALE_CACHE },
|
||||||
{ NULL, 0, 0, 0 }
|
{ NULL, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -431,7 +431,7 @@ static struct {
|
|||||||
{ 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
|
{ 'M', ARG_DUP, "<bootp opts>", gettext_noop("Specify BOOTP options to DHCP server."), NULL },
|
||||||
{ 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
|
{ 'n', OPT_NO_POLL, NULL, gettext_noop("Do NOT poll %s file, reload only on SIGHUP."), RESOLVFILE },
|
||||||
{ 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
|
{ 'N', OPT_NO_NEG, NULL, gettext_noop("Do NOT cache failed search results."), NULL },
|
||||||
{ LOPT_STALE_CACHE, OPT_STALE_CACHE, NULL, gettext_noop("Use expired cache data for faster reply."), NULL },
|
{ LOPT_STALE_CACHE, ARG_ONE, "[=<max_expired>]", gettext_noop("Use expired cache data for faster reply."), NULL },
|
||||||
{ 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
|
{ 'o', OPT_ORDER, NULL, gettext_noop("Use nameservers strictly in the order given in %s."), RESOLVFILE },
|
||||||
{ 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
|
{ 'O', ARG_DUP, "<optspec>", gettext_noop("Specify options to be sent to DHCP clients."), NULL },
|
||||||
{ LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
|
{ LOPT_FORCE, ARG_DUP, "<optspec>", gettext_noop("DHCP option sent even if the client does not request it."), NULL},
|
||||||
@@ -5151,6 +5151,24 @@ err:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case LOPT_STALE_CACHE:
|
||||||
|
{
|
||||||
|
int max_expiry = STALE_CACHE_EXPIRY;
|
||||||
|
if (arg)
|
||||||
|
{
|
||||||
|
/* Don't accept negative TTLs here, they'd have the counter-intuitive
|
||||||
|
side-effect of evicting cache records before they expire */
|
||||||
|
if (!atoi_check(arg, &max_expiry) || max_expiry < 0)
|
||||||
|
ret_err(gen_err);
|
||||||
|
/* Store "serve expired forever" as -1 internally, the option isn't
|
||||||
|
active for daemon->cache_max_expiry == 0 */
|
||||||
|
if (max_expiry == 0)
|
||||||
|
max_expiry = -1;
|
||||||
|
}
|
||||||
|
daemon->cache_max_expiry = max_expiry;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_DNSSEC
|
#ifdef HAVE_DNSSEC
|
||||||
case LOPT_DNSSEC_STAMP: /* --dnssec-timestamp */
|
case LOPT_DNSSEC_STAMP: /* --dnssec-timestamp */
|
||||||
daemon->timestamp_file = opt_string_alloc(arg);
|
daemon->timestamp_file = opt_string_alloc(arg);
|
||||||
|
|||||||
Reference in New Issue
Block a user