]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/resolve/resolved-resolv-conf.c
resolved: automatically forget all learnt DNS server information when the network...
[thirdparty/systemd.git] / src / resolve / resolved-resolv-conf.c
index ae17aef3ab78936cc404691fd12a14fd2b7ee45a..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"
@@ -60,7 +61,7 @@ int manager_read_resolv_conf(Manager *m) {
                 return 0;
 
         /* Is it symlinked to our own file? */
-        if (stat("/run/systemd/resolve/resolv.conf", &own) >= 0 &&
+        if (stat(PRIVATE_RESOLV_CONF, &own) >= 0 &&
             st.st_dev == own.st_dev &&
             st.st_ino == own.st_ino)
                 return 0;
@@ -87,7 +88,7 @@ int manager_read_resolv_conf(Manager *m) {
                 char *l;
 
                 l = strstrip(line);
-                if (*l == '#' || *l == ';')
+                if (IN_SET(*l, '#', ';'))
                         continue;
 
                 a = first_word(l, "nameserver");
@@ -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:
@@ -154,8 +160,18 @@ static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) {
                 return;
         }
 
+        /* Check if the DNS server is limited to particular domains;
+         * resolv.conf does not have a syntax to express that, so it must not
+         * appear as a global name server to avoid routing unrelated domains to
+         * it (which is a privacy violation, will most probably fail anyway,
+         * and adds unnecessary load) */
+        if (dns_server_limited_domains(s)) {
+                log_debug("DNS server %s has route-only domains, not using as global name server", dns_server_string(s));
+                return;
+        }
+
         if (*count == MAXNS)
-                fputs("# Too many DNS servers configured, the following entries may be ignored.\n", f);
+                fputs_unlocked("# Too many DNS servers configured, the following entries may be ignored.\n", f);
         (*count)++;
 
         fprintf(f, "nameserver %s\n", dns_server_string(s));
@@ -171,36 +187,39 @@ static void write_resolv_conf_search(
         assert(domains);
         assert(f);
 
-        fputs("search", f);
+        fputs_unlocked("search", f);
 
         ORDERED_SET_FOREACH(domain, domains, i) {
                 if (++count > MAXDNSRCH) {
-                        fputs("\n# Too many search domains configured, remaining ones ignored.", f);
+                        fputs_unlocked("\n# Too many search domains configured, remaining ones ignored.", f);
                         break;
                 }
                 length += strlen(domain) + 1;
                 if (length > 256) {
-                        fputs("\n# Total length of all search domains is too long, remaining ones ignored.", f);
+                        fputs_unlocked("\n# Total length of all search domains is too long, remaining ones ignored.", f);
                         break;
                 }
-                fputc(' ', f);
-                fputs(domain, f);
+                fputc_unlocked(' ', f);
+                fputs_unlocked(domain, f);
         }
 
-        fputs("\n", f);
+        fputs_unlocked("\n", f);
 }
 
 static int write_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet *domains) {
         Iterator i;
 
-        fputs("# This file is managed by systemd-resolved(8). Do not edit.\n#\n"
-              "# Third party programs must not access this file directly, but\n"
-              "# only through the symlink at /etc/resolv.conf. To manage\n"
-              "# resolv.conf(5) in a different way, replace the symlink by a\n"
-              "# static file or a different symlink.\n\n", f);
+        fputs_unlocked("# This file is managed by man:systemd-resolved(8). Do not edit.\n#\n"
+                       "# This is a dynamic resolv.conf file for connecting local clients directly to\n"
+                       "# all known DNS servers.\n#\n"
+                       "# Third party programs must not access this file directly, but only through the\n"
+                       "# symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a different way,\n"
+                       "# replace this symlink by a static file or a different symlink.\n#\n"
+                       "# See man:systemd-resolved.service(8) for details about the supported modes of\n"
+                       "# operation for /etc/resolv.conf.\n\n", f);
 
         if (ordered_set_isempty(dns))
-                fputs("# No DNS servers known.\n", f);
+                fputs_unlocked("# No DNS servers known.\n", f);
         else {
                 unsigned count = 0;
                 DnsServer *s;
@@ -232,7 +251,7 @@ int manager_write_resolv_conf(Manager *m) {
         if (r < 0)
                 return log_warning_errno(r, "Failed to compile list of DNS servers: %m");
 
-        r = manager_compile_search_domains(m, &domains);
+        r = manager_compile_search_domains(m, &domains, false);
         if (r < 0)
                 return log_warning_errno(r, "Failed to compile list of search domains: %m");