summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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: