diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c index c060ccd714..6afc193f69 100644 --- a/src/resolve/resolved-resolv-conf.c +++ b/src/resolve/resolved-resolv-conf.c @@ -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" @@ -27,41 +28,30 @@ #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... */