]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolve: when the stub listener is disabled, symlink stub-resolv.conf to resolv.conf 15495/head
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 20 Apr 2020 13:22:18 +0000 (15:22 +0200)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Mon, 20 Apr 2020 13:50:40 +0000 (15:50 +0200)
When the stub listener is disabled, stub-resolv.conf is useless. Instead of
warning about this, let's just make stub-resolv.conf point to the private
resolv.conf file. (The original bug report asked for "mirroring", but I think
a symlink is nicer than a copy because it is easier to see that a redirection
was made.)

Fixes #14700.

src/resolve/resolved-resolv-conf.c

index c060ccd7144741e0a2301eef69ac0d9d64a97c0b..6afc193f69c7553c420ae88c8a6897c586b5c273 100644 (file)
@@ -9,6 +9,7 @@
 #include "dns-domain.h"
 #include "fd-util.h"
 #include "fileio.h"
+#include "fs-util.h"
 #include "ordered-set.h"
 #include "resolved-conf.h"
 #include "resolved-dns-server.h"
 #define PRIVATE_STATIC_RESOLV_CONF ROOTLIBEXECDIR "/resolv.conf"
 
 int manager_check_resolv_conf(const Manager *m) {
-        const char *path;
-        struct stat st;
-        int r;
+        struct stat st, own;
 
         assert(m);
 
         /* This warns only when our stub listener is disabled and /etc/resolv.conf is a symlink to
-         * PRIVATE_STATIC_RESOLV_CONF or PRIVATE_STUB_RESOLV_CONF. */
+         * PRIVATE_STATIC_RESOLV_CONF. */
 
         if (m->dns_stub_listener_mode != DNS_STUB_LISTENER_NO)
                 return 0;
 
-        r = stat("/etc/resolv.conf", &st);
-        if (r < 0) {
+        if (stat("/etc/resolv.conf", &st) < 0) {
                 if (errno == ENOENT)
                         return 0;
 
                 return log_warning_errno(errno, "Failed to stat /etc/resolv.conf: %m");
         }
 
-        FOREACH_STRING(path,
-                       PRIVATE_STUB_RESOLV_CONF,
-                       PRIVATE_STATIC_RESOLV_CONF) {
-
-                struct stat own;
-
-                /* Is it symlinked to our own uplink file? */
-                if (stat(path, &own) >= 0 &&
-                    st.st_dev == own.st_dev &&
-                    st.st_ino == own.st_ino) {
-                        log_warning("DNSStubListener= is disabled, but /etc/resolv.conf is a symlink to %s "
-                                    "which expects DNSStubListener= to be enabled.", path);
-                        return -EOPNOTSUPP;
-                }
-        }
+        /* Is it symlinked to our own uplink file? */
+        if (stat(PRIVATE_STATIC_RESOLV_CONF, &own) >= 0 &&
+            st.st_dev == own.st_dev &&
+            st.st_ino == own.st_ino)
+                return log_warning_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+                                         "DNSStubListener= is disabled, but /etc/resolv.conf is a symlink to "
+                                         PRIVATE_STATIC_RESOLV_CONF " which expects DNSStubListener= to be enabled.");
 
         return 0;
 }
@@ -365,26 +355,33 @@ int manager_write_resolv_conf(Manager *m) {
                 goto fail;
         }
 
-        r = fopen_temporary_label(PRIVATE_STUB_RESOLV_CONF, PRIVATE_STUB_RESOLV_CONF, &f_stub, &temp_path_stub);
-        if (r < 0) {
-                log_warning_errno(r, "Failed to open new %s for writing: %m", PRIVATE_STUB_RESOLV_CONF);
-                goto fail;
-        }
+        if (m->dns_stub_listener_mode != DNS_STUB_LISTENER_NO) {
+                r = fopen_temporary_label(PRIVATE_STUB_RESOLV_CONF, PRIVATE_STUB_RESOLV_CONF, &f_stub, &temp_path_stub);
+                if (r < 0) {
+                        log_warning_errno(r, "Failed to open new %s for writing: %m", PRIVATE_STUB_RESOLV_CONF);
+                        goto fail;
+                }
 
-        (void) fchmod(fileno(f_stub), 0644);
+                (void) fchmod(fileno(f_stub), 0644);
 
-        r = write_stub_resolv_conf_contents(f_stub, dns, domains);
-        if (r < 0) {
-                log_error_errno(r, "Failed to write new %s: %m", PRIVATE_STUB_RESOLV_CONF);
-                goto fail;
+                r = write_stub_resolv_conf_contents(f_stub, dns, domains);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to write new %s: %m", PRIVATE_STUB_RESOLV_CONF);
+                        goto fail;
+                }
+
+                if (rename(temp_path_stub, PRIVATE_STUB_RESOLV_CONF) < 0)
+                        r = log_error_errno(errno, "Failed to move new %s into place: %m", PRIVATE_STUB_RESOLV_CONF);
+
+        } else {
+                r = symlink_atomic(basename(PRIVATE_UPLINK_RESOLV_CONF), PRIVATE_STUB_RESOLV_CONF);
+                if (r < 0)
+                        log_error_errno(r, "Failed to symlink %s: %m", PRIVATE_STUB_RESOLV_CONF);
         }
 
         if (rename(temp_path_uplink, PRIVATE_UPLINK_RESOLV_CONF) < 0)
                 r = log_error_errno(errno, "Failed to move new %s into place: %m", PRIVATE_UPLINK_RESOLV_CONF);
 
-        if (rename(temp_path_stub, PRIVATE_STUB_RESOLV_CONF) < 0)
-                r = log_error_errno(errno, "Failed to move new %s into place: %m", PRIVATE_STUB_RESOLV_CONF);
-
  fail:
         if (r < 0) {
                 /* Something went wrong, perform cleanup... */