resolve: when the stub listener is disabled, symlink stub-resolv.conf to resolv.conf

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.
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2020-04-20 15:22:18 +02:00
parent 965228a846
commit ca8b81d923
1 changed files with 31 additions and 34 deletions

View 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"
@ -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... */