]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: switch cache option to a tri-state option (systemd#5552). 13047/head
authorJorge Niedbalski <jnr@metaklass.org>
Fri, 12 Jul 2019 19:34:24 +0000 (15:34 -0400)
committerJorge Niedbalski <jnr@metaklass.org>
Wed, 17 Jul 2019 14:42:53 +0000 (10:42 -0400)
Change the resolved.conf Cache option to a tri-state "no, no-negative, yes" values.

If a lookup returns SERVFAIL systemd-resolved will cache the result for 30s (See 201d995),
however, there are several use cases on which this condition is not acceptable (See systemd#5552 comments)
and the only workaround would be to disable cache entirely or flush it , which isn't optimal.

This change adds the 'no-negative' option when set it avoids putting in cache
negative answers but still works the same heuristics for positive answers.

Signed-off-by: Jorge Niedbalski <jnr@metaklass.org>
NEWS
man/resolved.conf.xml
src/resolve/resolved-dns-cache.c
src/resolve/resolved-dns-cache.h
src/resolve/resolved-dns-transaction.c
src/resolve/resolved-gperf.gperf
src/resolve/resolved-manager.c
src/resolve/resolved-manager.h
src/resolve/resolved-mdns.c
src/shared/resolve-util.c
src/shared/resolve-util.h

diff --git a/NEWS b/NEWS
index 18fac477fce7f608d178feb168ed242e6beb3850..8aa40f7ddcfaf67cd7f17f2aef189b83bb496265 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -178,6 +178,13 @@ CHANGES WITH 243 in spe:
 
         * systemd-resolved gained support for a new 'strict' DNS-over-TLS mode.
 
+        * systemd-resolved "Cache=" configuration option in resolved.conf has been extended
+          to also accept the 'no-negative' value. Previously,
+          only a boolean option was allowed (yes/no), having yes as the default.
+          If this option is set to 'no-negative', negative answers are skipped
+          from being cached while keeping the same cache heuristics for positive answers.
+          The default remains as "yes" (i. e. caching is enabled).
+
         * The predictable naming scheme for network devices now supports
           generating predictable names for "netdevsim" devices.
 
index a647a4ace7786018a98ac5a74101acef3efbf8b7..213be1d7b2c72c43e85d86ecdf9bababb1384943 100644 (file)
 
       <varlistentry>
         <term><varname>Cache=</varname></term>
-        <listitem><para>Takes a boolean argument. If <literal>yes</literal> (the default), resolving a domain name
+        <listitem><para>Takes a boolean or <literal>no-negative</literal> as argument. If <literal>yes</literal> (the default), resolving a domain name
         which already got queried earlier will return the previous result as long as it is still valid, and thus does
         not result in a new network request. Be aware that turning off caching comes at a performance penalty, which
         is particularly high when DNSSEC is used.</para>
+        If <literal>no-negative</literal>, only positive answers are cached.
 
         <para>Note that caching is turned off implicitly if the configured DNS server is on a host-local IP address
         (such as 127.0.0.1 or ::1), in order to avoid duplicate local caching.</para></listitem>
index 524d5cdb5316210dc3e309f75cfb84add062f13a..946889a83444f053943a88782f713e1f93ffebb3 100644 (file)
@@ -621,6 +621,7 @@ static bool rr_eligible(DnsResourceRecord *rr) {
 
 int dns_cache_put(
                 DnsCache *c,
+                DnsCacheMode cache_mode,
                 DnsResourceKey *key,
                 int rcode,
                 DnsAnswer *answer,
@@ -728,6 +729,13 @@ int dns_cache_put(
                         return 0;
         }
 
+        if (cache_mode == DNS_CACHE_MODE_NO_NEGATIVE) {
+                char key_str[DNS_RESOURCE_KEY_STRING_MAX];
+                log_debug("Not caching negative entry for: %s, cache mode set to no-negative",
+                        dns_resource_key_to_string(key, key_str, sizeof key_str));
+                return 0;
+        }
+
         r = dns_cache_put_negative(
                         c,
                         key,
index 48a3bde98b1db9492cb3c57c3a29908b509b978f..afd7d45db6617442be2ac2fb406e51c480052b33 100644 (file)
@@ -4,6 +4,7 @@
 #include "hashmap.h"
 #include "list.h"
 #include "prioq.h"
+#include "resolve-util.h"
 #include "time-util.h"
 
 typedef struct DnsCache {
@@ -21,7 +22,7 @@ typedef struct DnsCache {
 void dns_cache_flush(DnsCache *c);
 void dns_cache_prune(DnsCache *c);
 
-int dns_cache_put(DnsCache *c, DnsResourceKey *key, int rcode, DnsAnswer *answer, bool authenticated, uint32_t nsec_ttl, usec_t timestamp, int owner_family, const union in_addr_union *owner_address);
+int dns_cache_put(DnsCache *c, DnsCacheMode cache_mode, DnsResourceKey *key, int rcode, DnsAnswer *answer, bool authenticated, uint32_t nsec_ttl, usec_t timestamp, int owner_family, const union in_addr_union *owner_address);
 int dns_cache_lookup(DnsCache *c, DnsResourceKey *key, bool clamp_ttl, int *rcode, DnsAnswer **answer, bool *authenticated);
 
 int dns_cache_check_conflicts(DnsCache *cache, DnsResourceRecord *rr, int owner_family, const union in_addr_union *owner_address);
index deb46fae7a19a6262b4b22c41dcb31f4304acc62..262f63cae3c9587189959c484dd8b61e809cc3c6 100644 (file)
@@ -672,7 +672,7 @@ static void dns_transaction_cache_answer(DnsTransaction *t) {
                 return;
 
         /* Caching disabled? */
-        if (!t->scope->manager->enable_cache)
+        if (t->scope->manager->enable_cache == DNS_CACHE_MODE_NO)
                 return;
 
         /* We never cache if this packet is from the local host, under
@@ -683,6 +683,7 @@ static void dns_transaction_cache_answer(DnsTransaction *t) {
                 return;
 
         dns_cache_put(&t->scope->cache,
+                      t->scope->manager->enable_cache,
                       t->key,
                       t->answer_rcode,
                       t->answer,
index 9b9290b727eae87a7a5c30e870922898a1bd2c14..049fe9ebddafaa3aee42db68fe35ba7b50ddd758 100644 (file)
@@ -24,6 +24,6 @@ Resolve.LLMNR,           config_parse_resolve_support,        0,
 Resolve.MulticastDNS,    config_parse_resolve_support,        0,                   offsetof(Manager, mdns_support)
 Resolve.DNSSEC,          config_parse_dnssec_mode,            0,                   offsetof(Manager, dnssec_mode)
 Resolve.DNSOverTLS,      config_parse_dns_over_tls_mode,      0,                   offsetof(Manager, dns_over_tls_mode)
-Resolve.Cache,           config_parse_bool,                   0,                   offsetof(Manager, enable_cache)
+Resolve.Cache,           config_parse_dns_cache_mode,         DNS_CACHE_MODE_YES,  offsetof(Manager, enable_cache)
 Resolve.DNSStubListener, config_parse_dns_stub_listener_mode, 0,                   offsetof(Manager, dns_stub_listener_mode)
-Resolve.ReadEtcHosts,    config_parse_bool,                   0,                   offsetof(Manager, read_etc_hosts)
+Resolve.ReadEtcHosts,    config_parse_bool,                   0,                   offsetof(Manager, read_etc_hosts)
\ No newline at end of file
index fc8607f79a011902ca12664b6acc1f056716c6b0..486b7a87bec02b49c2a7e9d960ed5200f38e2b6a 100644 (file)
@@ -581,7 +581,7 @@ int manager_new(Manager **ret) {
                 .mdns_support = RESOLVE_SUPPORT_YES,
                 .dnssec_mode = DEFAULT_DNSSEC_MODE,
                 .dns_over_tls_mode = DEFAULT_DNS_OVER_TLS_MODE,
-                .enable_cache = true,
+                .enable_cache = DNS_CACHE_MODE_YES,
                 .dns_stub_listener_mode = DNS_STUB_LISTENER_YES,
                 .read_resolv_conf = true,
                 .need_builtin_fallbacks = true,
index 0f7d8ee5ee1b13bf95b43a689c38e47b122e10d1..7f7d3a6b9c6df65047c702463e4ee28ebcd47e86 100644 (file)
@@ -37,7 +37,7 @@ struct Manager {
         ResolveSupport mdns_support;
         DnssecMode dnssec_mode;
         DnsOverTlsMode dns_over_tls_mode;
-        bool enable_cache;
+        DnsCacheMode enable_cache;
         DnsStubListenerMode dns_stub_listener_mode;
 
 #if ENABLE_DNS_OVER_TLS
index 67080cb01c408923c63e4ad89d5659cdd8b70271..eba2978991fa19ac8b0d44294c886320d9817846 100644 (file)
@@ -319,7 +319,7 @@ static int on_mdns_packet(sd_event_source *s, int fd, uint32_t revents, void *us
                                 dns_transaction_process_reply(t, p);
                 }
 
-                dns_cache_put(&scope->cache, NULL, DNS_PACKET_RCODE(p), p->answer, false, (uint32_t) -1, 0, p->family, &p->sender);
+                dns_cache_put(&scope->cache, scope->manager->enable_cache, NULL, DNS_PACKET_RCODE(p), p->answer, false, (uint32_t) -1, 0, p->family, &p->sender);
 
         } else if (dns_packet_validate_query(p) > 0)  {
                 log_debug("Got mDNS query packet for id %u", DNS_PACKET_ID(p));
index 3d14410e32a7787c0ea35ffc6a4af23104a98246..615cb6d852f8290e7440684d9df0af7ca2f94919 100644 (file)
@@ -41,3 +41,12 @@ bool dns_server_address_valid(int family, const union in_addr_union *sa) {
 
         return true;
 }
+
+DEFINE_CONFIG_PARSE_ENUM(config_parse_dns_cache_mode, dns_cache_mode, DnsCacheMode, "Failed to parse DNS cache mode setting")
+
+static const char* const dns_cache_mode_table[_DNS_CACHE_MODE_MAX] = {
+        [DNS_CACHE_MODE_YES] = "yes",
+        [DNS_CACHE_MODE_NO] = "no",
+        [DNS_CACHE_MODE_NO_NEGATIVE] = "no-negative",
+};
+DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(dns_cache_mode, DnsCacheMode, DNS_CACHE_MODE_YES);
index cf097dfaa38466f4252f5b46896501c4f3ea5c94..acf1f3dade9a2d20aa275c5ca89489d424deea49 100644 (file)
@@ -8,6 +8,16 @@
 /* 127.0.0.53 in native endian */
 #define INADDR_DNS_STUB ((in_addr_t) 0x7f000035U)
 
+typedef enum DnsCacheMode DnsCacheMode;
+
+enum DnsCacheMode {
+        DNS_CACHE_MODE_NO,
+        DNS_CACHE_MODE_YES,
+        DNS_CACHE_MODE_NO_NEGATIVE,
+        _DNS_CACHE_MODE_MAX,
+        _DNS_CACHE_MODE_INVALID = 1
+};
+
 typedef enum ResolveSupport ResolveSupport;
 typedef enum DnssecMode DnssecMode;
 typedef enum DnsOverTlsMode DnsOverTlsMode;
@@ -56,6 +66,7 @@ enum DnsOverTlsMode {
 CONFIG_PARSER_PROTOTYPE(config_parse_resolve_support);
 CONFIG_PARSER_PROTOTYPE(config_parse_dnssec_mode);
 CONFIG_PARSER_PROTOTYPE(config_parse_dns_over_tls_mode);
+CONFIG_PARSER_PROTOTYPE(config_parse_dns_cache_mode);
 
 const char* resolve_support_to_string(ResolveSupport p) _const_;
 ResolveSupport resolve_support_from_string(const char *s) _pure_;
@@ -67,3 +78,6 @@ const char* dns_over_tls_mode_to_string(DnsOverTlsMode p) _const_;
 DnsOverTlsMode dns_over_tls_mode_from_string(const char *s) _pure_;
 
 bool dns_server_address_valid(int family, const union in_addr_union *sa);
+
+const char* dns_cache_mode_to_string(DnsCacheMode p) _const_;
+DnsCacheMode dns_cache_mode_from_string(const char *s) _pure_;