]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: automatically forget all learnt DNS server information when the network...
authorLennart Poettering <lennart@poettering.net>
Fri, 29 Sep 2017 19:18:29 +0000 (21:18 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 5 Oct 2017 14:22:22 +0000 (16:22 +0200)
When the network configuration changes we should relearn everything
there is to know about the configured DNS servers, because we might talk
to the same addresses, but there might be different servers behind them.

src/resolve/resolved-dns-server.c
src/resolve/resolved-dns-server.h
src/resolve/resolved-link.c
src/resolve/resolved-link.h
src/resolve/resolved-manager.c
src/resolve/resolved-manager.h
src/resolve/resolved-resolv-conf.c

index b3d37525f475688863e6cada63af436ebc9a4631..f0822d1f72ca6b7a0c12606bbe53f7f033f0dfd6 100644 (file)
@@ -70,15 +70,12 @@ int dns_server_new(
 
         s->n_ref = 1;
         s->manager = m;
-        s->verified_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID;
-        s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_BEST;
-        s->features_grace_period_usec = DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC;
-        s->received_udp_packet_max = DNS_PACKET_UNICAST_SIZE_MAX;
         s->type = type;
         s->family = family;
         s->address = *in_addr;
         s->ifindex = ifindex;
-        s->resend_timeout = DNS_TIMEOUT_MIN_USEC;
+
+        dns_server_reset_features(s);
 
         switch (type) {
 
@@ -828,6 +825,34 @@ void dns_server_flush_cache(DnsServer *s) {
         dns_cache_flush(&scope->cache);
 }
 
+void dns_server_reset_features(DnsServer *s) {
+        assert(s);
+
+        s->max_rtt = 0;
+        s->resend_timeout = DNS_TIMEOUT_MIN_USEC;
+
+        s->verified_feature_level = _DNS_SERVER_FEATURE_LEVEL_INVALID;
+        s->possible_feature_level = DNS_SERVER_FEATURE_LEVEL_BEST;
+
+        s->received_udp_packet_max = DNS_PACKET_UNICAST_SIZE_MAX;
+
+        s->packet_bad_opt = false;
+        s->packet_rrsig_missing = false;
+
+        s->features_grace_period_usec = DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC;
+
+        s->warned_downgrade = false;
+
+        dns_server_reset_counters(s);
+}
+
+void dns_server_reset_features_all(DnsServer *s) {
+        DnsServer *i;
+
+        LIST_FOREACH(servers, i, s)
+                dns_server_reset_features(i);
+}
+
 static const char* const dns_server_type_table[_DNS_SERVER_TYPE_MAX] = {
         [DNS_SERVER_SYSTEM] = "system",
         [DNS_SERVER_FALLBACK] = "fallback",
index bc95d53c6a81aa1f8c3735694cbe736c655ad57c..a5a82f7b7605d1cacf9e2c9eacca07501bf8f863 100644 (file)
@@ -151,3 +151,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DnsServer*, dns_server_unref);
 extern const struct hash_ops dns_server_hash_ops;
 
 void dns_server_flush_cache(DnsServer *s);
+
+void dns_server_reset_features(DnsServer *s);
+void dns_server_reset_features_all(DnsServer *s);
index 21fd8465e6d6b50194e4f83a8bfe240e0ce095be..3d26831b064c57bb716b9b29d55a7314f5ab98b7 100644 (file)
@@ -111,13 +111,30 @@ Link *link_free(Link *l) {
 }
 
 void link_allocate_scopes(Link *l) {
+        bool unicast_relevant;
         int r;
 
         assert(l);
 
-        if (link_relevant(l, AF_UNSPEC, false) &&
-            l->dns_servers) {
+        /* If a link that used to be relevant is no longer, or a link that did not use to be relevant now becomes
+         * relevant, let's reinit the learnt global DNS server information, since we might talk to different servers
+         * now, even if they have the same addresses as before. */
+
+        unicast_relevant = link_relevant(l, AF_UNSPEC, false);
+        if (unicast_relevant != l->unicast_relevant) {
+                l->unicast_relevant = unicast_relevant;
+
+                dns_server_reset_features_all(l->manager->fallback_dns_servers);
+                dns_server_reset_features_all(l->manager->dns_servers);
+        }
+
+        /* And now, allocate all scopes that makes sense now if we didn't have them yet, and drop those which we don't
+         * need anymore */
+
+        if (unicast_relevant && l->dns_servers) {
                 if (!l->unicast_scope) {
+                        dns_server_reset_features_all(l->dns_servers);
+
                         r = dns_scope_new(l->manager, &l->unicast_scope, l, DNS_PROTOCOL_DNS, AF_UNSPEC);
                         if (r < 0)
                                 log_warning_errno(r, "Failed to allocate DNS scope: %m");
index 55a56b79067d6167bc6c358959fec279a4de9955..c20b8b6d2931bbfd02ee56759f037d6363ad5cb3 100644 (file)
@@ -88,6 +88,8 @@ struct Link {
 
         bool loaded;
         char *state_file;
+
+        bool unicast_relevant;
 };
 
 int link_new(Manager *m, Link **ret, int ifindex);
index 58fe572d3b9969c7bbfb2fa68c6d05a6498b69da..3765d74cee3f67b179341896d25daaf274689da1 100644 (file)
@@ -1396,6 +1396,19 @@ void manager_flush_caches(Manager *m) {
         log_info("Flushed all caches.");
 }
 
+void manager_reset_server_features(Manager *m) {
+        Iterator i;
+        Link *l;
+
+        dns_server_reset_features_all(m->dns_servers);
+        dns_server_reset_features_all(m->fallback_dns_servers);
+
+        HASHMAP_FOREACH(l, m->links, i)
+                dns_server_reset_features_all(l->dns_servers);
+
+        log_info("Resetting learnt feature levels on all servers.");
+}
+
 void manager_cleanup_saved_user(Manager *m) {
         _cleanup_closedir_ DIR *d = NULL;
         struct dirent *de;
index 97c52b77292e6115093a12b1d0188991a1980d2e..bb45ecc1d60979c5921e1952722a5fde75f8acb4 100644 (file)
@@ -184,5 +184,6 @@ void manager_dnssec_verdict(Manager *m, DnssecVerdict verdict, const DnsResource
 bool manager_routable(Manager *m, int family);
 
 void manager_flush_caches(Manager *m);
+void manager_reset_server_features(Manager *m);
 
 void manager_cleanup_saved_user(Manager *m);
index 2af77b34074ad2c753e7b00eb925a2e3b21e80a6..e3d6a3340934a7ce63e4f5b48241f00477d2e2fc 100644 (file)
@@ -26,6 +26,7 @@
 #include "fileio.h"
 #include "ordered-set.h"
 #include "resolved-conf.h"
+#include "resolved-dns-server.h"
 #include "resolved-resolv-conf.h"
 #include "string-util.h"
 #include "strv.h"
@@ -136,6 +137,11 @@ int manager_read_resolv_conf(Manager *m) {
         if (m->unicast_scope)
                 dns_cache_flush(&m->unicast_scope->cache);
 
+        /* If /etc/resolv.conf changed, make sure to forget everything we learned about the DNS servers. After all we
+         * might now talk to a very different DNS server that just happens to have the same IP address as an old one
+         * (think 192.168.1.1). */
+        dns_server_reset_features_all(m->dns_servers);
+
         return 0;
 
 clear: