diff options
Diffstat (limited to 'src/resolve/resolved-resolv-conf.c')
-rw-r--r-- | src/resolve/resolved-resolv-conf.c | 74 |
1 files changed, 62 insertions, 12 deletions
diff --git a/src/resolve/resolved-resolv-conf.c b/src/resolve/resolved-resolv-conf.c index 5a022507c9..5205071d3f 100644 --- a/src/resolve/resolved-resolv-conf.c +++ b/src/resolve/resolved-resolv-conf.c @@ -6,7 +6,6 @@ #include "alloc-util.h" #include "dns-domain.h" #include "fd-util.h" -#include "fileio-label.h" #include "fileio.h" #include "ordered-set.h" #include "resolved-conf.h" @@ -14,6 +13,7 @@ #include "resolved-resolv-conf.h" #include "string-util.h" #include "strv.h" +#include "tmpfile-util-label.h" /* A resolv.conf file containing the DNS server and domain data we learnt from uplink, i.e. the full uplink data */ #define PRIVATE_UPLINK_RESOLV_CONF "/run/systemd/resolve/resolv.conf" @@ -21,9 +21,49 @@ /* A resolv.conf file containing the domain data we learnt from uplink, but our own DNS server address. */ #define PRIVATE_STUB_RESOLV_CONF "/run/systemd/resolve/stub-resolv.conf" -/* A static resolv.conf file containing no domains, but only our own DNS sever address */ +/* A static resolv.conf file containing no domains, but only our own DNS server address */ #define PRIVATE_STATIC_RESOLV_CONF ROOTLIBEXECDIR "/resolv.conf" +int manager_check_resolv_conf(const Manager *m) { + const char *path; + struct stat st; + int r; + + 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. */ + + if (m->dns_stub_listener_mode != DNS_STUB_LISTENER_NO) + return 0; + + r = stat("/etc/resolv.conf", &st); + if (r < 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; + } + } + + return 0; +} + static bool file_is_our_own(const struct stat *st) { const char *path; @@ -49,7 +89,6 @@ static bool file_is_our_own(const struct stat *st) { int manager_read_resolv_conf(Manager *m) { _cleanup_fclose_ FILE *f = NULL; struct stat st; - char line[LINE_MAX]; unsigned n = 0; int r; @@ -97,10 +136,19 @@ int manager_read_resolv_conf(Manager *m) { dns_server_mark_all(m->dns_servers); dns_search_domain_mark_all(m->search_domains); - FOREACH_LINE(line, f, r = -errno; goto clear) { + for (;;) { + _cleanup_free_ char *line = NULL; const char *a; char *l; + r = read_line(f, LONG_LINE_MAX, &line); + if (r < 0) { + log_error_errno(r, "Failed to read /etc/resolv.conf: %m"); + goto clear; + } + if (r == 0) + break; + n++; l = strstrip(line); @@ -169,6 +217,8 @@ clear: } static void write_resolv_conf_server(DnsServer *s, FILE *f, unsigned *count) { + DnsScope *scope; + assert(s); assert(f); assert(count); @@ -178,13 +228,12 @@ 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)); + /* Check if the scope this DNS server belongs to is suitable as 'default' route for lookups; 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) */ + scope = dns_server_scope(s); + if (scope && !dns_scope_is_default_route(scope)) { + log_debug("Scope of DNS server %s has only route-only domains, not using as global name server", dns_server_string(s)); return; } @@ -273,7 +322,8 @@ static int write_stub_resolv_conf_contents(FILE *f, OrderedSet *dns, OrderedSet "# See man:systemd-resolved.service(8) for details about the supported modes of\n" "# operation for /etc/resolv.conf.\n" "\n" - "nameserver 127.0.0.53\n", f); + "nameserver 127.0.0.53\n" + "options edns0\n", f); if (!ordered_set_isempty(domains)) write_resolv_conf_search(domains, f); |