summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2017-09-29 21:18:29 +0200
committerLennart Poettering <lennart@poettering.net>2017-10-05 16:22:22 +0200
commit59c0fd0e17e485d551daa9cd26fa0cfc726085b0 (patch)
treeca2b9b72cbd258c0da43604e1a3930df12cc1f08
parent608f70e6b454020bfc8f807bd0f9d1c412d4157a (diff)
downloadsystemd-59c0fd0e17e485d551daa9cd26fa0cfc726085b0.tar.gz
resolved: automatically forget all learnt DNS server information when the network configuration changes
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.
-rw-r--r--src/resolve/resolved-dns-server.c35
-rw-r--r--src/resolve/resolved-dns-server.h3
-rw-r--r--src/resolve/resolved-link.c21
-rw-r--r--src/resolve/resolved-link.h2
-rw-r--r--src/resolve/resolved-manager.c13
-rw-r--r--src/resolve/resolved-manager.h1
-rw-r--r--src/resolve/resolved-resolv-conf.c6
7 files changed, 74 insertions, 7 deletions
diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c
index b3d37525f4..f0822d1f72 100644
--- a/src/resolve/resolved-dns-server.c
+++ b/src/resolve/resolved-dns-server.c
@@ -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",
diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h
index bc95d53c6a..a5a82f7b76 100644
--- a/src/resolve/resolved-dns-server.h
+++ b/src/resolve/resolved-dns-server.h
@@ -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);
diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c
index 21fd8465e6..3d26831b06 100644
--- a/src/resolve/resolved-link.c
+++ b/src/resolve/resolved-link.c
@@ -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");
diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h
index 55a56b7906..c20b8b6d29 100644
--- a/src/resolve/resolved-link.h
+++ b/src/resolve/resolved-link.h
@@ -88,6 +88,8 @@ struct Link {
bool loaded;
char *state_file;
+
+ bool unicast_relevant;
};
int link_new(Manager *m, Link **ret, int ifindex);
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index 58fe572d3b..3765d74cee 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -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;
diff --git a/src/resolve/resolved-manager.h b/src/resolve/resolved-manager.h
index 97c52b7729..bb45ecc1d6 100644
--- a/src/resolve/resolved-manager.h
+++ b/src/resolve/resolved-manager.h
@@ -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);
diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c
index 2af77b3407..e3d6a33409 100644
--- a/src/resolve/resolved-resolv-conf.c
+++ b/src/resolve/resolved-resolv-conf.c
@@ -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: